diff --git a/NASAL语言教程-完整版.pdf b/NASAL语言教程-完整版.pdf deleted file mode 100644 index e80601e..0000000 Binary files a/NASAL语言教程-完整版.pdf and /dev/null differ diff --git a/README.md b/README.md index f64a156..b825911 100644 --- a/README.md +++ b/README.md @@ -25,24 +25,8 @@ I wrote the lexer, parser and runtime(nasal virtual machine/ast-runtime virtual They found it easier for them to check errors before copying nasal-codes in nasal-console in Flightgear to test. # Lexical Analysis - -What do it's outputs look like? -> ( identifier | start ) - -> ( operator | ; ) - -> ( reserve word | print ) - -> ( operator | ( ) - -> ( string | Engine started ) - -> ( operator | ) ) - -This is what it outputs. - -And the flow chart of lexer is here: +The flow chart of lexer is here: [![nasal_lexer.png](pic/nasal_lexer.png?raw=true)](https://github.com/ValKmjolnir/Nasal-Interpreter/blob/master/pic/nasal_lexer.png) diff --git a/version3.0/lib.nas b/lib.nas similarity index 94% rename from version3.0/lib.nas rename to lib.nas index 35c7843..fa46b87 100644 --- a/version3.0/lib.nas +++ b/lib.nas @@ -1,163 +1,163 @@ -var import=func(filename) -{ - nasal_call_import(filename); - return nil; -} -var print=func(elements...) -{ - nasal_call_builtin_std_cout(elements); - return nil; -}; -var append=func(vector,elements...) -{ - nasal_call_builtin_push_back(vector,elements); - return nil; -} -var setsize=func(vector,size) -{ - nasal_call_builtin_set_size(vector,size); - return nil; -} -var system=func(str) -{ - nasal_call_builtin_system(str); - return; -} -var input=func() -{ - return nasal_call_builtin_input(); -} -var sleep=func(duration) -{ - nasal_call_builtin_sleep(duration); - return; -} -var split=func(delimeter,string) -{ - return nasal_call_builtin_split(delimeter,string); -} -var rand=func(seed=nil) -{ - return nasal_call_builtin_rand(seed); -} -var id=func(thing) -{ - return nasal_call_builtin_get_id(thing); -} -var int=func(value) -{ - return nasal_call_builtin_trans_int(value); -} -var num=func(value) -{ - return nasal_call_builtin_trans_num(value); -} -var pop=func(vector) -{ - return nasal_call_builtin_pop_back(vector); -} -var str=func(number) -{ - return nasal_call_builtin_trans_str(number); -} -var size=func(object) -{ - return nasal_call_builtin_size(object); -} -var contains=func(hash,key) -{ - return nasal_call_builtin_contains(hash,key); -} -var delete=func(hash,key) -{ - nasal_call_builtin_delete(hash,key); - return; -} -var keys=func(hash) -{ - return nasal_call_builtin_get_keys(hash); -} -var time=func(begin_time) -{ - return nasal_call_builtin_time(begin_time); -} -var die=func(str) -{ - nasal_call_builtin_die(str); - return nil; -} -var type=func(object) -{ - return nasal_call_builtin_type(object); -} - -var io= -{ - fin:func(filename) - { - return nasal_call_builtin_finput(filename); - }, - fout:func(filename,str) - { - nasal_call_builtin_foutput(filename,str); - return; - } -}; - -var bits= -{ - bitxor:func(a,b) - { - return nasal_call_builtin_xor(a,b); - }, - bitand:func(a,b) - { - return nasal_call_builtin_and(a,b); - }, - bitor:func(a,b) - { - return nasal_call_builtin_or(a,b); - }, - bitnand:func(a,b) - { - return nasal_call_builtin_nand(a,b); - }, - bitnot:func(a) - { - return nasal_call_builtin_not(a); - } -}; - -var math= -{ - e:2.7182818284590452354, - pi:3.14159265358979323846, - sin:func(x) - { - return nasal_call_builtin_sin(x); - }, - cos:func(x) - { - return nasal_call_builtin_cos(x); - }, - tan:func(x) - { - return nasal_call_builtin_tan(x); - }, - exp:func(x) - { - return nasal_call_builtin_exp(x); - }, - ln:func(x) - { - return nasal_call_builtin_cpp_math_ln(x); - }, - sqrt:func(x) - { - return nasal_call_builtin_cpp_math_sqrt(x); - }, - atan2:func(x,y) - { - return nasal_call_builtin_cpp_atan2(x,y); - }, -}; +var import=func(filename) +{ + nasal_call_import(filename); + return nil; +} +var print=func(elements...) +{ + nasal_call_builtin_std_cout(elements); + return nil; +}; +var append=func(vector,elements...) +{ + nasal_call_builtin_push_back(vector,elements); + return nil; +} +var setsize=func(vector,size) +{ + nasal_call_builtin_set_size(vector,size); + return nil; +} +var system=func(str) +{ + nasal_call_builtin_system(str); + return; +} +var input=func() +{ + return nasal_call_builtin_input(); +} +var sleep=func(duration) +{ + nasal_call_builtin_sleep(duration); + return; +} +var split=func(delimeter,string) +{ + return nasal_call_builtin_split(delimeter,string); +} +var rand=func(seed=nil) +{ + return nasal_call_builtin_rand(seed); +} +var id=func(thing) +{ + return nasal_call_builtin_get_id(thing); +} +var int=func(value) +{ + return nasal_call_builtin_trans_int(value); +} +var num=func(value) +{ + return nasal_call_builtin_trans_num(value); +} +var pop=func(vector) +{ + return nasal_call_builtin_pop_back(vector); +} +var str=func(number) +{ + return nasal_call_builtin_trans_str(number); +} +var size=func(object) +{ + return nasal_call_builtin_size(object); +} +var contains=func(hash,key) +{ + return nasal_call_builtin_contains(hash,key); +} +var delete=func(hash,key) +{ + nasal_call_builtin_delete(hash,key); + return; +} +var keys=func(hash) +{ + return nasal_call_builtin_get_keys(hash); +} +var time=func(begin_time) +{ + return nasal_call_builtin_time(begin_time); +} +var die=func(str) +{ + nasal_call_builtin_die(str); + return nil; +} +var type=func(object) +{ + return nasal_call_builtin_type(object); +} + +var io= +{ + fin:func(filename) + { + return nasal_call_builtin_finput(filename); + }, + fout:func(filename,str) + { + nasal_call_builtin_foutput(filename,str); + return; + } +}; + +var bits= +{ + bitxor:func(a,b) + { + return nasal_call_builtin_xor(a,b); + }, + bitand:func(a,b) + { + return nasal_call_builtin_and(a,b); + }, + bitor:func(a,b) + { + return nasal_call_builtin_or(a,b); + }, + bitnand:func(a,b) + { + return nasal_call_builtin_nand(a,b); + }, + bitnot:func(a) + { + return nasal_call_builtin_not(a); + } +}; + +var math= +{ + e:2.7182818284590452354, + pi:3.14159265358979323846, + sin:func(x) + { + return nasal_call_builtin_sin(x); + }, + cos:func(x) + { + return nasal_call_builtin_cos(x); + }, + tan:func(x) + { + return nasal_call_builtin_tan(x); + }, + exp:func(x) + { + return nasal_call_builtin_exp(x); + }, + ln:func(x) + { + return nasal_call_builtin_cpp_math_ln(x); + }, + sqrt:func(x) + { + return nasal_call_builtin_cpp_math_sqrt(x); + }, + atan2:func(x,y) + { + return nasal_call_builtin_cpp_atan2(x,y); + }, +}; diff --git a/version3.0/main.cpp b/main.cpp similarity index 95% rename from version3.0/main.cpp rename to main.cpp index 17974c6..d712896 100644 --- a/version3.0/main.cpp +++ b/main.cpp @@ -1,248 +1,248 @@ -#include "nasal.h" - -nasal_resource resource; -nasal_lexer lexer; -nasal_parse parse; -nasal_import preprocessor; -nasal_codegen code_generator; -std::string command; -std::string inputfile="null"; -nasal_runtime runtime; - -void help() -{ - std::cout<<">> [\"file\"] input a file name.\n"; - std::cout<<">> [clear ] clear the screen.\n"; - std::cout<<">> [del ] clear the input filename.\n"; - std::cout<<">> [rs ] print source code.\n"; - std::cout<<">> [lex ] use lexer to turn code into tokens.\n"; - std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n"; - std::cout<<">> [run ] run abstract syntax tree.\n"; - std::cout<<">> [exec ] generate byte code.\n"; - std::cout<<">> [erun ] run byte code.\n"; - std::cout<<">> [logo ] print logo of nasal .\n"; - std::cout<<">> [exit ] quit nasal interpreter.\n"; - return; -} - -void logo() -{ - std::cout<<" __ _ \n"; - std::cout<<" /\\ \\ \\__ _ ___ __ _| | \n"; - std::cout<<" / \\/ / _` / __|/ _` | | \n"; - std::cout<<" / /\\ / (_| \\__ \\ (_| | | \n"; - std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"; - return; -} - -void del_func() -{ - resource.clear(); - lexer.clear(); - parse.clear(); - inputfile="null"; - std::cout<<">> [Delete] complete.\n"; - return; -} - -void die(std::string stage,std::string filename) -{ - std::cout<<">> ["<: error(s) occurred,stop.\n"; - return; -} - -void lex_func() -{ - if(!resource.input_file(inputfile)) - { - die("resource",inputfile); - return; - } - lexer.scanner(resource.get_file()); - if(lexer.get_error()) - { - die("lexer",inputfile); - return; - } - lexer.print_token(); - return; -} - -void ast_print() -{ - if(!resource.input_file(inputfile)) - { - die("resource",inputfile); - return; - } - lexer.scanner(resource.get_file()); - if(lexer.get_error()) - { - die("lexer",inputfile); - return; - } - parse.set_toklist(lexer.get_token_list()); - parse.main_process(); - if(parse.get_error()) - { - die("parse",inputfile); - return; - } - parse.get_root().print_ast(0); - return; -} -void runtime_start() -{ - if(!resource.input_file(inputfile)) - { - die("resource",inputfile); - return; - } - lexer.scanner(resource.get_file()); - if(lexer.get_error()) - { - die("lexer",inputfile); - return; - } - parse.set_toklist(lexer.get_token_list()); - parse.main_process(); - if(parse.get_error()) - { - die("parse",inputfile); - return; - } - preprocessor.preprocessing(parse.get_root()); - if(preprocessor.get_error()) - { - die("import",inputfile); - return; - } - runtime.set_root(preprocessor.get_root()); - runtime.run(); - return; -} - -void codegen_start() -{ - if(!resource.input_file(inputfile)) - { - die("resource",inputfile); - return; - } - lexer.scanner(resource.get_file()); - if(lexer.get_error()) - { - die("lexer",inputfile); - return; - } - parse.set_toklist(lexer.get_token_list()); - parse.main_process(); - if(parse.get_error()) - { - die("parse",inputfile); - return; - } - preprocessor.preprocessing(parse.get_root()); - if(preprocessor.get_error()) - { - die("import",inputfile); - return; - } - runtime.set_root(preprocessor.get_root()); - code_generator.output_exec(inputfile+".naexec",preprocessor.get_root()); - if(code_generator.get_error()) - { - die("code",inputfile); - return; - } - return; -} - -void execution_start() -{ - code_generator.load_exec(inputfile,preprocessor.get_root()); - if(code_generator.get_error()) - { - die("code",inputfile); - return; - } - runtime.set_root(preprocessor.get_root()); - runtime.run(); - return; -} - -int main() -{ -#ifdef _WIN32 - // use chcp 65001 to use unicode io - system("chcp 65001"); - system("cls"); -#endif - logo(); -#ifdef _WIN32 - std::cout<<">> [system] Windows system.\n"; -#endif -#ifdef _linux_ - std::cout<<">> [system] Linux system.\n"; -#endif -#ifdef TARGET_OS_MAC - std::cout<<">> [system] MacOS system.\n"; -#endif - - std::cout<<">> Nasal interpreter ver 3.0 .\n"; - std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n"; - std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n"; - std::cout<<">> Input \"help\" to get help .\n"; - while(1) - { - std::cout<<">> "; - std::cin>>command; - if(command=="help") - help(); - else if(command=="clear") - { -#ifdef _WIN32 - system("cls"); -#endif -#ifdef _linux_ - system("clear"); -#endif -#ifdef TARGET_OS_MAC - system("clear"); -#endif - } - else if(command=="del") - del_func(); - else if(command=="rs") - { - if(resource.input_file(inputfile)) - resource.print_file(); - } - else if(command=="lex") - lex_func(); - else if(command=="ast") - ast_print(); - else if(command=="run") - runtime_start(); - else if(command=="exec") - codegen_start(); - else if(command=="erun") - execution_start(); - else if(command=="logo") - logo(); - else if(command=="exit") - break; - else - { - inputfile=command; - std::ifstream fin(command); - if(fin.fail()) - { - std::cout<<">> [file] cannot open file \""<> [\"file\"] input a file name.\n"; + std::cout<<">> [clear ] clear the screen.\n"; + std::cout<<">> [del ] clear the input filename.\n"; + std::cout<<">> [rs ] print source code.\n"; + std::cout<<">> [lex ] use lexer to turn code into tokens.\n"; + std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n"; + std::cout<<">> [run ] run abstract syntax tree.\n"; + std::cout<<">> [exec ] generate byte code.\n"; + std::cout<<">> [erun ] run byte code.\n"; + std::cout<<">> [logo ] print logo of nasal .\n"; + std::cout<<">> [exit ] quit nasal interpreter.\n"; + return; +} + +void logo() +{ + std::cout<<" __ _ \n"; + std::cout<<" /\\ \\ \\__ _ ___ __ _| | \n"; + std::cout<<" / \\/ / _` / __|/ _` | | \n"; + std::cout<<" / /\\ / (_| \\__ \\ (_| | | \n"; + std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"; + return; +} + +void del_func() +{ + resource.clear(); + lexer.clear(); + parse.clear(); + inputfile="null"; + std::cout<<">> [Delete] complete.\n"; + return; +} + +void die(std::string stage,std::string filename) +{ + std::cout<<">> ["<: error(s) occurred,stop.\n"; + return; +} + +void lex_func() +{ + if(!resource.input_file(inputfile)) + { + die("resource",inputfile); + return; + } + lexer.scanner(resource.get_file()); + if(lexer.get_error()) + { + die("lexer",inputfile); + return; + } + lexer.print_token(); + return; +} + +void ast_print() +{ + if(!resource.input_file(inputfile)) + { + die("resource",inputfile); + return; + } + lexer.scanner(resource.get_file()); + if(lexer.get_error()) + { + die("lexer",inputfile); + return; + } + parse.set_toklist(lexer.get_token_list()); + parse.main_process(); + if(parse.get_error()) + { + die("parse",inputfile); + return; + } + parse.get_root().print_ast(0); + return; +} +void runtime_start() +{ + if(!resource.input_file(inputfile)) + { + die("resource",inputfile); + return; + } + lexer.scanner(resource.get_file()); + if(lexer.get_error()) + { + die("lexer",inputfile); + return; + } + parse.set_toklist(lexer.get_token_list()); + parse.main_process(); + if(parse.get_error()) + { + die("parse",inputfile); + return; + } + preprocessor.preprocessing(parse.get_root()); + if(preprocessor.get_error()) + { + die("import",inputfile); + return; + } + runtime.set_root(preprocessor.get_root()); + runtime.run(); + return; +} + +void codegen_start() +{ + if(!resource.input_file(inputfile)) + { + die("resource",inputfile); + return; + } + lexer.scanner(resource.get_file()); + if(lexer.get_error()) + { + die("lexer",inputfile); + return; + } + parse.set_toklist(lexer.get_token_list()); + parse.main_process(); + if(parse.get_error()) + { + die("parse",inputfile); + return; + } + preprocessor.preprocessing(parse.get_root()); + if(preprocessor.get_error()) + { + die("import",inputfile); + return; + } + runtime.set_root(preprocessor.get_root()); + code_generator.output_exec(inputfile+".naexec",preprocessor.get_root()); + if(code_generator.get_error()) + { + die("code",inputfile); + return; + } + return; +} + +void execution_start() +{ + code_generator.load_exec(inputfile,preprocessor.get_root()); + if(code_generator.get_error()) + { + die("code",inputfile); + return; + } + runtime.set_root(preprocessor.get_root()); + runtime.run(); + return; +} + +int main() +{ +#ifdef _WIN32 + // use chcp 65001 to use unicode io + system("chcp 65001"); + system("cls"); +#endif + logo(); +#ifdef _WIN32 + std::cout<<">> [system] Windows system.\n"; +#endif +#ifdef _linux_ + std::cout<<">> [system] Linux system.\n"; +#endif +#ifdef TARGET_OS_MAC + std::cout<<">> [system] MacOS system.\n"; +#endif + + std::cout<<">> Nasal interpreter ver 3.0 .\n"; + std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n"; + std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n"; + std::cout<<">> Input \"help\" to get help .\n"; + while(1) + { + std::cout<<">> "; + std::cin>>command; + if(command=="help") + help(); + else if(command=="clear") + { +#ifdef _WIN32 + system("cls"); +#endif +#ifdef _linux_ + system("clear"); +#endif +#ifdef TARGET_OS_MAC + system("clear"); +#endif + } + else if(command=="del") + del_func(); + else if(command=="rs") + { + if(resource.input_file(inputfile)) + resource.print_file(); + } + else if(command=="lex") + lex_func(); + else if(command=="ast") + ast_print(); + else if(command=="run") + runtime_start(); + else if(command=="exec") + codegen_start(); + else if(command=="erun") + execution_start(); + else if(command=="logo") + logo(); + else if(command=="exit") + break; + else + { + inputfile=command; + std::ifstream fin(command); + if(fin.fail()) + { + std::cout<<">> [file] cannot open file \""< -#include -#include - -class abstract_syntax_tree -{ - private: - int ast_node_type; - double var_number; - std::string var_string; - std::string var_name; - std::list children; - public: - abstract_syntax_tree() - { - ast_node_type=0; - var_number=0; - var_string=""; - var_name=""; - children.clear(); - return; - } - abstract_syntax_tree(const abstract_syntax_tree& p) - { - ast_node_type=p.ast_node_type; - var_number=p.var_number; - var_string=p.var_string; - var_name=p.var_name; - children=p.children; - return; - } - abstract_syntax_tree& operator=(const abstract_syntax_tree& p) - { - ast_node_type=p.ast_node_type; - var_number=p.var_number; - var_string=p.var_string; - var_name=p.var_name; - children=p.children; - return *this; - } - void print_tree(const int n) - { - std::cout<print_tree(n+1); - } - return; - } - void set_node_type(const int type) - { - ast_node_type=type; - return; - } - void set_var_string(std::string& str) - { - var_string=str; - return; - } - void set_var_number(std::string& str) - { - if(str=="nil") - { - var_number=0; - return; - } - if((int)str.length()>2 && (str[1]=='x' || str[1]=='o')) - { - if(str[1]=='x') - { - int num=0; - int pw=1; - for(int i=(int)str.length()-1;i>1;--i) - { - if('0'<=str[i] && str[i]<='9') - num+=(str[i]-'0')*pw; - else if('a'<=str[i] && str[i]<='f') - num+=(10+str[i]-'a')*pw; - else if('A'<=str[i] && str[i]<='F') - num+=(10+str[i]-'A')*pw; - pw<<=4; - } - var_number=(double)num; - } - else - { - int num=0; - int pw=1; - for(int i=(int)str.length()-1;i>1;--i) - { - num+=(str[i]-'0')*pw; - pw<<=3; - } - var_number=(double)num; - } - return; - } - int dot_place=-1; - for(int i=0;i<(int)str.length();++i) - if(str[i]=='.') - { - dot_place=i; - break; - } - if(dot_place==-1) - { - var_number=0; - double pw=1; - for(int i=(int)str.length()-1;i>=0;--i) - { - var_number+=(str[i]-'0')*pw; - pw*=10; - } - } - else - { - var_number=0; - double pw=0.1; - for(int i=dot_place+1;i<(int)str.length();++i) - { - var_number+=(str[i]-'0')*pw; - pw/=10; - } - pw=1; - for(int i=dot_place-1;i>=0;--i) - { - var_number+=(str[i]-'0')*pw; - pw*=10; - } - } - return; - } - void set_var_name(std::string& str) - { - var_name=str; - return; - } - void add_child(abstract_syntax_tree& p) - { - children.push_back(p); - return; - } - double return_var_number() - { - return var_number; - } - std::string return_var_string() - { - return var_string; - } - std::string return_var_name() - { - return var_name; - } -}; - -int main() -{ - abstract_syntax_tree a,b; - a.add_child(a); - a.add_child(a); - a.add_child(a); - b=a; - b.print_tree(1); - return 0; -} diff --git a/misc/lexer(useless).h b/misc/lexer(useless).h deleted file mode 100644 index d5cb091..0000000 --- a/misc/lexer(useless).h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef __LEXER_H__ -#define __LEXER_H__ - - -#include -#include -#include -#include "nasal.h" -#include "process_stack.h" - -using namespace nasal; - -std::string text; -process_stack _test; -process_stack_unit _unit; - -void PrintProcess(std::string content) -{ - std::string Sentence=""; - int len=(int)content.length(); - for(int i=0;i> "; - std::getline(std::cin,text); - int len=(int)text.length(); - - int sharpDetected=0; - for(int i=len-1;i>=0;--i) - { - if(text[i]=='#') - { - //ignore sharp - len=i; - sharpDetected=i; - } - if(text[i]==';') - { - len=i+1; - //find the real end of the sentence - if(sharpDetected) - { - for(int j=sharpDetected-1;j>=len;--j) - if(text[j]!=' ') - { - len=j+1; - break; - } - } - else - { - for(int j=(int)text.length()-1;j>=len;--j) - if(text[j]!=' ') - { - len=j+1; - break; - } - } - break; - } - } - - if(text[len-1]==';') - { - for(int i=0;i=0;--j) - if(text[j]!=' ') - { - string_end=j; - break; - } - if(text[string_end]!=')') - { - std::cout< -#include -#include - -#define IDENTIFIER -1 //Զʶ -#define OPERATOR -2 // or -#define NUMBER -3 // -#define RESERVEWORD -4 //ؼ -#define STRING -5 //ַ -#define FAIL -6 //ʧ -#define SCANEND -7 //ɨ -#define ERRORFOUND -8 //쳣 - -// \n -// \t tab -// \r س -// \\ б -// \' -// \" ˫ -std::string ReserveWord[26]= -{ - "for","foreach","forindex","while", - "var","func","break","continue","return", - "if","else","elsif","nil","and","or", - "print","cmp","append","setsize","subvec","pop", - "sort","contains","delete","keys","typeof" -}; - -std::string OperatorOrDelimiter[40]= -{ - "+","-","*","/","=","+=","-=","*=","/=", - "\n","\t","\r","\\","\'","\"",".", - "<","<=",">",">=","==","!=","~=","!","~", - ",",";","(",")","[","]","{","}","#","?",":", - "&","|","%","^" -}; - -std::string IdentifierTable[1000]={""}; -char ResourcePrograme[16777216]; - -int isReserveWord(std::string &p) -{ - for(int i=0;i<26;++i) - if(ReserveWord[i]==p) - return i+1; - return FAIL; -} - -int isOperatorOrDelimiter(std::string &p) -{ - for(int i=0;i<40;++i) - if(OperatorOrDelimiter[i]==p) - return i+1; - return FAIL; -} - -bool isLetter(char t) -{ - return (('a'<=t) && (t<='z') || ('A'<=t) && (t<='Z')); -} - -bool isNumber(char t) -{ - return (('0'<=t) && (t<='9')); -} - -void InputFile(std::string &FileName) -{ - std::ifstream fin(FileName); - if(fin.fail()) - { - std::cout<<"[Error] Failed to load file: "<127) - { - ++ptr; - temp=Source[ptr]; - } - - token=""; - if(isLetter(temp) || temp=='_') - { - token+=temp; - ++ptr; - temp=Source[ptr]; - while(isLetter(temp) || isNumber(temp) || temp=='_') - { - token+=temp; - ++ptr; - temp=Source[ptr]; - } - Syn=isReserveWord(token); - if(Syn==FAIL) - Syn=IDENTIFIER; - else - Syn=RESERVEWORD; - } - else if(isNumber(temp)) - { - int PointCnt=0; - while(isNumber(temp)) - { - token+=temp; - ++ptr; - temp=Source[ptr]; - if(temp=='.' && !PointCnt) - { - ++PointCnt; - token+=temp; - ++ptr; - temp=Source[ptr]; - } - } - Syn=NUMBER; - } - else if(temp=='(' || temp==')' || temp=='[' || temp==']' || temp=='{' || - temp=='}' || temp==',' || temp==';' || temp=='|' || temp==':' || - temp=='?' || temp=='.' || temp=='`' || temp=='\'' || temp=='&'|| - temp=='%' || temp=='$' || temp=='^') - { - token+=temp; - ++ptr; - Syn=OPERATOR; - } - else if(temp=='=' || temp=='+' || temp=='-' || temp=='*' || temp=='!' || temp=='/' || temp=='<' || temp=='>' || temp=='~') - { - Syn=OPERATOR; - token+=temp; - ++ptr; - temp=Source[ptr]; - if(temp=='=') - { - token+=temp; - ++ptr; - } - } - else if(temp=='\\') - { - Syn=OPERATOR; - token+=temp; - ++ptr; - temp=Source[ptr]; - if(temp=='=' || temp=='n' || temp=='t' || temp=='r' || temp=='\\' || temp=='\'' || temp=='\"') - { - token+=temp; - ++ptr; - } - } - else if(temp=='\"') - { - Syn=STRING; - token+=temp; - ++ptr; - temp=Source[ptr]; - while(temp!='\"') - { - if(temp=='\\') - { - token+=temp; - - ++ptr; - temp=Source[ptr]; - token+=temp; - - ++ptr; - temp=Source[ptr]; - } - else - { - token+=temp; - ++ptr; - temp=Source[ptr]; - } - if(temp=='@' || temp=='\n') - break; - } - //add the last char \" - if(temp=='\"') - { - token+=temp; - ++ptr; - } - else - token+=" __missing_end_of_string"; - } - else if(temp=='@') - { - Syn=SCANEND; - return; - } - else - { - Syn=FAIL; - std::cout<<"[Error] Unexpected error occurred: "<> exit: exit the programe."<> clear: clean the screen."<> help: find help."<> input the file name to scan."<> "; - std::cin>>FileNameOrCommand; - - if(FileNameOrCommand=="exit") - break; - else if(FileNameOrCommand=="clear") - { - system("cls"); - continue; - } - else if(FileNameOrCommand=="help") - { - help(); - continue; - } - //std::ofstream fout("Data.txt"); - InputFile(FileNameOrCommand); - while(Syn!=SCANEND && Syn!=ERRORFOUND) - { - Scanner(Syn,ResourcePrograme,token,Ptr); - if(Syn==OPERATOR) - std::cout<<"( Operator | "<> Complete scanning \""< parse; - token this_token; - int error; - int warning; - public: - nasal_parser() - { - error=0; - warning=0; - this_token.type=0; - } - void get_token() - { - if(parse.empty()) - { - this_token.type=0; - return; - } - this_token=parse.top(); - parse.pop(); - return; - } - int get_error_num() - { - return error; - } - void print_parser_stack() - { - if(parse.empty()) - return; - int line=0; - std::stack temp; - while(!parse.empty()) - { - temp.push(parse.top()); - if(line!=temp.top().line) - { - if(line+1==temp.top().line) - { - line=temp.top().line; - if(line==1) - std::cout<<"line "< "; - parse.pop(); - } - while(!temp.empty()) - { - parse.push(temp.top()); - temp.pop(); - } - std::cout<& lexer) - { - while(!parse.empty()) - parse.pop(); - std::stack temp; - for(std::list::iterator i=lexer.begin();i!=lexer.end();++i) - { - token temp_parse; - temp_parse=*i; - temp.push(temp_parse);//push this into stack - } - if(temp.empty()) - { - std::cout<<">>[Parse] warning: empty lexer list."<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] line "<>[Error] parse stack empty."<>[Parse] complete generation."< -#include -#include "nasal.h" -namespace nasal -{ - - -struct process_stack_unit -{ - int line; //place the unit first appear - std::string name; //content of the unit or name of the var/class/function - std::string format_type; //var class function string info - var unitdata; - bool global; - process_stack_unit *next; - process_stack_unit *last; -}; - -class process_stack -{ - private: - process_stack_unit *head; - process_stack_unit *ptr; - public: - process_stack() - { - head=new process_stack_unit; - head->line=0; - head->name="InterpreterInfo"; - head->format_type="Info"; - head->global=false; - head->unitdata.Type="string"; - head->unitdata.data=new std::string; - *((std::string *)head->unitdata.data)="# Nasal language for FlightGear."; - - head->last=NULL; - head->next=NULL; - ptr=NULL; - } - ~process_stack() - { - process_stack_unit *temp=head; - while(temp->next) - { - temp=temp->next; - delete head; - head=temp; - } - delete head; - } - void stack_append(process_stack_unit &p) - { - process_stack_unit *temp=head; - process_stack_unit *last_node; - while(temp->next) - { - temp=temp->next; - } - temp->next=new process_stack_unit; - - last_node=temp; - temp=temp->next; - - temp->last=last_node; - last_node->next=temp; - temp->next=NULL; - - temp->name=p.name; - temp->line=p.line; - temp->format_type=p.format_type; - temp->global=p.global; - temp->unitdata=p.unitdata; - - return; - } - void stack_print(bool reverse_mode_used) - { - process_stack_unit *temp=head; - std::cout<<"In stack: "<next) - temp=temp->next; - while(temp->last) - { - std::cout<<"line "<line<<": |"<format_type<<"|"<name<<"|\n\t|"; - temp->unitdata.Print(); - std::cout<last; - } - std::cout<<"line "<line<<": |"<format_type<<"|"<name<<"|\n\t|"; - temp->unitdata.Print(); - std::cout<line<<": |"<format_type<<"|"<name<<"|\n\t|"; - temp->unitdata.Print(); - std::cout<next) - { - temp=temp->next; - std::cout<<"line "<line<<": |"<format_type<<"|"<name<<"|\n\t|"; - temp->unitdata.Print(); - std::cout<next) - { - last_node=temp; - temp=temp->next; - } - last_node->next=NULL; - delete temp; - return; - } - bool check_stack(std::string &ElementName) - { - process_stack_unit *temp=head; - while(temp->next) - { - temp=temp->next; - if(temp->name==ElementName) - return true; - } - return false; - } - void stack_content_print(std::string &ElementName) - { - process_stack_unit *temp=head; - while(temp->next) - { - temp=temp->next; - if(temp->name==ElementName) - { - temp->unitdata.Print(); - return; - } - } - return; - } -}; - - - - -} - -#endif diff --git a/misc/str2num.h b/misc/str2num.h deleted file mode 100644 index 6f86c8c..0000000 --- a/misc/str2num.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __STR2NUM_H__ -#define __STR2NUM_H__ - -#include -#include - -namespace nasal -{ - -void Str2Num(std::string &str) -{ - for(int i=0;i<(int)str.length();++i) - if(!(('0'<=str[i]) && (str[i]<='9') || (str[i]=='.'))) - { - std::cout<<"[Error] Non-numeric string."<=0;--i) - { - num+=acc*((long long int)(str[i]-'0')); - acc*=10; - } - std::cout<=0;--i) - { - num+=acc*((double)(str[i]-'0')); - acc*=10; - } - std::cout< must choose - [] can choose - {} can repeat 0 to infinite time(s) - | or - ::= is defined as -*) - -nil ::= nil; -id ::= identifier; -number::= number; -string::= string; -vector::= - '[' {calculation ','} ']' -; -hash ::= - '{' {hashmember ','} '}' -; -hashmember::= - id|string ':' calculation -; -function::= - func argument_list expressions -; -argument_list::= - '(' [{id ','} ([id '...']|{id '=' scalar ','})] ')' -; -expr::= - definition - |multi_assignment - |calculation - |loop - |conditional - |return_expr - |continue_expr - |break_expr -; -expressions::= - '{' {expr} '}' -; -calculation::= - calculation '?' calculation ':' calculation - |or_expr - |calculation ('=' | '+=' | '-=' | '*=' | '/=' | '~=') calculation -; -or_expr::= - and_expr or and_expr -; -and_expr::= - cmp_expr and cmp_expr -; -cmp_expr::= - additive_expr ('==' | '!=' | '>' | '<' | '>=' | '<=') additive_expr -; -additive_expr::= - multive_expr ('+' | '-' | '~') multive_expr -; -multive_expr::= - (unary|scalar) ('*' | '/') (unary|scalar) -; -unary::= - ('-'|'!') scalar -; -scalar::= - function {call_scalar} - |identifier {call_scalar} - |vector {call_scalar} - |hash {call_scalar} - |number - |string - |'(' calculation ')' {call_scalar} -; -call_scalar::= - call_hash - |call_vector - |call_func -; -call_hash::= - '.' id -; -call_vector::= - '[' {(subvec) ','} ']' -; -call_func::= - '(' {calculation ','} ')' - |'(' {hashmember ','} ')' -; -subvec::= - [calculation] ':' [calculation] -; -definition::= - var id '=' calculation - |var '(' multi_id ')' '=' (calculation | multi_scalar) - |'(' var multi_id ')' '=' (calculation | multi_scalar) -; -multi_id::= - {',' id} -; -multi_scalar::= - '(' {',' calculation} ')' -; -multi_assignment::= - multi_scalar '=' (multi_scalar|calculation) -; -loop::= - while_loop - |for_loop - |forei_loop -; -while_loop::= - while '(' calculation ')' expressions -; -for_loop::= - for '(' [definition|calculation] ';' [calculation] ';' [calculation] ')' expressions -; -forei_loop::= - (forindex | foreach) '(' (definition | calculation) ';' calculation ')' expressions -; -conditional::= - if '(' calculation ')' expressions - {elsif '(' calculation ')' expressions} - [else expressions] -; -continue_expr::= - continue -; -break_expr::= - break -; -return_expr::= - return [calculation] +(* + <> must choose + [] can choose + {} can repeat 0 to infinite time(s) + | or + ::= is defined as +*) + +nil ::= nil; +id ::= identifier; +number::= number; +string::= string; +vector::= + '[' {calculation ','} ']' +; +hash ::= + '{' {hashmember ','} '}' +; +hashmember::= + id|string ':' calculation +; +function::= + func argument_list expressions +; +argument_list::= + '(' [{id ','} ([id '...']|{id '=' scalar ','})] ')' +; +expr::= + definition + |multi_assignment + |calculation + |loop + |conditional + |return_expr + |continue_expr + |break_expr +; +expressions::= + '{' {expr} '}' +; +calculation::= + calculation '?' calculation ':' calculation + |or_expr + |calculation ('=' | '+=' | '-=' | '*=' | '/=' | '~=') calculation +; +or_expr::= + and_expr or and_expr +; +and_expr::= + cmp_expr and cmp_expr +; +cmp_expr::= + additive_expr ('==' | '!=' | '>' | '<' | '>=' | '<=') additive_expr +; +additive_expr::= + multive_expr ('+' | '-' | '~') multive_expr +; +multive_expr::= + (unary|scalar) ('*' | '/') (unary|scalar) +; +unary::= + ('-'|'!') scalar +; +scalar::= + function {call_scalar} + |identifier {call_scalar} + |vector {call_scalar} + |hash {call_scalar} + |number + |string + |'(' calculation ')' {call_scalar} +; +call_scalar::= + call_hash + |call_vector + |call_func +; +call_hash::= + '.' id +; +call_vector::= + '[' {(subvec) ','} ']' +; +call_func::= + '(' {calculation ','} ')' + |'(' {hashmember ','} ')' +; +subvec::= + [calculation] ':' [calculation] +; +definition::= + var id '=' calculation + |var '(' multi_id ')' '=' (calculation | multi_scalar) + |'(' var multi_id ')' '=' (calculation | multi_scalar) +; +multi_id::= + {',' id} +; +multi_scalar::= + '(' {',' calculation} ')' +; +multi_assignment::= + multi_scalar '=' (multi_scalar|calculation) +; +loop::= + while_loop + |for_loop + |forei_loop +; +while_loop::= + while '(' calculation ')' expressions +; +for_loop::= + for '(' [definition|calculation] ';' [calculation] ';' [calculation] ')' expressions +; +forei_loop::= + (forindex | foreach) '(' (definition | calculation) ';' calculation ')' expressions +; +conditional::= + if '(' calculation ')' expressions + {elsif '(' calculation ')' expressions} + [else expressions] +; +continue_expr::= + continue +; +break_expr::= + break +; +return_expr::= + return [calculation] ; \ No newline at end of file diff --git a/version3.0/nasal.h b/nasal.h similarity index 95% rename from version3.0/nasal.h rename to nasal.h index 3ed57c4..cea2911 100644 --- a/version3.0/nasal.h +++ b/nasal.h @@ -1,34 +1,34 @@ -#ifndef __NASAL_H__ -#define __NASAL_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* if thread is used, don't forget to add -std=c++11 or higher standard before executing */ -// #include -#include -#include -#include -#include -#include - -#include "nasal_enum.h" -#include "nasal_misc.h" -#include "nasal_resource.h" -#include "nasal_lexer.h" -#include "nasal_ast.h" -#include "nasal_parse.h" -#include "nasal_import.h" -#include "nasal_codegen.h" -#include "nasal_gc.h" -#include "nasal_runtime.h" -#include "nasal_builtin.h" - -#endif +#ifndef __NASAL_H__ +#define __NASAL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* if thread is used, don't forget to add -std=c++11 or higher standard before executing */ +// #include +#include +#include +#include +#include +#include + +#include "nasal_enum.h" +#include "nasal_misc.h" +#include "nasal_resource.h" +#include "nasal_lexer.h" +#include "nasal_ast.h" +#include "nasal_parse.h" +#include "nasal_import.h" +#include "nasal_codegen.h" +#include "nasal_gc.h" +#include "nasal_runtime.h" +#include "nasal_builtin.h" + +#endif diff --git a/version3.0/nasal_ast.h b/nasal_ast.h similarity index 94% rename from version3.0/nasal_ast.h rename to nasal_ast.h index 671cf42..6989ca5 100644 --- a/version3.0/nasal_ast.h +++ b/nasal_ast.h @@ -1,129 +1,129 @@ -#ifndef __NASAL_AST_H__ -#define __NASAL_AST_H__ - -class nasal_ast -{ -private: - int line; - int type; - std::string str; - std::vector children; -public: - nasal_ast(); - nasal_ast(const nasal_ast&); - ~nasal_ast(); - nasal_ast& operator=(const nasal_ast&); - void clear(); - void set_line(int); - void set_type(int); - void set_str(std::string&); - void add_child(nasal_ast); - int get_line(); - int get_type(); - std::string get_str(); - std::vector& get_children(); - void print_ast(int); -}; - -nasal_ast::nasal_ast() -{ - this->line=0; - this->type=ast_null; - this->str=""; - return; -} - -nasal_ast::nasal_ast(const nasal_ast& tmp) -{ - this->line=tmp.line; - this->type=tmp.type; - this->str=tmp.str; - this->children=tmp.children; - return; -} - -nasal_ast::~nasal_ast() -{ - this->str.clear(); - this->children.clear(); - return; -} - -nasal_ast& nasal_ast::operator=(const nasal_ast& tmp) -{ - this->line=tmp.line; - this->type=tmp.type; - this->str=tmp.str; - this->children=tmp.children; - return *this; -} - -void nasal_ast::clear() -{ - this->line=0; - this->type=ast_null; - this->str=""; - this->children.clear(); - return; -} - -void nasal_ast::set_line(int l) -{ - this->line=l; - return; -} - -void nasal_ast::set_type(int t) -{ - this->type=t; - return; -} - -void nasal_ast::set_str(std::string& s) -{ - this->str=s; - return; -} - -void nasal_ast::add_child(nasal_ast ast) -{ - children.push_back(ast); - return; -} - -int nasal_ast::get_line() -{ - return this->line; -} - -int nasal_ast::get_type() -{ - return this->type; -} - -std::string nasal_ast::get_str() -{ - return this->str; -} - -std::vector& nasal_ast::get_children() -{ - return this->children; -} - -void nasal_ast::print_ast(int depth) -{ - std::string indentation=""; - for(int i=0;itype); - std::cout<type==ast_number || this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash) - std::cout<<":"<str; - std::cout<children.size(); - for(int i=0;ichildren[i].print_ast(depth+1); - return; -} - +#ifndef __NASAL_AST_H__ +#define __NASAL_AST_H__ + +class nasal_ast +{ +private: + int line; + int type; + std::string str; + std::vector children; +public: + nasal_ast(); + nasal_ast(const nasal_ast&); + ~nasal_ast(); + nasal_ast& operator=(const nasal_ast&); + void clear(); + void set_line(int); + void set_type(int); + void set_str(std::string&); + void add_child(nasal_ast); + int get_line(); + int get_type(); + std::string get_str(); + std::vector& get_children(); + void print_ast(int); +}; + +nasal_ast::nasal_ast() +{ + this->line=0; + this->type=ast_null; + this->str=""; + return; +} + +nasal_ast::nasal_ast(const nasal_ast& tmp) +{ + this->line=tmp.line; + this->type=tmp.type; + this->str=tmp.str; + this->children=tmp.children; + return; +} + +nasal_ast::~nasal_ast() +{ + this->str.clear(); + this->children.clear(); + return; +} + +nasal_ast& nasal_ast::operator=(const nasal_ast& tmp) +{ + this->line=tmp.line; + this->type=tmp.type; + this->str=tmp.str; + this->children=tmp.children; + return *this; +} + +void nasal_ast::clear() +{ + this->line=0; + this->type=ast_null; + this->str=""; + this->children.clear(); + return; +} + +void nasal_ast::set_line(int l) +{ + this->line=l; + return; +} + +void nasal_ast::set_type(int t) +{ + this->type=t; + return; +} + +void nasal_ast::set_str(std::string& s) +{ + this->str=s; + return; +} + +void nasal_ast::add_child(nasal_ast ast) +{ + children.push_back(ast); + return; +} + +int nasal_ast::get_line() +{ + return this->line; +} + +int nasal_ast::get_type() +{ + return this->type; +} + +std::string nasal_ast::get_str() +{ + return this->str; +} + +std::vector& nasal_ast::get_children() +{ + return this->children; +} + +void nasal_ast::print_ast(int depth) +{ + std::string indentation=""; + for(int i=0;itype); + std::cout<type==ast_number || this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash) + std::cout<<":"<str; + std::cout<children.size(); + for(int i=0;ichildren[i].print_ast(depth+1); + return; +} + #endif \ No newline at end of file diff --git a/version3.0/nasal_builtin.h b/nasal_builtin.h similarity index 97% rename from version3.0/nasal_builtin.h rename to nasal_builtin.h index cd0e35d..3b7011c 100644 --- a/version3.0/nasal_builtin.h +++ b/nasal_builtin.h @@ -1,789 +1,789 @@ -#ifndef __NASAL_BUILTIN_H__ -#define __NASAL_BUILTIN_H__ - -#define in_builtin_find(value_name_string) (local_scope_addr>=0?nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(value_name_string):-1) -#define in_builtin_check(value_addr,value_type) (nasal_vm.gc_get(value_addr).get_type()==(value_type)) - -int nasal_runtime::builtin_print(int local_scope_addr) -{ - // get arguments - int vector_value_addr=in_builtin_find("elements"); - if(vector_value_addr<0 || !in_builtin_check(vector_value_addr,vm_vector)) - { - std::cout<<">> [runtime] builtin_print: \"elements\" has wrong value type(must be vector).\n"; - ++error; - return -1; - } - // main process - nasal_vector& ref_vec=nasal_vm.gc_get(vector_value_addr).get_vector(); - int size=ref_vec.size(); - for(int i=0;i> [runtime] builtin_append: \"vector\" has wrong value type(must be vector).\n"; - ++error; - return -1; - } - if(elem_value_addr<0 || !in_builtin_check(elem_value_addr,vm_vector)) - { - std::cout<<">> [runtime] builtin_append: \"elements\" has wrong value type(must be vector).\n"; - ++error; - return -1; - } - nasal_vector& ref_vector=nasal_vm.gc_get(vector_value_addr).get_vector(); - nasal_vector& ref_elements=nasal_vm.gc_get(elem_value_addr).get_vector(); - int size=ref_elements.size(); - for(int i=0;i> [runtime] builtin_setsize: \"vector\" has wrong value type(must be vector).\n"; - ++error; - return -1; - } - if(size_value_addr<0) - { - std::cout<<">> [runtime] builtin_setsize: \"size\" has wrong value type(must be string or number).\n"; - ++error; - return -1; - } - int type=nasal_vm.gc_get(size_value_addr).get_type(); - if(type!=vm_number && type!=vm_string) - { - std::cout<<">> [runtime] builtin_setsize: size is not a number.\n"; - ++error; - return -1; - } - int number; - if(type==vm_number) - number=(int)nasal_vm.gc_get(size_value_addr).get_number(); - else - { - std::string str=nasal_vm.gc_get(size_value_addr).get_string(); - if(check_numerable_string(str)) - number=(int)trans_string_to_number(str); - else - { - std::cout<<">> [runtime] builtin_setsize: size is not a numerable string.\n"; - ++error; - return -1; - } - } - if(number<0) - { - std::cout<<">> [runtime] builtin_setsize: size must be greater than -1.\n"; - ++error; - return -1; - } - nasal_vector& ref_vector=nasal_vm.gc_get(vector_value_addr).get_vector(); - int vec_size=ref_vector.size(); - if(number=0) - nasal_vm.del_reference(addr); - } - else if(number>vec_size) - for(int i=vec_size;i> [runtime] builtin_system: \"str\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - std::string str=nasal_vm.gc_get(str_value_addr).get_string(); - int size=str.length(); - char* command=new char[size+1]; - for(int i=0;i>str; - nasal_vm.gc_get(ret_addr).set_string(str); - return ret_addr; -} - -int nasal_runtime::builtin_sleep(int local_scope_addr) -{ - int value_addr=in_builtin_find("duration"); - if(value_addr<0 || (nasal_vm.gc_get(value_addr).get_type()!=vm_string && nasal_vm.gc_get(value_addr).get_type()!=vm_number)) - { - std::cout<<">> [runtime] builtin_sleep: \"duration\" has wrong value type(must be string or number).\n"; - ++error; - return -1; - } - unsigned long sleep_time=0; - if(nasal_vm.gc_get(value_addr).get_type()==vm_string) - { - std::string str=nasal_vm.gc_get(value_addr).get_string(); - if(check_numerable_string(str)) - sleep_time=(unsigned long)trans_string_to_number(str); - else - { - std::cout<<">> [runtime] builtin_sleep: this is not a numerable string.\n"; - ++error; - return -1; - } - } - else - sleep_time=(unsigned long)nasal_vm.gc_get(value_addr).get_number(); - sleep(sleep_time); // sleep in unistd.h will make this progress sleep sleep_time seconds. - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_nil); - return ret_addr; -} - -int nasal_runtime::builtin_finput(int local_scope_addr) -{ - int value_addr=in_builtin_find("filename"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_string) - { - std::cout<<">> [runtime] builtin_finput: \"filename\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - std::string filename=nasal_vm.gc_get(value_addr).get_string(); - std::ifstream fin(filename); - std::string file_content=""; - if(!fin.fail()) - while(!fin.eof()) - { - file_content.push_back(fin.get()); - if(fin.eof()) - break; - } - else - file_content="cannot open file named \'"+filename+"\'."; - fin.close(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_string); - nasal_vm.gc_get(ret_addr).set_string(file_content); - return ret_addr; -} - -int nasal_runtime::builtin_foutput(int local_scope_addr) -{ - int value_addr=in_builtin_find("filename"); - int str_value_addr=in_builtin_find("str"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_string) - { - std::cout<<">> [runtime] builtin_foutput: \"filename\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - if(str_value_addr<0 || nasal_vm.gc_get(str_value_addr).get_type()!=vm_string) - { - std::cout<<">> [runtime] builtin_foutput: \"str\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - std::string filename=nasal_vm.gc_get(value_addr).get_string(); - std::string file_content=nasal_vm.gc_get(str_value_addr).get_string(); - std::ofstream fout(filename); - fout<> [runtime] builtin_split: \"delimeter\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - if(string_value_addr<0 || nasal_vm.gc_get(string_value_addr).get_type()!=vm_string) - { - std::cout<<">> [runtime] builtin_split: \"string\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - std::string delimeter=nasal_vm.gc_get(delimeter_value_addr).get_string(); - std::string source=nasal_vm.gc_get(string_value_addr).get_string(); - int delimeter_len=delimeter.length(); - if(delimeter_len<1) - { - std::cout<<">> [runtime] builtin_split: delimeter's length must be greater than 0.\n"; - ++error; - return -1; - } - int source_len=source.length(); - - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_vector); - nasal_vector& ref_vec=nasal_vm.gc_get(ret_addr).get_vector(); - std::string tmp=""; - for(int i=0;i=source_len || source[i+j]!=delimeter[j]) - break; - if(j==delimeter_len-1) - check_delimeter=true; - } - if(check_delimeter) - { - int str_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(str_addr).set_type(vm_string); - nasal_vm.gc_get(str_addr).set_string(tmp); - ref_vec.add_elem(str_addr); - tmp=""; - i+=delimeter_len-1; - } - else - tmp+=source[i]; - } - if(tmp.length()) - { - int str_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(str_addr).set_type(vm_string); - nasal_vm.gc_get(str_addr).set_string(tmp); - ref_vec.add_elem(str_addr); - tmp=""; - } - return ret_addr; -} -int nasal_runtime::builtin_rand(int local_scope_addr) -{ - int value_addr=in_builtin_find("seed"); - if(value_addr<0 || (nasal_vm.gc_get(value_addr).get_type()!=vm_number && nasal_vm.gc_get(value_addr).get_type()!=vm_nil)) - { - std::cout<<">> [runtime] builtin_rand: \"seed\" has wrong value type(must be nil or number).\n"; - ++error; - return -1; - } - if(nasal_vm.gc_get(value_addr).get_type()==vm_number) - { - unsigned int number=(unsigned int)nasal_vm.gc_get(value_addr).get_number(); - srand(number); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_nil); - return ret_addr; - } - double num=0; - for(int i=0;i<5;++i) - num=(num+rand())*(1.0/(RAND_MAX+1.0)); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(num); - return ret_addr; -} -int nasal_runtime::builtin_id(int local_scope_addr) -{ - int value_addr=in_builtin_find("id"); - if(value_addr<0) - { - std::cout<<">> [runtime] builtin_id: cannot find \"id\".\n"; - ++error; - return -1; - } - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)value_addr); - return ret_addr; -} -int nasal_runtime::builtin_int(int local_scope_addr) -{ - int value_addr=in_builtin_find("value"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_int: \"value\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - int number=(int)nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)number); - return ret_addr; -} -int nasal_runtime::builtin_num(int local_scope_addr) -{ - int value_addr=in_builtin_find("value"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_string) - { - std::cout<<">> [runtime] builtin_num: \"value\" has wrong value type(must be string).\n"; - ++error; - return -1; - } - std::string str=nasal_vm.gc_get(value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] builtin_num: this is not a numerable string.\n"; - ++error; - return -1; - } - double number=trans_string_to_number(str); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(number); - return ret_addr; -} -int nasal_runtime::builtin_pop(int local_scope_addr) -{ - int value_addr=in_builtin_find("vector"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_vector) - { - std::cout<<">> [runtime] builtin_pop: \"vector\" has wrong value type(must be vector).\n"; - ++error; - return -1; - } - int ret_addr=nasal_vm.gc_get(value_addr).get_vector().del_elem(); - return ret_addr; -} -int nasal_runtime::builtin_str(int local_scope_addr) -{ - int value_addr=in_builtin_find("number"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_str: \"number\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_string); - nasal_vm.gc_get(ret_addr).set_string(trans_number_to_string(number)); - return ret_addr; -} -int nasal_runtime::builtin_size(int local_scope_addr) -{ - int value_addr=in_builtin_find("object"); - if(value_addr<0) - { - std::cout<<">> [runtime] builtin_size: cannot find value \"object\".\n"; - ++error; - return -1; - } - int type=nasal_vm.gc_get(value_addr).get_type(); - int number=-1; - switch(type) - { - case vm_nil: - case vm_number: - case vm_function: - case vm_closure:break; - case vm_string:number=nasal_vm.gc_get(value_addr).get_string().length();break; - case vm_vector:number=nasal_vm.gc_get(value_addr).get_vector().size();break; - case vm_hash:number=nasal_vm.gc_get(value_addr).get_hash().size();break; - } - int ret_addr=nasal_vm.gc_alloc(); - if(number<0) - nasal_vm.gc_get(ret_addr).set_type(vm_nil); - else - { - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)number); - } - return ret_addr; -} -int nasal_runtime::builtin_xor(int local_scope_addr) -{ - int a_addr=in_builtin_find("a"); - int b_addr=in_builtin_find("b"); - if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_xor: \"a\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_xor: \"b\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); - int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)(number_a^number_b)); - return ret_addr; -} -int nasal_runtime::builtin_and(int local_scope_addr) -{ - int a_addr=in_builtin_find("a"); - int b_addr=in_builtin_find("b"); - if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_and: \"a\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_and: \"b\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); - int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)(number_a&number_b)); - return ret_addr; -} -int nasal_runtime::builtin_or(int local_scope_addr) -{ - int a_addr=in_builtin_find("a"); - int b_addr=in_builtin_find("b"); - if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_or: \"a\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_or: \"b\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); - int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)(number_a|number_b)); - return ret_addr; -} -int nasal_runtime::builtin_nand(int local_scope_addr) -{ - int a_addr=in_builtin_find("a"); - int b_addr=in_builtin_find("b"); - if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_nand: \"a\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_nand: \"b\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); - int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)(~(number_a&number_b))); - return ret_addr; -} -int nasal_runtime::builtin_not(int local_scope_addr) -{ - int a_addr=in_builtin_find("a"); - if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_not: \"a\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - int number=(int)nasal_vm.gc_get(a_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)(~number)); - return ret_addr; -} -int nasal_runtime::builtin_sin(int local_scope_addr) -{ - int value_addr=in_builtin_find("x"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_sin: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(sin(number)); - return ret_addr; -} -int nasal_runtime::builtin_cos(int local_scope_addr) -{ - int value_addr=in_builtin_find("x"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_cos: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(cos(number)); - return ret_addr; -} -int nasal_runtime::builtin_tan(int local_scope_addr) -{ - int value_addr=in_builtin_find("x"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_tan: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(tan(number)); - return ret_addr; -} -int nasal_runtime::builtin_exp(int local_scope_addr) -{ - int value_addr=in_builtin_find("x"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_exp: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(exp(number)); - return ret_addr; -} -int nasal_runtime::builtin_ln(int local_scope_addr) -{ - int value_addr=in_builtin_find("x"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_ln: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(log(number)/log(2.7182818284590452354)); - return ret_addr; -} -int nasal_runtime::builtin_sqrt(int local_scope_addr) -{ - int value_addr=in_builtin_find("x"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_sqrt: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double number=nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(sqrt(number)); - return ret_addr; -} -int nasal_runtime::builtin_atan2(int local_scope_addr) -{ - int x_value_addr=in_builtin_find("x"); - int y_value_addr=in_builtin_find("y"); - if(x_value_addr<0 || nasal_vm.gc_get(x_value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_atan2: \"x\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - if(y_value_addr<0 || nasal_vm.gc_get(y_value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_atan2: \"y\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - double x=nasal_vm.gc_get(x_value_addr).get_number(); - double y=nasal_vm.gc_get(y_value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number(atan2(y,x)); - return ret_addr; -} -int nasal_runtime::builtin_time(int local_scope_addr) -{ - int value_addr=in_builtin_find("begin_time"); - if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) - { - std::cout<<">> [runtime] builtin_time: \"begin_time\" has wrong value type(must be number).\n"; - ++error; - return -1; - } - time_t begin_time=(time_t)nasal_vm.gc_get(value_addr).get_number(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)time(&begin_time)); - return ret_addr; -} -int nasal_runtime::builtin_contains(int local_scope_addr) -{ - int hash_addr=in_builtin_find("hash"); - int key_addr=in_builtin_find("key"); - if(hash_addr<0 || !in_builtin_check(hash_addr,vm_hash)) - { - std::cout<<">> [runtime] builtin_contains: \"hash\" has wrong type(must be hash).\n"; - ++error; - return -1; - } - if(key_addr<0 || !in_builtin_check(key_addr,vm_string)) - { - std::cout<<">> [runtime] builtin_contains: \"key\" has wrong type(must be string).\n"; - ++error; - return -1; - } - std::string key=nasal_vm.gc_get(key_addr).get_string(); - bool contains=nasal_vm.gc_get(hash_addr).get_hash().check_contain(key); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_number); - nasal_vm.gc_get(ret_addr).set_number((double)contains); - return ret_addr; -} -int nasal_runtime::builtin_delete(int local_scope_addr) -{ - int hash_addr=in_builtin_find("hash"); - int key_addr=in_builtin_find("key"); - if(hash_addr<0 || !in_builtin_check(hash_addr,vm_hash)) - { - std::cout<<">> [runtime] builtin_delete: \"hash\" has wrong type(must be hash).\n"; - ++error; - return -1; - } - if(key_addr<0 || !in_builtin_check(key_addr,vm_string)) - { - std::cout<<">> [runtime] builtin_delete: \"key\" has wrong type(must be string).\n"; - ++error; - return -1; - } - std::string key=nasal_vm.gc_get(key_addr).get_string(); - nasal_vm.gc_get(hash_addr).get_hash().del_elem(key); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_nil); - return ret_addr; -} -int nasal_runtime::builtin_getkeys(int local_scope_addr) -{ - int hash_addr=in_builtin_find("hash"); - if(hash_addr<0 || !in_builtin_check(hash_addr,vm_hash)) - { - std::cout<<">> [runtime] builtin_delete: \"hash\" has wrong type(must be hash).\n"; - ++error; - return -1; - } - int ret_addr=nasal_vm.gc_get(hash_addr).get_hash().get_keys(); - return ret_addr; -} -int nasal_runtime::builtin_import(int local_scope_addr) -{ - // this function is used in preprocessing. - // this function will return nothing when running. - ++error; - std::cout<<">> [runtime] builtin_import: cannot use import when running.\n"; - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_nil); - return ret_addr; -} -int nasal_runtime::builtin_die(int local_scope_addr) -{ - int str_addr=in_builtin_find("str"); - if(str_addr<0 || !in_builtin_check(str_addr,vm_string)) - { - std::cout<<">> [runtime] builtin_die: \"str\" has wrong type(must be string).\n"; - ++error; - return -1; - } - ++error; - std::cout<<">> [runtime] error: "<> [runtime] builtin_type: cannot find \"object\".\n"; - ++error; - return -1; - } - int type=nasal_vm.gc_get(value_addr).get_type(); - int ret_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_addr).set_type(vm_string); - switch(type) - { - case vm_nil: nasal_vm.gc_get(ret_addr).set_string("nil");break; - case vm_number: nasal_vm.gc_get(ret_addr).set_string("number");break; - case vm_string: nasal_vm.gc_get(ret_addr).set_string("string");break; - case vm_vector: nasal_vm.gc_get(ret_addr).set_string("vector");break; - case vm_hash: nasal_vm.gc_get(ret_addr).set_string("hash");break; - case vm_function: nasal_vm.gc_get(ret_addr).set_string("function");break; - } - return ret_addr; -} +#ifndef __NASAL_BUILTIN_H__ +#define __NASAL_BUILTIN_H__ + +#define in_builtin_find(value_name_string) (local_scope_addr>=0?nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(value_name_string):-1) +#define in_builtin_check(value_addr,value_type) (nasal_vm.gc_get(value_addr).get_type()==(value_type)) + +int nasal_runtime::builtin_print(int local_scope_addr) +{ + // get arguments + int vector_value_addr=in_builtin_find("elements"); + if(vector_value_addr<0 || !in_builtin_check(vector_value_addr,vm_vector)) + { + std::cout<<">> [runtime] builtin_print: \"elements\" has wrong value type(must be vector).\n"; + ++error; + return -1; + } + // main process + nasal_vector& ref_vec=nasal_vm.gc_get(vector_value_addr).get_vector(); + int size=ref_vec.size(); + for(int i=0;i> [runtime] builtin_append: \"vector\" has wrong value type(must be vector).\n"; + ++error; + return -1; + } + if(elem_value_addr<0 || !in_builtin_check(elem_value_addr,vm_vector)) + { + std::cout<<">> [runtime] builtin_append: \"elements\" has wrong value type(must be vector).\n"; + ++error; + return -1; + } + nasal_vector& ref_vector=nasal_vm.gc_get(vector_value_addr).get_vector(); + nasal_vector& ref_elements=nasal_vm.gc_get(elem_value_addr).get_vector(); + int size=ref_elements.size(); + for(int i=0;i> [runtime] builtin_setsize: \"vector\" has wrong value type(must be vector).\n"; + ++error; + return -1; + } + if(size_value_addr<0) + { + std::cout<<">> [runtime] builtin_setsize: \"size\" has wrong value type(must be string or number).\n"; + ++error; + return -1; + } + int type=nasal_vm.gc_get(size_value_addr).get_type(); + if(type!=vm_number && type!=vm_string) + { + std::cout<<">> [runtime] builtin_setsize: size is not a number.\n"; + ++error; + return -1; + } + int number; + if(type==vm_number) + number=(int)nasal_vm.gc_get(size_value_addr).get_number(); + else + { + std::string str=nasal_vm.gc_get(size_value_addr).get_string(); + if(check_numerable_string(str)) + number=(int)trans_string_to_number(str); + else + { + std::cout<<">> [runtime] builtin_setsize: size is not a numerable string.\n"; + ++error; + return -1; + } + } + if(number<0) + { + std::cout<<">> [runtime] builtin_setsize: size must be greater than -1.\n"; + ++error; + return -1; + } + nasal_vector& ref_vector=nasal_vm.gc_get(vector_value_addr).get_vector(); + int vec_size=ref_vector.size(); + if(number=0) + nasal_vm.del_reference(addr); + } + else if(number>vec_size) + for(int i=vec_size;i> [runtime] builtin_system: \"str\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + std::string str=nasal_vm.gc_get(str_value_addr).get_string(); + int size=str.length(); + char* command=new char[size+1]; + for(int i=0;i>str; + nasal_vm.gc_get(ret_addr).set_string(str); + return ret_addr; +} + +int nasal_runtime::builtin_sleep(int local_scope_addr) +{ + int value_addr=in_builtin_find("duration"); + if(value_addr<0 || (nasal_vm.gc_get(value_addr).get_type()!=vm_string && nasal_vm.gc_get(value_addr).get_type()!=vm_number)) + { + std::cout<<">> [runtime] builtin_sleep: \"duration\" has wrong value type(must be string or number).\n"; + ++error; + return -1; + } + unsigned long sleep_time=0; + if(nasal_vm.gc_get(value_addr).get_type()==vm_string) + { + std::string str=nasal_vm.gc_get(value_addr).get_string(); + if(check_numerable_string(str)) + sleep_time=(unsigned long)trans_string_to_number(str); + else + { + std::cout<<">> [runtime] builtin_sleep: this is not a numerable string.\n"; + ++error; + return -1; + } + } + else + sleep_time=(unsigned long)nasal_vm.gc_get(value_addr).get_number(); + sleep(sleep_time); // sleep in unistd.h will make this progress sleep sleep_time seconds. + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_nil); + return ret_addr; +} + +int nasal_runtime::builtin_finput(int local_scope_addr) +{ + int value_addr=in_builtin_find("filename"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_string) + { + std::cout<<">> [runtime] builtin_finput: \"filename\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + std::string filename=nasal_vm.gc_get(value_addr).get_string(); + std::ifstream fin(filename); + std::string file_content=""; + if(!fin.fail()) + while(!fin.eof()) + { + file_content.push_back(fin.get()); + if(fin.eof()) + break; + } + else + file_content="cannot open file named \'"+filename+"\'."; + fin.close(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_string); + nasal_vm.gc_get(ret_addr).set_string(file_content); + return ret_addr; +} + +int nasal_runtime::builtin_foutput(int local_scope_addr) +{ + int value_addr=in_builtin_find("filename"); + int str_value_addr=in_builtin_find("str"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_string) + { + std::cout<<">> [runtime] builtin_foutput: \"filename\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + if(str_value_addr<0 || nasal_vm.gc_get(str_value_addr).get_type()!=vm_string) + { + std::cout<<">> [runtime] builtin_foutput: \"str\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + std::string filename=nasal_vm.gc_get(value_addr).get_string(); + std::string file_content=nasal_vm.gc_get(str_value_addr).get_string(); + std::ofstream fout(filename); + fout<> [runtime] builtin_split: \"delimeter\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + if(string_value_addr<0 || nasal_vm.gc_get(string_value_addr).get_type()!=vm_string) + { + std::cout<<">> [runtime] builtin_split: \"string\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + std::string delimeter=nasal_vm.gc_get(delimeter_value_addr).get_string(); + std::string source=nasal_vm.gc_get(string_value_addr).get_string(); + int delimeter_len=delimeter.length(); + if(delimeter_len<1) + { + std::cout<<">> [runtime] builtin_split: delimeter's length must be greater than 0.\n"; + ++error; + return -1; + } + int source_len=source.length(); + + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_vector); + nasal_vector& ref_vec=nasal_vm.gc_get(ret_addr).get_vector(); + std::string tmp=""; + for(int i=0;i=source_len || source[i+j]!=delimeter[j]) + break; + if(j==delimeter_len-1) + check_delimeter=true; + } + if(check_delimeter) + { + int str_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(str_addr).set_type(vm_string); + nasal_vm.gc_get(str_addr).set_string(tmp); + ref_vec.add_elem(str_addr); + tmp=""; + i+=delimeter_len-1; + } + else + tmp+=source[i]; + } + if(tmp.length()) + { + int str_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(str_addr).set_type(vm_string); + nasal_vm.gc_get(str_addr).set_string(tmp); + ref_vec.add_elem(str_addr); + tmp=""; + } + return ret_addr; +} +int nasal_runtime::builtin_rand(int local_scope_addr) +{ + int value_addr=in_builtin_find("seed"); + if(value_addr<0 || (nasal_vm.gc_get(value_addr).get_type()!=vm_number && nasal_vm.gc_get(value_addr).get_type()!=vm_nil)) + { + std::cout<<">> [runtime] builtin_rand: \"seed\" has wrong value type(must be nil or number).\n"; + ++error; + return -1; + } + if(nasal_vm.gc_get(value_addr).get_type()==vm_number) + { + unsigned int number=(unsigned int)nasal_vm.gc_get(value_addr).get_number(); + srand(number); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_nil); + return ret_addr; + } + double num=0; + for(int i=0;i<5;++i) + num=(num+rand())*(1.0/(RAND_MAX+1.0)); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(num); + return ret_addr; +} +int nasal_runtime::builtin_id(int local_scope_addr) +{ + int value_addr=in_builtin_find("id"); + if(value_addr<0) + { + std::cout<<">> [runtime] builtin_id: cannot find \"id\".\n"; + ++error; + return -1; + } + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)value_addr); + return ret_addr; +} +int nasal_runtime::builtin_int(int local_scope_addr) +{ + int value_addr=in_builtin_find("value"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_int: \"value\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + int number=(int)nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)number); + return ret_addr; +} +int nasal_runtime::builtin_num(int local_scope_addr) +{ + int value_addr=in_builtin_find("value"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_string) + { + std::cout<<">> [runtime] builtin_num: \"value\" has wrong value type(must be string).\n"; + ++error; + return -1; + } + std::string str=nasal_vm.gc_get(value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] builtin_num: this is not a numerable string.\n"; + ++error; + return -1; + } + double number=trans_string_to_number(str); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(number); + return ret_addr; +} +int nasal_runtime::builtin_pop(int local_scope_addr) +{ + int value_addr=in_builtin_find("vector"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_vector) + { + std::cout<<">> [runtime] builtin_pop: \"vector\" has wrong value type(must be vector).\n"; + ++error; + return -1; + } + int ret_addr=nasal_vm.gc_get(value_addr).get_vector().del_elem(); + return ret_addr; +} +int nasal_runtime::builtin_str(int local_scope_addr) +{ + int value_addr=in_builtin_find("number"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_str: \"number\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_string); + nasal_vm.gc_get(ret_addr).set_string(trans_number_to_string(number)); + return ret_addr; +} +int nasal_runtime::builtin_size(int local_scope_addr) +{ + int value_addr=in_builtin_find("object"); + if(value_addr<0) + { + std::cout<<">> [runtime] builtin_size: cannot find value \"object\".\n"; + ++error; + return -1; + } + int type=nasal_vm.gc_get(value_addr).get_type(); + int number=-1; + switch(type) + { + case vm_nil: + case vm_number: + case vm_function: + case vm_closure:break; + case vm_string:number=nasal_vm.gc_get(value_addr).get_string().length();break; + case vm_vector:number=nasal_vm.gc_get(value_addr).get_vector().size();break; + case vm_hash:number=nasal_vm.gc_get(value_addr).get_hash().size();break; + } + int ret_addr=nasal_vm.gc_alloc(); + if(number<0) + nasal_vm.gc_get(ret_addr).set_type(vm_nil); + else + { + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)number); + } + return ret_addr; +} +int nasal_runtime::builtin_xor(int local_scope_addr) +{ + int a_addr=in_builtin_find("a"); + int b_addr=in_builtin_find("b"); + if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_xor: \"a\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_xor: \"b\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); + int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)(number_a^number_b)); + return ret_addr; +} +int nasal_runtime::builtin_and(int local_scope_addr) +{ + int a_addr=in_builtin_find("a"); + int b_addr=in_builtin_find("b"); + if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_and: \"a\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_and: \"b\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); + int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)(number_a&number_b)); + return ret_addr; +} +int nasal_runtime::builtin_or(int local_scope_addr) +{ + int a_addr=in_builtin_find("a"); + int b_addr=in_builtin_find("b"); + if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_or: \"a\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_or: \"b\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); + int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)(number_a|number_b)); + return ret_addr; +} +int nasal_runtime::builtin_nand(int local_scope_addr) +{ + int a_addr=in_builtin_find("a"); + int b_addr=in_builtin_find("b"); + if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_nand: \"a\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + if(b_addr<0 || nasal_vm.gc_get(b_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_nand: \"b\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + int number_a=(int)nasal_vm.gc_get(a_addr).get_number(); + int number_b=(int)nasal_vm.gc_get(b_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)(~(number_a&number_b))); + return ret_addr; +} +int nasal_runtime::builtin_not(int local_scope_addr) +{ + int a_addr=in_builtin_find("a"); + if(a_addr<0 || nasal_vm.gc_get(a_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_not: \"a\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + int number=(int)nasal_vm.gc_get(a_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)(~number)); + return ret_addr; +} +int nasal_runtime::builtin_sin(int local_scope_addr) +{ + int value_addr=in_builtin_find("x"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_sin: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(sin(number)); + return ret_addr; +} +int nasal_runtime::builtin_cos(int local_scope_addr) +{ + int value_addr=in_builtin_find("x"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_cos: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(cos(number)); + return ret_addr; +} +int nasal_runtime::builtin_tan(int local_scope_addr) +{ + int value_addr=in_builtin_find("x"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_tan: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(tan(number)); + return ret_addr; +} +int nasal_runtime::builtin_exp(int local_scope_addr) +{ + int value_addr=in_builtin_find("x"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_exp: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(exp(number)); + return ret_addr; +} +int nasal_runtime::builtin_ln(int local_scope_addr) +{ + int value_addr=in_builtin_find("x"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_ln: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(log(number)/log(2.7182818284590452354)); + return ret_addr; +} +int nasal_runtime::builtin_sqrt(int local_scope_addr) +{ + int value_addr=in_builtin_find("x"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_sqrt: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double number=nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(sqrt(number)); + return ret_addr; +} +int nasal_runtime::builtin_atan2(int local_scope_addr) +{ + int x_value_addr=in_builtin_find("x"); + int y_value_addr=in_builtin_find("y"); + if(x_value_addr<0 || nasal_vm.gc_get(x_value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_atan2: \"x\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + if(y_value_addr<0 || nasal_vm.gc_get(y_value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_atan2: \"y\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + double x=nasal_vm.gc_get(x_value_addr).get_number(); + double y=nasal_vm.gc_get(y_value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number(atan2(y,x)); + return ret_addr; +} +int nasal_runtime::builtin_time(int local_scope_addr) +{ + int value_addr=in_builtin_find("begin_time"); + if(value_addr<0 || nasal_vm.gc_get(value_addr).get_type()!=vm_number) + { + std::cout<<">> [runtime] builtin_time: \"begin_time\" has wrong value type(must be number).\n"; + ++error; + return -1; + } + time_t begin_time=(time_t)nasal_vm.gc_get(value_addr).get_number(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)time(&begin_time)); + return ret_addr; +} +int nasal_runtime::builtin_contains(int local_scope_addr) +{ + int hash_addr=in_builtin_find("hash"); + int key_addr=in_builtin_find("key"); + if(hash_addr<0 || !in_builtin_check(hash_addr,vm_hash)) + { + std::cout<<">> [runtime] builtin_contains: \"hash\" has wrong type(must be hash).\n"; + ++error; + return -1; + } + if(key_addr<0 || !in_builtin_check(key_addr,vm_string)) + { + std::cout<<">> [runtime] builtin_contains: \"key\" has wrong type(must be string).\n"; + ++error; + return -1; + } + std::string key=nasal_vm.gc_get(key_addr).get_string(); + bool contains=nasal_vm.gc_get(hash_addr).get_hash().check_contain(key); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_number); + nasal_vm.gc_get(ret_addr).set_number((double)contains); + return ret_addr; +} +int nasal_runtime::builtin_delete(int local_scope_addr) +{ + int hash_addr=in_builtin_find("hash"); + int key_addr=in_builtin_find("key"); + if(hash_addr<0 || !in_builtin_check(hash_addr,vm_hash)) + { + std::cout<<">> [runtime] builtin_delete: \"hash\" has wrong type(must be hash).\n"; + ++error; + return -1; + } + if(key_addr<0 || !in_builtin_check(key_addr,vm_string)) + { + std::cout<<">> [runtime] builtin_delete: \"key\" has wrong type(must be string).\n"; + ++error; + return -1; + } + std::string key=nasal_vm.gc_get(key_addr).get_string(); + nasal_vm.gc_get(hash_addr).get_hash().del_elem(key); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_nil); + return ret_addr; +} +int nasal_runtime::builtin_getkeys(int local_scope_addr) +{ + int hash_addr=in_builtin_find("hash"); + if(hash_addr<0 || !in_builtin_check(hash_addr,vm_hash)) + { + std::cout<<">> [runtime] builtin_delete: \"hash\" has wrong type(must be hash).\n"; + ++error; + return -1; + } + int ret_addr=nasal_vm.gc_get(hash_addr).get_hash().get_keys(); + return ret_addr; +} +int nasal_runtime::builtin_import(int local_scope_addr) +{ + // this function is used in preprocessing. + // this function will return nothing when running. + ++error; + std::cout<<">> [runtime] builtin_import: cannot use import when running.\n"; + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_nil); + return ret_addr; +} +int nasal_runtime::builtin_die(int local_scope_addr) +{ + int str_addr=in_builtin_find("str"); + if(str_addr<0 || !in_builtin_check(str_addr,vm_string)) + { + std::cout<<">> [runtime] builtin_die: \"str\" has wrong type(must be string).\n"; + ++error; + return -1; + } + ++error; + std::cout<<">> [runtime] error: "<> [runtime] builtin_type: cannot find \"object\".\n"; + ++error; + return -1; + } + int type=nasal_vm.gc_get(value_addr).get_type(); + int ret_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_addr).set_type(vm_string); + switch(type) + { + case vm_nil: nasal_vm.gc_get(ret_addr).set_string("nil");break; + case vm_number: nasal_vm.gc_get(ret_addr).set_string("number");break; + case vm_string: nasal_vm.gc_get(ret_addr).set_string("string");break; + case vm_vector: nasal_vm.gc_get(ret_addr).set_string("vector");break; + case vm_hash: nasal_vm.gc_get(ret_addr).set_string("hash");break; + case vm_function: nasal_vm.gc_get(ret_addr).set_string("function");break; + } + return ret_addr; +} #endif \ No newline at end of file diff --git a/version3.0/nasal_codegen.h b/nasal_codegen.h similarity index 96% rename from version3.0/nasal_codegen.h rename to nasal_codegen.h index 8c202b5..5f45e22 100644 --- a/version3.0/nasal_codegen.h +++ b/nasal_codegen.h @@ -1,225 +1,225 @@ -#ifndef __NASAL_CODEGEN_H__ -#define __NASAL_CODEGEN_H__ - -// unfinished -// now it can output ast but it is not byte code yet -// please wait... -class nasal_codegen -{ -private: - std::vector file_header; - std::vector output_file; - std::vector string_table; - int error; - void init(); - void output_int(unsigned int,std::vector&); - void output_short(unsigned short,std::vector&); - void output_root(nasal_ast&); - unsigned int input_int(std::ifstream&); - unsigned short input_short(std::ifstream&); - void input_root(nasal_ast&,std::ifstream&); -public: - nasal_codegen(); - int get_error(); - void output_exec(std::string,nasal_ast&); - void load_exec(std::string,nasal_ast&); -}; - -nasal_codegen::nasal_codegen() -{ - error=0; - string_table.clear(); - return; -} - -int nasal_codegen::get_error() -{ - return error; -} - -void nasal_codegen::init() -{ - error=0; - string_table.clear(); - file_header.clear(); - output_file.clear(); - return; -} - -void nasal_codegen::output_int(unsigned int num,std::vector& vec) -{ - unsigned int tmp=0xff000000; - unsigned int offset=24; - for(int i=0;i<4;++i) - { - vec.push_back((unsigned char)((tmp&num)>>offset)); - offset-=8; - tmp>>=8; - } - return; -} - -void nasal_codegen::output_short(unsigned short num,std::vector& vec) -{ - vec.push_back((unsigned char)((num&0xff00)>>8)); - vec.push_back((unsigned char)(num&0x00ff)); - return; -} - -void nasal_codegen::output_root(nasal_ast& root) -{ - unsigned char type=(unsigned char)root.get_type(); - output_file.push_back(type); - std::vector& ref_vec=root.get_children(); - unsigned short root_children_size=ref_vec.size(); - output_short(root_children_size,output_file); - if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash) - { - std::string tmp=root.get_str(); - if(std::find(string_table.begin(),string_table.end(),tmp)==string_table.end()) - { - string_table.push_back(tmp); - output_short(string_table.size()-1,output_file); - } - else - { - for(int i=0;iinit(); - - // put header input file_header - unsigned char header[4]={0x40,0x56,0x4b,0x21}; - for(int i=0;i<4;++i) - file_header.push_back(header[i]); - - // main progress,put codes into output_file - output_root(root); - - // put string table into file_header - output_short(string_table.size(),file_header); - for(int i=0;i> [code] cannot generate file \""<> [code] cannot open file\""<> [code] \""< file_header; + std::vector output_file; + std::vector string_table; + int error; + void init(); + void output_int(unsigned int,std::vector&); + void output_short(unsigned short,std::vector&); + void output_root(nasal_ast&); + unsigned int input_int(std::ifstream&); + unsigned short input_short(std::ifstream&); + void input_root(nasal_ast&,std::ifstream&); +public: + nasal_codegen(); + int get_error(); + void output_exec(std::string,nasal_ast&); + void load_exec(std::string,nasal_ast&); +}; + +nasal_codegen::nasal_codegen() +{ + error=0; + string_table.clear(); + return; +} + +int nasal_codegen::get_error() +{ + return error; +} + +void nasal_codegen::init() +{ + error=0; + string_table.clear(); + file_header.clear(); + output_file.clear(); + return; +} + +void nasal_codegen::output_int(unsigned int num,std::vector& vec) +{ + unsigned int tmp=0xff000000; + unsigned int offset=24; + for(int i=0;i<4;++i) + { + vec.push_back((unsigned char)((tmp&num)>>offset)); + offset-=8; + tmp>>=8; + } + return; +} + +void nasal_codegen::output_short(unsigned short num,std::vector& vec) +{ + vec.push_back((unsigned char)((num&0xff00)>>8)); + vec.push_back((unsigned char)(num&0x00ff)); + return; +} + +void nasal_codegen::output_root(nasal_ast& root) +{ + unsigned char type=(unsigned char)root.get_type(); + output_file.push_back(type); + std::vector& ref_vec=root.get_children(); + unsigned short root_children_size=ref_vec.size(); + output_short(root_children_size,output_file); + if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash) + { + std::string tmp=root.get_str(); + if(std::find(string_table.begin(),string_table.end(),tmp)==string_table.end()) + { + string_table.push_back(tmp); + output_short(string_table.size()-1,output_file); + } + else + { + for(int i=0;iinit(); + + // put header input file_header + unsigned char header[4]={0x40,0x56,0x4b,0x21}; + for(int i=0;i<4;++i) + file_header.push_back(header[i]); + + // main progress,put codes into output_file + output_root(root); + + // put string table into file_header + output_short(string_table.size(),file_header); + for(int i=0;i> [code] cannot generate file \""<> [code] cannot open file\""<> [code] \""<> [parse] error_info: [line "<> [parse] error_info: [line "< address in memory -> value address in gc -nasal_hash: elems[key] -> address in memory -> value address in gc -nasal_function: closure -> value address in gc(type: nasal_closure) -nasal_closure: std::list> -> std::map -> (int) -> address in memory -> value address in gc -*/ - -class nasal_vector -{ -private: - // this int points to the space in nasal_vm::memory_manager_memory - std::vector elems; -public: - nasal_vector(); - ~nasal_vector(); - void add_elem(int); - int del_elem(); - int size(); - int get_value_address(int); - int get_mem_address(int); -}; - -class nasal_hash -{ -private: - // this int points to the space in nasal_vm::memory_manager_memory - std::map elems; -public: - nasal_hash(); - ~nasal_hash(); - void add_elem(std::string,int); - void del_elem(std::string); - int size(); - int get_value_address(std::string); - int get_mem_address(std::string); - bool check_contain(std::string); - int get_keys(); -}; - -class nasal_function -{ -private: - // this int points to the space in nasal_vm::garbage_collector_memory - int closure_addr; - nasal_ast argument_list; - nasal_ast function_expr; -public: - nasal_function(); - ~nasal_function(); - void set_closure_addr(int); - int get_closure_addr(); - void set_arguments(nasal_ast&); - nasal_ast& get_arguments(); - void set_run_block(nasal_ast&); - nasal_ast& get_run_block(); -}; - -class nasal_closure -{ -private: - // int in std::map points to the space in nasal_vm::memory_manager_memory - // and this memory_manager_memory space stores an address to garbage_collector_memory - // and this address points to an nasal_hash - std::list > elems; -public: - nasal_closure(); - ~nasal_closure(); - void add_scope(); - void del_scope(); - void add_new_value(std::string,int); - int get_value_address(std::string); - int get_mem_address(std::string); - void set_closure(nasal_closure&); -}; - -class nasal_scalar -{ -private: - int type; - void* scalar_ptr; -public: - nasal_scalar(); - ~nasal_scalar(); - void clear(); - bool set_type(int); - void set_number(double); - void set_string(std::string); - int get_type(); - double get_number(); - std::string get_string(); - nasal_vector& get_vector(); - nasal_hash& get_hash(); - nasal_function& get_func(); - nasal_closure& get_closure(); - // parameter: memory_manager_memory address - int nasal_scalar_add(int,int); - int nasal_scalar_sub(int,int); - int nasal_scalar_mult(int,int); - int nasal_scalar_div(int,int); - int nasal_scalar_link(int,int); - int nasal_scalar_and(int,int); - int nasal_scalar_or(int,int); - int nasal_scalar_unary_sub(int); - int nasal_scalar_unary_not(int); - int nasal_scalar_cmp_equal(int,int); - int nasal_scalar_cmp_not_equal(int,int); - int nasal_scalar_cmp_less(int,int); - int nasal_scalar_cmp_greater(int,int); - int nasal_scalar_cmp_less_or_equal(int,int); - int nasal_scalar_cmp_greater_or_equal(int,int); -}; - -class nasal_virtual_machine -{ - struct gc_unit - { - bool collected; - int ref_cnt; - nasal_scalar elem; - gc_unit() - { - collected=true; - ref_cnt=0; - return; - } - }; -private: - bool error_info_output_switch; - nasal_scalar error_returned_value; - std::queue garbage_collector_free_space; - std::vector garbage_collector_memory; - std::queue memory_manager_free_space; - std::vector memory_manager_memory; -public: - nasal_virtual_machine(); - ~nasal_virtual_machine(); - void clear(); - void debug(); - int gc_alloc(); // garbage collector gives a new space - nasal_scalar& gc_get(int); // get scalar that stored in gc - void add_reference(int); - void del_reference(int); - int get_refcnt(int); - int mem_alloc(); // memory gives a new space - int mem_free(int); // give space back to memory - int mem_change(int,int); // change value in memory space - int mem_init(int,int); // init value in memory space - int mem_get(int); // get value in memory space -}; - -/* - nasal runtime virtual machine - nasal_scalar_calculator gives functions that calculate nasal_scalar - example: nasal_scalar_calculator.nasal_scalar_add(0x00007c00,0x0000aa55) -*/ -nasal_virtual_machine nasal_vm; -nasal_scalar nasal_scalar_calculator; -// error values set here,if defined before nasal_vm,SIGSEGV will occur. -nasal_vector error_vector; -nasal_hash error_hash; -nasal_function error_function; -nasal_closure error_closure; - -/*functions of nasal_vector*/ -nasal_vector::nasal_vector() -{ - elems.clear(); - return; -} -nasal_vector::~nasal_vector() -{ - int size=elems.size(); - for(int i=0;ielems.size(); -} -int nasal_vector::get_value_address(int index) -{ - int vec_size=elems.size(); - int left_range=-vec_size; - int right_range=vec_size-1; - if(indexright_range) - { - std::cout<<">> [runtime] nasal_vector::get_value_address: index out of range."<right_range) - { - std::cout<<">> [runtime] nasal_vector::get_mem_address: index out of range."<::iterator iter=elems.begin();iter!=elems.end();++iter) - nasal_vm.mem_free(iter->second); - elems.clear(); - return; -} -void nasal_hash::add_elem(std::string key,int value_address) -{ - if(elems.find(key)==elems.end()) - { - int memory_address=nasal_vm.mem_alloc(); - nasal_vm.mem_init(memory_address,value_address); - elems[key]=memory_address; - } - return; -} -void nasal_hash::del_elem(std::string key) -{ - if(elems.find(key)!=elems.end()) - { - nasal_vm.mem_free(elems[key]); - elems.erase(key); - } - return; -} -int nasal_hash::size() -{ - return elems.size(); -} -int nasal_hash::get_value_address(std::string key) -{ - int ret_value_addr=-1; - if(elems.find(key)!=elems.end()) - return nasal_vm.mem_get(elems[key]); - else if(elems.find("parents")!=elems.end()) - { - int mem_addr=elems["parents"]; - int val_addr=nasal_vm.mem_get(mem_addr); - if(nasal_vm.gc_get(val_addr).get_type()==vm_vector) - { - nasal_vector& vec_ref=nasal_vm.gc_get(val_addr).get_vector(); - int size=vec_ref.size(); - for(int i=0;i=0) - break; - } - } - } - return ret_value_addr; -} -int nasal_hash::get_mem_address(std::string key) -{ - int ret_mem_addr=-1; - if(elems.find(key)!=elems.end()) - return elems[key]; - else if(elems.find("parents")!=elems.end()) - { - int mem_addr=elems["parents"]; - int val_addr=nasal_vm.mem_get(mem_addr); - if(nasal_vm.gc_get(val_addr).get_type()==vm_vector) - { - nasal_vector& vec_ref=nasal_vm.gc_get(val_addr).get_vector(); - int size=vec_ref.size(); - for(int i=0;i=0) - break; - } - } - } - return ret_mem_addr; -} -bool nasal_hash::check_contain(std::string key) -{ - if(elems.find(key)!=elems.end()) - return true; - if(elems.find("parents")!=elems.end()) - { - bool result=false; - int mem_addr=elems["parents"]; - int val_addr=nasal_vm.mem_get(mem_addr); - if(nasal_vm.gc_get(val_addr).get_type()==vm_vector) - { - nasal_vector& vec_ref=nasal_vm.gc_get(val_addr).get_vector(); - int size=vec_ref.size(); - for(int i=0;i::iterator iter=elems.begin();iter!=elems.end();++iter) - { - int str_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(str_addr).set_type(vm_string); - nasal_vm.gc_get(str_addr).set_string(iter->first); - ref_vec.add_elem(str_addr); - } - return ret_addr; -} - -/*functions of nasal_function*/ -nasal_function::nasal_function() -{ - closure_addr=-1; - argument_list.clear(); - function_expr.clear(); - return; -} -nasal_function::~nasal_function() -{ - if(closure_addr>=0) - nasal_vm.del_reference(closure_addr); - argument_list.clear(); - function_expr.clear(); - return; -} -void nasal_function::set_closure_addr(int value_address) -{ - if(closure_addr>=0) - nasal_vm.del_reference(closure_addr); - int new_closure=nasal_vm.gc_alloc(); - nasal_vm.gc_get(new_closure).set_type(vm_closure); - nasal_vm.gc_get(new_closure).get_closure().set_closure(nasal_vm.gc_get(value_address).get_closure()); - closure_addr=new_closure; - return; -} -int nasal_function::get_closure_addr() -{ - return this->closure_addr; -} -void nasal_function::set_arguments(nasal_ast& node) -{ - argument_list=node; - return; -} -nasal_ast& nasal_function::get_arguments() -{ - return argument_list; -} -void nasal_function::set_run_block(nasal_ast& node) -{ - function_expr=node; - return; -} -nasal_ast& nasal_function::get_run_block() -{ - return function_expr; -} - -/*functions of nasal_closure*/ -nasal_closure::nasal_closure() -{ - elems.clear(); - return; -} -nasal_closure::~nasal_closure() -{ - for(std::list >::iterator i=elems.begin();i!=elems.end();++i) - { - for(std::map::iterator j=i->begin();j!=i->end();++j) - nasal_vm.mem_free(j->second); - i->clear(); - } - elems.clear(); - return; -} -void nasal_closure::add_scope() -{ - std::map new_scope; - this->elems.push_back(new_scope); - return; -} -void nasal_closure::del_scope() -{ - if(this->elems.empty()) - return; - for(std::map::iterator i=elems.back().begin();i!=elems.back().end();++i) - nasal_vm.mem_free(i->second); - this->elems.pop_back(); - return; -} -void nasal_closure::add_new_value(std::string key,int value_address) -{ - int new_mem_address=nasal_vm.mem_alloc(); - nasal_vm.mem_init(new_mem_address,value_address); - if(elems.back().find(key)!=elems.back().end()) - { - // if this value already exists,delete the old value and update a new value - int old_mem_address=elems.back()[key]; - nasal_vm.mem_free(old_mem_address); - } - elems.back()[key]=new_mem_address; - return; -} -int nasal_closure::get_value_address(std::string key) -{ - int ret_address=-1; - for(std::list >::iterator i=elems.begin();i!=elems.end();++i) - { - if(i->find(key)!=i->end()) - ret_address=nasal_vm.mem_get((*i)[key]); - } - return ret_address; -} -int nasal_closure::get_mem_address(std::string key) -{ - int ret_address=-1; - for(std::list >::iterator i=elems.begin();i!=elems.end();++i) - { - if(i->find(key)!=i->end()) - ret_address=(*i)[key]; - } - return ret_address; -} -void nasal_closure::set_closure(nasal_closure& tmp) -{ - for(std::list >::iterator i=elems.begin();i!=elems.end();++i) - for(std::map::iterator j=i->begin();j!=i->end();++j) - nasal_vm.mem_free(j->second); - elems.clear(); - for(std::list >::iterator i=tmp.elems.begin();i!=tmp.elems.end();++i) - { - this->add_scope(); - for(std::map::iterator j=i->begin();j!=i->end();++j) - { - int new_mem_addr=nasal_vm.mem_alloc(); - int value_addr=nasal_vm.mem_get(j->second); - nasal_vm.mem_init(new_mem_addr,value_addr); - nasal_vm.add_reference(value_addr); - elems.back()[j->first]=new_mem_addr; - } - } - return; -} - -/*functions of nasal_scalar*/ -nasal_scalar::nasal_scalar() -{ - this->type=vm_nil; - this->scalar_ptr=(void*)NULL; - return; -} -nasal_scalar::~nasal_scalar() -{ - // must set type and scalar_ptr to default first - // this operation will avoid SIGTRAP caused by circular reference - // circular reference will cause using destructor repeatedly - int tmp_type=this->type; - void* tmp_ptr=this->scalar_ptr; - - this->type=vm_nil; - this->scalar_ptr=NULL; - switch(tmp_type) - { - case vm_nil: break; - case vm_number: delete (double*)(tmp_ptr); break; - case vm_string: delete (std::string*)(tmp_ptr); break; - case vm_vector: delete (nasal_vector*)(tmp_ptr); break; - case vm_hash: delete (nasal_hash*)(tmp_ptr); break; - case vm_function: delete (nasal_function*)(tmp_ptr); break; - case vm_closure: delete (nasal_closure*)(tmp_ptr); break; - } - return; -} -void nasal_scalar::clear() -{ - // must set type and scalar_ptr to default first - // this operation will avoid SIGTRAP caused by circular reference - // circular reference will cause using destructor repeatedly - int tmp_type=this->type; - void* tmp_ptr=this->scalar_ptr; - - this->type=vm_nil; - this->scalar_ptr=NULL; - switch(tmp_type) - { - case vm_nil: break; - case vm_number: delete (double*)(tmp_ptr); break; - case vm_string: delete (std::string*)(tmp_ptr); break; - case vm_vector: delete (nasal_vector*)(tmp_ptr); break; - case vm_hash: delete (nasal_hash*)(tmp_ptr); break; - case vm_function: delete (nasal_function*)(tmp_ptr); break; - case vm_closure: delete (nasal_closure*)(tmp_ptr); break; - } - return; -} -bool nasal_scalar::set_type(int nasal_scalar_type) -{ - bool ret=true; - this->type=nasal_scalar_type; - switch(nasal_scalar_type) - { - case vm_nil: this->scalar_ptr=(void*)NULL; break; - case vm_number: this->scalar_ptr=(void*)(new double); break; - case vm_string: this->scalar_ptr=(void*)(new std::string); break; - case vm_vector: this->scalar_ptr=(void*)(new nasal_vector); break; - case vm_hash: this->scalar_ptr=(void*)(new nasal_hash); break; - case vm_function: this->scalar_ptr=(void*)(new nasal_function); break; - case vm_closure: this->scalar_ptr=(void*)(new nasal_closure); break; - default: - std::cout<<">> [vm] error scalar type: "<type=vm_nil; - this->scalar_ptr=(void*)NULL; - ret=false; - break; - } - return ret; -} -void nasal_scalar::set_number(double num) -{ - *(double*)(this->scalar_ptr)=num; - return; -} -void nasal_scalar::set_string(std::string str) -{ - *(std::string*)(this->scalar_ptr)=str; - return; -} -int nasal_scalar::get_type() -{ - return this->type; -} -double nasal_scalar::get_number() -{ - if(this->type==vm_number) - return *(double*)(this->scalar_ptr); - else - return 0; -} -std::string nasal_scalar::get_string() -{ - if(this->type==vm_string) - return *(std::string*)(this->scalar_ptr); - else - return "[vm] error value type"; -} -nasal_vector& nasal_scalar::get_vector() -{ - if(this->type==vm_vector) - return *(nasal_vector*)(this->scalar_ptr); - else - return error_vector; -} -nasal_hash& nasal_scalar::get_hash() -{ - if(this->type==vm_hash) - return *(nasal_hash*)(this->scalar_ptr); - else - return error_hash; -} -nasal_function& nasal_scalar::get_func() -{ - if(this->type==vm_function) - return *(nasal_function*)(this->scalar_ptr); - else - return error_function; -} -nasal_closure& nasal_scalar::get_closure() -{ - if(this->type==vm_closure) - return *(nasal_closure*)(this->scalar_ptr); - else - return error_closure; -} - -int nasal_scalar::nasal_scalar_add(int a_scalar_addr,int b_scalar_addr) -{ - if(a_scalar_addr<0 || b_scalar_addr<0) - { - std::cout<<">> [vm] scalar_add: memory returned an invalid address"<> [vm] scalar_add: error value type.only number and string can take part in add."<> [vm] scalar_add: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_add: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_sub: memory returned an invalid address"<> [vm] scalar_sub: error value type.only number and string can take part in sub."<> [vm] scalar_sub: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_sub: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_mult: memory returned an invalid address"<> [vm] scalar_mult: error value type.only number and string can take part in mult."<> [vm] scalar_mult: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_mult: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_div: memory returned an invalid address"<> [vm] scalar_div: error value type.only number and string can take part in div."<> [vm] scalar_div: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_div: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_link: memory returned an invalid address"<> [vm] scalar_link: error value type.only number and string can take part in link."<> [vm] scalar_and: hash and vector cannot take part in and calculation."<> [vm] scalar_or: hash and vector cannot take part in or calculation."<> [vm] scalar_unary_sub: memory returned an invalid address"<> [vm] scalar_unary_sub: error value type.only number and string can take part in unary sub."<> [vm] scalar_unary_sub: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_unary_not: memory returned an invalid address"<> [vm] scalar_unary_not: error value type.number,string and nil can take part in unary not."<> [vm] scalar_cmp_equal: memory returned an invalid address"<> [vm] scalar_cmp_not_equal: memory returned an invalid address"<> [vm] scalar_cmp_less: memory returned an invalid address"<> [vm] scalar_cmp_less: error value type.only number and string can take part in cmp_less."<> [vm] scalar_cmp_less: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_less: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_greater: memory returned an invalid address"<> [vm] scalar_cmp_greater: error value type.only number and string can take part in cmp_greater."<> [vm] scalar_cmp_greater: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_greater: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<b_num); - int new_value_address=nasal_vm.gc_alloc(); - nasal_vm.gc_get(new_value_address).set_type(vm_number); - nasal_vm.gc_get(new_value_address).set_number(result); - return new_value_address; -} -int nasal_scalar::nasal_scalar_cmp_less_or_equal(int a_scalar_addr,int b_scalar_addr) -{ - if(a_scalar_addr<0 || b_scalar_addr<0) - { - std::cout<<">> [vm] scalar_cmp_lequal: memory returned an invalid address"<> [vm] scalar_cmp_lequal: error value type.only number and string can take part in cmp_less_or_equal."<> [vm] scalar_cmp_lequal: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_lequal: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_gequal: memory returned an invalid address"<> [vm] scalar_cmp_gequal: error value type.only number and string can take part in cmp_greater_or_equal."<> [vm] scalar_cmp_gequal: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_gequal: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<=b_num); - int new_value_address=nasal_vm.gc_alloc(); - nasal_vm.gc_get(new_value_address).set_type(vm_number); - nasal_vm.gc_get(new_value_address).set_number(result); - return new_value_address; -} - -/*functions of nasal_virtual_machine*/ -nasal_virtual_machine::nasal_virtual_machine() -{ - error_info_output_switch=true; - return; -} -nasal_virtual_machine::~nasal_virtual_machine() -{ - error_info_output_switch=false; - int gc_mem_size=garbage_collector_memory.size(); - int mm_mem_size=memory_manager_memory.size(); - for(int i=0;i> [debug] "<<((i<<8)+j)<<": "<>8][ret&0xff].collected=false; - garbage_collector_memory[ret>>8][ret&0xff].ref_cnt=1; - garbage_collector_free_space.pop(); - return ret; -} -nasal_scalar& nasal_virtual_machine::gc_get(int value_address) -{ - int blk_num=(value_address>>8); - int blk_plc=(value_address&0xff); - if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) - return garbage_collector_memory[blk_num][blk_plc].elem; - else - { - if(error_info_output_switch) - std::cout<<">> [vm] gc_get:unexpected memory \'"<>8); - int blk_plc=(value_address&0xff); - if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) - ++garbage_collector_memory[blk_num][blk_plc].ref_cnt; - else - { - if(error_info_output_switch) - std::cout<<">> [vm] gc_add_ref:unexpected memory \'"<>8); - int blk_plc=(value_address&0xff); - if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) - --garbage_collector_memory[blk_num][blk_plc].ref_cnt; - else - { - if(error_info_output_switch) - std::cout<<">> [vm] gc_del_ref:unexpected memory \'"<>8); - int blk_plc=(value_address&0xff); - if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) - return garbage_collector_memory[blk_num][blk_plc].ref_cnt; - else - { - if(error_info_output_switch) - std::cout<<">> [vm] get_refcnt:unexpected memory \'"<del_reference(memory_manager_memory[memory_address>>8][memory_address&0xff]); - memory_manager_free_space.push(memory_address); - } - else - { - if(error_info_output_switch) - std::cout<<">> [vm] mem_free:unexpected memory \'"<del_reference(memory_manager_memory[memory_address>>8][memory_address&0xff]); - memory_manager_memory[memory_address>>8][memory_address&0xff]=value_address; - } - else - { - if(error_info_output_switch) - std::cout<<">> [vm] mem_change:unexpected memory \'"<>8][memory_address&0xff]=value_address; - else - { - if(error_info_output_switch) - std::cout<<">> [vm] mem_init:unexpected memory \'"<>8][memory_address&0xff]; - else - { - if(error_info_output_switch) - std::cout<<">> [vm] mem_get:unexpected memory \'"< address in memory -> value address in gc +nasal_hash: elems[key] -> address in memory -> value address in gc +nasal_function: closure -> value address in gc(type: nasal_closure) +nasal_closure: std::list> -> std::map -> (int) -> address in memory -> value address in gc +*/ + +class nasal_vector +{ +private: + // this int points to the space in nasal_vm::memory_manager_memory + std::vector elems; +public: + nasal_vector(); + ~nasal_vector(); + void add_elem(int); + int del_elem(); + int size(); + int get_value_address(int); + int get_mem_address(int); +}; + +class nasal_hash +{ +private: + // this int points to the space in nasal_vm::memory_manager_memory + std::map elems; +public: + nasal_hash(); + ~nasal_hash(); + void add_elem(std::string,int); + void del_elem(std::string); + int size(); + int get_value_address(std::string); + int get_mem_address(std::string); + bool check_contain(std::string); + int get_keys(); +}; + +class nasal_function +{ +private: + // this int points to the space in nasal_vm::garbage_collector_memory + int closure_addr; + nasal_ast argument_list; + nasal_ast function_expr; +public: + nasal_function(); + ~nasal_function(); + void set_closure_addr(int); + int get_closure_addr(); + void set_arguments(nasal_ast&); + nasal_ast& get_arguments(); + void set_run_block(nasal_ast&); + nasal_ast& get_run_block(); +}; + +class nasal_closure +{ +private: + // int in std::map points to the space in nasal_vm::memory_manager_memory + // and this memory_manager_memory space stores an address to garbage_collector_memory + // and this address points to an nasal_hash + std::list > elems; +public: + nasal_closure(); + ~nasal_closure(); + void add_scope(); + void del_scope(); + void add_new_value(std::string,int); + int get_value_address(std::string); + int get_mem_address(std::string); + void set_closure(nasal_closure&); +}; + +class nasal_scalar +{ +private: + int type; + void* scalar_ptr; +public: + nasal_scalar(); + ~nasal_scalar(); + void clear(); + bool set_type(int); + void set_number(double); + void set_string(std::string); + int get_type(); + double get_number(); + std::string get_string(); + nasal_vector& get_vector(); + nasal_hash& get_hash(); + nasal_function& get_func(); + nasal_closure& get_closure(); + // parameter: memory_manager_memory address + int nasal_scalar_add(int,int); + int nasal_scalar_sub(int,int); + int nasal_scalar_mult(int,int); + int nasal_scalar_div(int,int); + int nasal_scalar_link(int,int); + int nasal_scalar_and(int,int); + int nasal_scalar_or(int,int); + int nasal_scalar_unary_sub(int); + int nasal_scalar_unary_not(int); + int nasal_scalar_cmp_equal(int,int); + int nasal_scalar_cmp_not_equal(int,int); + int nasal_scalar_cmp_less(int,int); + int nasal_scalar_cmp_greater(int,int); + int nasal_scalar_cmp_less_or_equal(int,int); + int nasal_scalar_cmp_greater_or_equal(int,int); +}; + +class nasal_virtual_machine +{ + struct gc_unit + { + bool collected; + int ref_cnt; + nasal_scalar elem; + gc_unit() + { + collected=true; + ref_cnt=0; + return; + } + }; +private: + bool error_info_output_switch; + nasal_scalar error_returned_value; + std::queue garbage_collector_free_space; + std::vector garbage_collector_memory; + std::queue memory_manager_free_space; + std::vector memory_manager_memory; +public: + nasal_virtual_machine(); + ~nasal_virtual_machine(); + void clear(); + void debug(); + int gc_alloc(); // garbage collector gives a new space + nasal_scalar& gc_get(int); // get scalar that stored in gc + void add_reference(int); + void del_reference(int); + int get_refcnt(int); + int mem_alloc(); // memory gives a new space + int mem_free(int); // give space back to memory + int mem_change(int,int); // change value in memory space + int mem_init(int,int); // init value in memory space + int mem_get(int); // get value in memory space +}; + +/* + nasal runtime virtual machine + nasal_scalar_calculator gives functions that calculate nasal_scalar + example: nasal_scalar_calculator.nasal_scalar_add(0x00007c00,0x0000aa55) +*/ +nasal_virtual_machine nasal_vm; +nasal_scalar nasal_scalar_calculator; +// error values set here,if defined before nasal_vm,SIGSEGV will occur. +nasal_vector error_vector; +nasal_hash error_hash; +nasal_function error_function; +nasal_closure error_closure; + +/*functions of nasal_vector*/ +nasal_vector::nasal_vector() +{ + elems.clear(); + return; +} +nasal_vector::~nasal_vector() +{ + int size=elems.size(); + for(int i=0;ielems.size(); +} +int nasal_vector::get_value_address(int index) +{ + int vec_size=elems.size(); + int left_range=-vec_size; + int right_range=vec_size-1; + if(indexright_range) + { + std::cout<<">> [runtime] nasal_vector::get_value_address: index out of range."<right_range) + { + std::cout<<">> [runtime] nasal_vector::get_mem_address: index out of range."<::iterator iter=elems.begin();iter!=elems.end();++iter) + nasal_vm.mem_free(iter->second); + elems.clear(); + return; +} +void nasal_hash::add_elem(std::string key,int value_address) +{ + if(elems.find(key)==elems.end()) + { + int memory_address=nasal_vm.mem_alloc(); + nasal_vm.mem_init(memory_address,value_address); + elems[key]=memory_address; + } + return; +} +void nasal_hash::del_elem(std::string key) +{ + if(elems.find(key)!=elems.end()) + { + nasal_vm.mem_free(elems[key]); + elems.erase(key); + } + return; +} +int nasal_hash::size() +{ + return elems.size(); +} +int nasal_hash::get_value_address(std::string key) +{ + int ret_value_addr=-1; + if(elems.find(key)!=elems.end()) + return nasal_vm.mem_get(elems[key]); + else if(elems.find("parents")!=elems.end()) + { + int mem_addr=elems["parents"]; + int val_addr=nasal_vm.mem_get(mem_addr); + if(nasal_vm.gc_get(val_addr).get_type()==vm_vector) + { + nasal_vector& vec_ref=nasal_vm.gc_get(val_addr).get_vector(); + int size=vec_ref.size(); + for(int i=0;i=0) + break; + } + } + } + return ret_value_addr; +} +int nasal_hash::get_mem_address(std::string key) +{ + int ret_mem_addr=-1; + if(elems.find(key)!=elems.end()) + return elems[key]; + else if(elems.find("parents")!=elems.end()) + { + int mem_addr=elems["parents"]; + int val_addr=nasal_vm.mem_get(mem_addr); + if(nasal_vm.gc_get(val_addr).get_type()==vm_vector) + { + nasal_vector& vec_ref=nasal_vm.gc_get(val_addr).get_vector(); + int size=vec_ref.size(); + for(int i=0;i=0) + break; + } + } + } + return ret_mem_addr; +} +bool nasal_hash::check_contain(std::string key) +{ + if(elems.find(key)!=elems.end()) + return true; + if(elems.find("parents")!=elems.end()) + { + bool result=false; + int mem_addr=elems["parents"]; + int val_addr=nasal_vm.mem_get(mem_addr); + if(nasal_vm.gc_get(val_addr).get_type()==vm_vector) + { + nasal_vector& vec_ref=nasal_vm.gc_get(val_addr).get_vector(); + int size=vec_ref.size(); + for(int i=0;i::iterator iter=elems.begin();iter!=elems.end();++iter) + { + int str_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(str_addr).set_type(vm_string); + nasal_vm.gc_get(str_addr).set_string(iter->first); + ref_vec.add_elem(str_addr); + } + return ret_addr; +} + +/*functions of nasal_function*/ +nasal_function::nasal_function() +{ + closure_addr=-1; + argument_list.clear(); + function_expr.clear(); + return; +} +nasal_function::~nasal_function() +{ + if(closure_addr>=0) + nasal_vm.del_reference(closure_addr); + argument_list.clear(); + function_expr.clear(); + return; +} +void nasal_function::set_closure_addr(int value_address) +{ + if(closure_addr>=0) + nasal_vm.del_reference(closure_addr); + int new_closure=nasal_vm.gc_alloc(); + nasal_vm.gc_get(new_closure).set_type(vm_closure); + nasal_vm.gc_get(new_closure).get_closure().set_closure(nasal_vm.gc_get(value_address).get_closure()); + closure_addr=new_closure; + return; +} +int nasal_function::get_closure_addr() +{ + return this->closure_addr; +} +void nasal_function::set_arguments(nasal_ast& node) +{ + argument_list=node; + return; +} +nasal_ast& nasal_function::get_arguments() +{ + return argument_list; +} +void nasal_function::set_run_block(nasal_ast& node) +{ + function_expr=node; + return; +} +nasal_ast& nasal_function::get_run_block() +{ + return function_expr; +} + +/*functions of nasal_closure*/ +nasal_closure::nasal_closure() +{ + elems.clear(); + return; +} +nasal_closure::~nasal_closure() +{ + for(std::list >::iterator i=elems.begin();i!=elems.end();++i) + { + for(std::map::iterator j=i->begin();j!=i->end();++j) + nasal_vm.mem_free(j->second); + i->clear(); + } + elems.clear(); + return; +} +void nasal_closure::add_scope() +{ + std::map new_scope; + this->elems.push_back(new_scope); + return; +} +void nasal_closure::del_scope() +{ + if(this->elems.empty()) + return; + for(std::map::iterator i=elems.back().begin();i!=elems.back().end();++i) + nasal_vm.mem_free(i->second); + this->elems.pop_back(); + return; +} +void nasal_closure::add_new_value(std::string key,int value_address) +{ + int new_mem_address=nasal_vm.mem_alloc(); + nasal_vm.mem_init(new_mem_address,value_address); + if(elems.back().find(key)!=elems.back().end()) + { + // if this value already exists,delete the old value and update a new value + int old_mem_address=elems.back()[key]; + nasal_vm.mem_free(old_mem_address); + } + elems.back()[key]=new_mem_address; + return; +} +int nasal_closure::get_value_address(std::string key) +{ + int ret_address=-1; + for(std::list >::iterator i=elems.begin();i!=elems.end();++i) + { + if(i->find(key)!=i->end()) + ret_address=nasal_vm.mem_get((*i)[key]); + } + return ret_address; +} +int nasal_closure::get_mem_address(std::string key) +{ + int ret_address=-1; + for(std::list >::iterator i=elems.begin();i!=elems.end();++i) + { + if(i->find(key)!=i->end()) + ret_address=(*i)[key]; + } + return ret_address; +} +void nasal_closure::set_closure(nasal_closure& tmp) +{ + for(std::list >::iterator i=elems.begin();i!=elems.end();++i) + for(std::map::iterator j=i->begin();j!=i->end();++j) + nasal_vm.mem_free(j->second); + elems.clear(); + for(std::list >::iterator i=tmp.elems.begin();i!=tmp.elems.end();++i) + { + this->add_scope(); + for(std::map::iterator j=i->begin();j!=i->end();++j) + { + int new_mem_addr=nasal_vm.mem_alloc(); + int value_addr=nasal_vm.mem_get(j->second); + nasal_vm.mem_init(new_mem_addr,value_addr); + nasal_vm.add_reference(value_addr); + elems.back()[j->first]=new_mem_addr; + } + } + return; +} + +/*functions of nasal_scalar*/ +nasal_scalar::nasal_scalar() +{ + this->type=vm_nil; + this->scalar_ptr=(void*)NULL; + return; +} +nasal_scalar::~nasal_scalar() +{ + // must set type and scalar_ptr to default first + // this operation will avoid SIGTRAP caused by circular reference + // circular reference will cause using destructor repeatedly + int tmp_type=this->type; + void* tmp_ptr=this->scalar_ptr; + + this->type=vm_nil; + this->scalar_ptr=NULL; + switch(tmp_type) + { + case vm_nil: break; + case vm_number: delete (double*)(tmp_ptr); break; + case vm_string: delete (std::string*)(tmp_ptr); break; + case vm_vector: delete (nasal_vector*)(tmp_ptr); break; + case vm_hash: delete (nasal_hash*)(tmp_ptr); break; + case vm_function: delete (nasal_function*)(tmp_ptr); break; + case vm_closure: delete (nasal_closure*)(tmp_ptr); break; + } + return; +} +void nasal_scalar::clear() +{ + // must set type and scalar_ptr to default first + // this operation will avoid SIGTRAP caused by circular reference + // circular reference will cause using destructor repeatedly + int tmp_type=this->type; + void* tmp_ptr=this->scalar_ptr; + + this->type=vm_nil; + this->scalar_ptr=NULL; + switch(tmp_type) + { + case vm_nil: break; + case vm_number: delete (double*)(tmp_ptr); break; + case vm_string: delete (std::string*)(tmp_ptr); break; + case vm_vector: delete (nasal_vector*)(tmp_ptr); break; + case vm_hash: delete (nasal_hash*)(tmp_ptr); break; + case vm_function: delete (nasal_function*)(tmp_ptr); break; + case vm_closure: delete (nasal_closure*)(tmp_ptr); break; + } + return; +} +bool nasal_scalar::set_type(int nasal_scalar_type) +{ + bool ret=true; + this->type=nasal_scalar_type; + switch(nasal_scalar_type) + { + case vm_nil: this->scalar_ptr=(void*)NULL; break; + case vm_number: this->scalar_ptr=(void*)(new double); break; + case vm_string: this->scalar_ptr=(void*)(new std::string); break; + case vm_vector: this->scalar_ptr=(void*)(new nasal_vector); break; + case vm_hash: this->scalar_ptr=(void*)(new nasal_hash); break; + case vm_function: this->scalar_ptr=(void*)(new nasal_function); break; + case vm_closure: this->scalar_ptr=(void*)(new nasal_closure); break; + default: + std::cout<<">> [vm] error scalar type: "<type=vm_nil; + this->scalar_ptr=(void*)NULL; + ret=false; + break; + } + return ret; +} +void nasal_scalar::set_number(double num) +{ + *(double*)(this->scalar_ptr)=num; + return; +} +void nasal_scalar::set_string(std::string str) +{ + *(std::string*)(this->scalar_ptr)=str; + return; +} +int nasal_scalar::get_type() +{ + return this->type; +} +double nasal_scalar::get_number() +{ + if(this->type==vm_number) + return *(double*)(this->scalar_ptr); + else + return 0; +} +std::string nasal_scalar::get_string() +{ + if(this->type==vm_string) + return *(std::string*)(this->scalar_ptr); + else + return "[vm] error value type"; +} +nasal_vector& nasal_scalar::get_vector() +{ + if(this->type==vm_vector) + return *(nasal_vector*)(this->scalar_ptr); + else + return error_vector; +} +nasal_hash& nasal_scalar::get_hash() +{ + if(this->type==vm_hash) + return *(nasal_hash*)(this->scalar_ptr); + else + return error_hash; +} +nasal_function& nasal_scalar::get_func() +{ + if(this->type==vm_function) + return *(nasal_function*)(this->scalar_ptr); + else + return error_function; +} +nasal_closure& nasal_scalar::get_closure() +{ + if(this->type==vm_closure) + return *(nasal_closure*)(this->scalar_ptr); + else + return error_closure; +} + +int nasal_scalar::nasal_scalar_add(int a_scalar_addr,int b_scalar_addr) +{ + if(a_scalar_addr<0 || b_scalar_addr<0) + { + std::cout<<">> [vm] scalar_add: memory returned an invalid address"<> [vm] scalar_add: error value type.only number and string can take part in add."<> [vm] scalar_add: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_add: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_sub: memory returned an invalid address"<> [vm] scalar_sub: error value type.only number and string can take part in sub."<> [vm] scalar_sub: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_sub: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_mult: memory returned an invalid address"<> [vm] scalar_mult: error value type.only number and string can take part in mult."<> [vm] scalar_mult: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_mult: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_div: memory returned an invalid address"<> [vm] scalar_div: error value type.only number and string can take part in div."<> [vm] scalar_div: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_div: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_link: memory returned an invalid address"<> [vm] scalar_link: error value type.only number and string can take part in link."<> [vm] scalar_and: hash and vector cannot take part in and calculation."<> [vm] scalar_or: hash and vector cannot take part in or calculation."<> [vm] scalar_unary_sub: memory returned an invalid address"<> [vm] scalar_unary_sub: error value type.only number and string can take part in unary sub."<> [vm] scalar_unary_sub: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_unary_not: memory returned an invalid address"<> [vm] scalar_unary_not: error value type.number,string and nil can take part in unary not."<> [vm] scalar_cmp_equal: memory returned an invalid address"<> [vm] scalar_cmp_not_equal: memory returned an invalid address"<> [vm] scalar_cmp_less: memory returned an invalid address"<> [vm] scalar_cmp_less: error value type.only number and string can take part in cmp_less."<> [vm] scalar_cmp_less: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_less: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_greater: memory returned an invalid address"<> [vm] scalar_cmp_greater: error value type.only number and string can take part in cmp_greater."<> [vm] scalar_cmp_greater: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_greater: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<b_num); + int new_value_address=nasal_vm.gc_alloc(); + nasal_vm.gc_get(new_value_address).set_type(vm_number); + nasal_vm.gc_get(new_value_address).set_number(result); + return new_value_address; +} +int nasal_scalar::nasal_scalar_cmp_less_or_equal(int a_scalar_addr,int b_scalar_addr) +{ + if(a_scalar_addr<0 || b_scalar_addr<0) + { + std::cout<<">> [vm] scalar_cmp_lequal: memory returned an invalid address"<> [vm] scalar_cmp_lequal: error value type.only number and string can take part in cmp_less_or_equal."<> [vm] scalar_cmp_lequal: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_lequal: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_gequal: memory returned an invalid address"<> [vm] scalar_cmp_gequal: error value type.only number and string can take part in cmp_greater_or_equal."<> [vm] scalar_cmp_gequal: "<<*(std::string*)a_ref.scalar_ptr<<" is not a numerable string."<> [vm] scalar_cmp_gequal: "<<*(std::string*)b_ref.scalar_ptr<<" is not a numerable string."<=b_num); + int new_value_address=nasal_vm.gc_alloc(); + nasal_vm.gc_get(new_value_address).set_type(vm_number); + nasal_vm.gc_get(new_value_address).set_number(result); + return new_value_address; +} + +/*functions of nasal_virtual_machine*/ +nasal_virtual_machine::nasal_virtual_machine() +{ + error_info_output_switch=true; + return; +} +nasal_virtual_machine::~nasal_virtual_machine() +{ + error_info_output_switch=false; + int gc_mem_size=garbage_collector_memory.size(); + int mm_mem_size=memory_manager_memory.size(); + for(int i=0;i> [debug] "<<((i<<8)+j)<<": "<>8][ret&0xff].collected=false; + garbage_collector_memory[ret>>8][ret&0xff].ref_cnt=1; + garbage_collector_free_space.pop(); + return ret; +} +nasal_scalar& nasal_virtual_machine::gc_get(int value_address) +{ + int blk_num=(value_address>>8); + int blk_plc=(value_address&0xff); + if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) + return garbage_collector_memory[blk_num][blk_plc].elem; + else + { + if(error_info_output_switch) + std::cout<<">> [vm] gc_get:unexpected memory \'"<>8); + int blk_plc=(value_address&0xff); + if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) + ++garbage_collector_memory[blk_num][blk_plc].ref_cnt; + else + { + if(error_info_output_switch) + std::cout<<">> [vm] gc_add_ref:unexpected memory \'"<>8); + int blk_plc=(value_address&0xff); + if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) + --garbage_collector_memory[blk_num][blk_plc].ref_cnt; + else + { + if(error_info_output_switch) + std::cout<<">> [vm] gc_del_ref:unexpected memory \'"<>8); + int blk_plc=(value_address&0xff); + if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected) + return garbage_collector_memory[blk_num][blk_plc].ref_cnt; + else + { + if(error_info_output_switch) + std::cout<<">> [vm] get_refcnt:unexpected memory \'"<del_reference(memory_manager_memory[memory_address>>8][memory_address&0xff]); + memory_manager_free_space.push(memory_address); + } + else + { + if(error_info_output_switch) + std::cout<<">> [vm] mem_free:unexpected memory \'"<del_reference(memory_manager_memory[memory_address>>8][memory_address&0xff]); + memory_manager_memory[memory_address>>8][memory_address&0xff]=value_address; + } + else + { + if(error_info_output_switch) + std::cout<<">> [vm] mem_change:unexpected memory \'"<>8][memory_address&0xff]=value_address; + else + { + if(error_info_output_switch) + std::cout<<">> [vm] mem_init:unexpected memory \'"<>8][memory_address&0xff]; + else + { + if(error_info_output_switch) + std::cout<<">> [vm] mem_get:unexpected memory \'"< filename_table; - int error; - void die(std::string,std::string); - void init(); - bool check_import(nasal_ast&); - bool check_exist(std::string); - void linker(nasal_ast&,nasal_ast&); - nasal_ast file_import(nasal_ast&); - nasal_ast load(nasal_ast&); -public: - nasal_import(); - int get_error(); - void preprocessing(nasal_ast&); - nasal_ast& get_root(); -}; - -nasal_import::nasal_import() -{ - import_src.clear(); - import_lex.clear(); - import_par.clear(); - import_ast.clear(); - filename_table.clear(); - return; -} - -void nasal_import::die(std::string filename,std::string error_stage) -{ - ++error; - std::cout<<">> [import] in <\""<: error(s) occurred in "<& ref_vec=node.get_children(); - if(ref_vec.size()!=2) - return false; - if(ref_vec[0].get_str()!="import") - return false; - if(ref_vec[1].get_type()!=ast_call_func) - return false; - if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string) - return false; - return true; -} - -bool nasal_import::check_exist(std::string filename) -{ - // avoid importing the same file - int size=filename_table.size(); - for(int i=0;i& ref_vec=add_root.get_children(); - int size=ref_vec.size(); - for(int i=0;idie(filename,"resource"); - return tmp; - } - import_lex.scanner(import_src.get_file()); - if(import_lex.get_error()) - { - this->die(filename,"lexer"); - return tmp; - } - import_par.set_toklist(import_lex.get_token_list()); - import_par.main_process(); - if(import_par.get_error()) - { - this->die(filename,"parser"); - return tmp; - } - tmp=import_par.get_root(); - - // check if tmp has 'import' - return load(tmp); -} - -nasal_ast nasal_import::load(nasal_ast& root) -{ - nasal_ast new_root; - new_root.set_line(0); - new_root.set_type(ast_root); - - std::vector& ref_vec=root.get_children(); - int size=ref_vec.size(); - for(int i=0;i filename_table; + int error; + void die(std::string,std::string); + void init(); + bool check_import(nasal_ast&); + bool check_exist(std::string); + void linker(nasal_ast&,nasal_ast&); + nasal_ast file_import(nasal_ast&); + nasal_ast load(nasal_ast&); +public: + nasal_import(); + int get_error(); + void preprocessing(nasal_ast&); + nasal_ast& get_root(); +}; + +nasal_import::nasal_import() +{ + import_src.clear(); + import_lex.clear(); + import_par.clear(); + import_ast.clear(); + filename_table.clear(); + return; +} + +void nasal_import::die(std::string filename,std::string error_stage) +{ + ++error; + std::cout<<">> [import] in <\""<: error(s) occurred in "<& ref_vec=node.get_children(); + if(ref_vec.size()!=2) + return false; + if(ref_vec[0].get_str()!="import") + return false; + if(ref_vec[1].get_type()!=ast_call_func) + return false; + if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string) + return false; + return true; +} + +bool nasal_import::check_exist(std::string filename) +{ + // avoid importing the same file + int size=filename_table.size(); + for(int i=0;i& ref_vec=add_root.get_children(); + int size=ref_vec.size(); + for(int i=0;idie(filename,"resource"); + return tmp; + } + import_lex.scanner(import_src.get_file()); + if(import_lex.get_error()) + { + this->die(filename,"lexer"); + return tmp; + } + import_par.set_toklist(import_lex.get_token_list()); + import_par.main_process(); + if(import_par.get_error()) + { + this->die(filename,"parser"); + return tmp; + } + tmp=import_par.get_root(); + + // check if tmp has 'import' + return load(tmp); +} + +nasal_ast nasal_import::load(nasal_ast& root) +{ + nasal_ast new_root; + new_root.set_line(0); + new_root.set_type(ast_root); + + std::vector& ref_vec=root.get_children(); + int size=ref_vec.size(); + for(int i=0;i= <= -#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~') -#define IS_NOTE_HEAD(c) (c=='#') - -#ifndef TOKEN_TABLE_SIZE -#define TOKEN_TABLE_SIZE 45 -struct token_table -{ - std::string str; - int tok_type; -}tok_tbl[TOKEN_TABLE_SIZE]= -{ - {"for" ,tok_for }, - {"forindex",tok_forindex }, - {"foreach" ,tok_foreach }, - {"while" ,tok_while }, - {"var" ,tok_var }, - {"func" ,tok_func }, - {"break" ,tok_break }, - {"continue",tok_continue }, - {"return" ,tok_return }, - {"if" ,tok_if }, - {"elsif" ,tok_elsif }, - {"else" ,tok_else }, - {"nil" ,tok_nil }, - {"(" ,tok_left_curve }, - {")" ,tok_right_curve }, - {"[" ,tok_left_bracket }, - {"]" ,tok_right_bracket}, - {"{" ,tok_left_brace }, - {"}" ,tok_right_brace }, - {";" ,tok_semi }, - {"and" ,tok_and }, - {"or" ,tok_or }, - {"," ,tok_comma }, - {"." ,tok_dot }, - {"..." ,tok_ellipsis }, - {"?" ,tok_quesmark }, - {":" ,tok_colon }, - {"+" ,tok_add }, - {"-" ,tok_sub }, - {"*" ,tok_mult }, - {"/" ,tok_div }, - {"~" ,tok_link }, - {"!" ,tok_not }, - {"=" ,tok_equal }, - {"+=" ,tok_add_equal }, - {"-=" ,tok_sub_equal }, - {"*=" ,tok_mult_equal }, - {"/=" ,tok_div_equal }, - {"~=" ,tok_link_equal }, - {"==" ,tok_cmp_equal }, - {"!=" ,tok_cmp_not_equal}, - {"<" ,tok_less_than }, - {">" ,tok_greater_than }, - {"<=" ,tok_less_equal }, - {">=" ,tok_greater_equal}, -}; -#endif - -struct token -{ - int line; - int type; - std::string str; -}; - -class nasal_lexer -{ -private: - int error; - std::vector token_list; - std::string identifier_gen(std::vector&,int&,int&); - void generate_number_error(int,std::string); - std::string number_gen(std::vector&,int&,int&); - std::string string_gen(std::vector&,int&,int&); -public: - void clear(); - void scanner(std::vector&); - void print_token(); - int get_error(); - std::vector& get_token_list(); -}; - -void nasal_lexer::clear() -{ - token_list.clear(); - return; -} - -std::string nasal_lexer::identifier_gen(std::vector& res,int& ptr,int& line) -{ - int res_size=res.size(); - std::string token_str=""; - while(ptr> [lexer] line "<& res,int& ptr,int& line) -{ - int res_size=res.size(); - bool scientific_notation=false;// numbers like 1e8 are scientific_notation - std::string token_str=""; - // generate hex number - if(res[ptr]=='0' && ptr+1 0|[1~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) - if(ptr=res_size) - { - generate_number_error(line,token_str); - return "0"; - } - while(ptr=res_size) - { - generate_number_error(line,token_str); - return "0"; - } - if(ptr=res_size) - { - generate_number_error(line,token_str); - return "0"; - } - if(ptr& res,int& ptr,int& line) -{ - int res_size=res.size(); - std::string token_str=""; - char str_begin=res[ptr++]; - if(ptr>=res_size) return token_str; - while(ptr=res_size) - { - ++error; - std::cout<<">> [lexer] line "<& res) -{ - error=0; - token_list.clear(); - int line=1,ptr=0,res_size=res.size(); - std::string token_str; - while(ptr=res_size) break; - if(IS_IDENTIFIER_HEAD(res[ptr])) - { - token_str=identifier_gen(res,ptr,line); - token new_token; - new_token.line=line; - new_token.str=token_str; - new_token.type=0; - for(int i=0;i> [lexer] line "<& nasal_lexer::get_token_list() -{ - return token_list; -} +#ifndef __NASAL_LEXER_H__ +#define __NASAL_LEXER_H__ + +#define IS_IDENTIFIER_HEAD(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')) +#define IS_IDENTIFIER_BODY(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9')) +#define IS_HEX_NUMBER(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F')) +#define IS_OCT_NUMEBR(c) ('0'<=c&&c<='7') +#define IS_DIGIT(c) ('0'<=c&&c<='9') +#define IS_STRING_HEAD(c) (c=='\''||c=='\"') +// single operators have only one character +#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\ + c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\') +// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <= +#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~') +#define IS_NOTE_HEAD(c) (c=='#') + +#ifndef TOKEN_TABLE_SIZE +#define TOKEN_TABLE_SIZE 45 +struct token_table +{ + std::string str; + int tok_type; +}tok_tbl[TOKEN_TABLE_SIZE]= +{ + {"for" ,tok_for }, + {"forindex",tok_forindex }, + {"foreach" ,tok_foreach }, + {"while" ,tok_while }, + {"var" ,tok_var }, + {"func" ,tok_func }, + {"break" ,tok_break }, + {"continue",tok_continue }, + {"return" ,tok_return }, + {"if" ,tok_if }, + {"elsif" ,tok_elsif }, + {"else" ,tok_else }, + {"nil" ,tok_nil }, + {"(" ,tok_left_curve }, + {")" ,tok_right_curve }, + {"[" ,tok_left_bracket }, + {"]" ,tok_right_bracket}, + {"{" ,tok_left_brace }, + {"}" ,tok_right_brace }, + {";" ,tok_semi }, + {"and" ,tok_and }, + {"or" ,tok_or }, + {"," ,tok_comma }, + {"." ,tok_dot }, + {"..." ,tok_ellipsis }, + {"?" ,tok_quesmark }, + {":" ,tok_colon }, + {"+" ,tok_add }, + {"-" ,tok_sub }, + {"*" ,tok_mult }, + {"/" ,tok_div }, + {"~" ,tok_link }, + {"!" ,tok_not }, + {"=" ,tok_equal }, + {"+=" ,tok_add_equal }, + {"-=" ,tok_sub_equal }, + {"*=" ,tok_mult_equal }, + {"/=" ,tok_div_equal }, + {"~=" ,tok_link_equal }, + {"==" ,tok_cmp_equal }, + {"!=" ,tok_cmp_not_equal}, + {"<" ,tok_less_than }, + {">" ,tok_greater_than }, + {"<=" ,tok_less_equal }, + {">=" ,tok_greater_equal}, +}; +#endif + +struct token +{ + int line; + int type; + std::string str; +}; + +class nasal_lexer +{ +private: + int error; + std::vector token_list; + std::string identifier_gen(std::vector&,int&,int&); + void generate_number_error(int,std::string); + std::string number_gen(std::vector&,int&,int&); + std::string string_gen(std::vector&,int&,int&); +public: + void clear(); + void scanner(std::vector&); + void print_token(); + int get_error(); + std::vector& get_token_list(); +}; + +void nasal_lexer::clear() +{ + token_list.clear(); + return; +} + +std::string nasal_lexer::identifier_gen(std::vector& res,int& ptr,int& line) +{ + int res_size=res.size(); + std::string token_str=""; + while(ptr> [lexer] line "<& res,int& ptr,int& line) +{ + int res_size=res.size(); + bool scientific_notation=false;// numbers like 1e8 are scientific_notation + std::string token_str=""; + // generate hex number + if(res[ptr]=='0' && ptr+1 0|[1~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) + if(ptr=res_size) + { + generate_number_error(line,token_str); + return "0"; + } + while(ptr=res_size) + { + generate_number_error(line,token_str); + return "0"; + } + if(ptr=res_size) + { + generate_number_error(line,token_str); + return "0"; + } + if(ptr& res,int& ptr,int& line) +{ + int res_size=res.size(); + std::string token_str=""; + char str_begin=res[ptr++]; + if(ptr>=res_size) return token_str; + while(ptr=res_size) + { + ++error; + std::cout<<">> [lexer] line "<& res) +{ + error=0; + token_list.clear(); + int line=1,ptr=0,res_size=res.size(); + std::string token_str; + while(ptr=res_size) break; + if(IS_IDENTIFIER_HEAD(res[ptr])) + { + token_str=identifier_gen(res,ptr,line); + token new_token; + new_token.line=line; + new_token.str=token_str; + new_token.type=0; + for(int i=0;i> [lexer] line "<& nasal_lexer::get_token_list() +{ + return token_list; +} #endif \ No newline at end of file diff --git a/version3.0/nasal_misc.h b/nasal_misc.h similarity index 95% rename from version3.0/nasal_misc.h rename to nasal_misc.h index 03c2ca8..af8144e 100644 --- a/version3.0/nasal_misc.h +++ b/nasal_misc.h @@ -1,258 +1,258 @@ -#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' - '1e23' - '1E-123' - '1.34E10' -*/ -inline bool check_hex_string(std::string str,int len) -{ - for(int i=2;i'7') - return false; - return true; -} -inline bool check_dec_string(std::string str,int len) -{ - int i=0; - // check integer part - while('0'<=str[i] && str[i]<='9' && i'9') - return false; - } - return true; -} - -bool check_numerable_string(std::string str) -{ - int len=str.length(); - if(!len) return false; - if(str[0]=='-' || str[0]=='+') - { - if(len==1) return false; - std::string tmp=""; - for(int i=1;i2 && str[0]=='0' && str[1]=='x') - return check_hex_string(str,len); - else if(len>2 && str[0]=='0' && str[1]=='o') - return check_oct_string(str,len); - else if('0'<=str[0] && str[0]<='9') - return check_dec_string(str,len); - return false; -} - -/* - trans_string_to_number: - convert string to number -*/ -inline double hex_to_double(std::string str,int len) -{ - double ret=0,num_pow=1; - for(int i=len-1;i>1;--i) - { - if('0'<=str[i] && str[i]<='9') - ret+=num_pow*(str[i]-'0'); - else if('a'<=str[i] && str[i]<='f') - ret+=num_pow*(str[i]-'a'+10); - else if('A'<=str[i] && str[i]<='F') - ret+=num_pow*(str[i]-'A'+10); - num_pow*=16; - } - return ret; -} -inline double oct_to_double(std::string str,int len) -{ - double ret=0,num_pow=1; - for(int i=len-1;i>1;--i) - { - ret+=num_pow*(str[i]-'0'); - num_pow*=8; - } - return ret; -} -inline double dec_to_double(std::string str,int len) -{ - double ret=0; - int i=0; - while('0'<=str[i] && str[i]<='9' && i2 && str[0]=='0' && str[1]=='x') - ret_num=hex_to_double(str,len); - else if(len>2 && str[0]=='0' && str[1]=='o') - ret_num=oct_to_double(str,len); - else if('0'<=str[0] && str[0]<='9') - ret_num=dec_to_double(str,len); - return is_negative?-ret_num:ret_num; -} - -/* - trans_number_to_string: - convert number to string -*/ -std::string trans_number_to_string(double number) -{ - std::string trans_num_string=""; - if(number<0) - { - trans_num_string+='-'; - number=-number; - } - if(number==0) - return "0"; - double integer_bit=1; - while(number>=integer_bit) - integer_bit*=10; - integer_bit/=10; - if(integer_bit==0.1) - trans_num_string+='0'; - while(integer_bit!=0.1) - { - trans_num_string+=(char)('0'+(int(number/integer_bit))); - number-=(double)(int(number/integer_bit))*integer_bit; - integer_bit/=10; - } - if(number!=0) - trans_num_string+='.'; - while(number!=0) - { - trans_num_string+=(char)('0'+int(number*10)); - number*=10; - number-=(double)(int(number)); - } - return trans_num_string; -} - -/* - prt_hex: - transform int to hex format and print it out (std::cout) -*/ -void prt_hex(const int ptr) -{ - char hex[9]; - hex[8]=0; - int tmp_plc=ptr; - if(tmp_plc<0) - { - tmp_plc=-tmp_plc; - std::cout<<"-0x"; - } - 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); - hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10); - tmp_plc>>=4; - } - std::cout<'7') + return false; + return true; +} +inline bool check_dec_string(std::string str,int len) +{ + int i=0; + // check integer part + while('0'<=str[i] && str[i]<='9' && i'9') + return false; + } + return true; +} + +bool check_numerable_string(std::string str) +{ + int len=str.length(); + if(!len) return false; + if(str[0]=='-' || str[0]=='+') + { + if(len==1) return false; + std::string tmp=""; + for(int i=1;i2 && str[0]=='0' && str[1]=='x') + return check_hex_string(str,len); + else if(len>2 && str[0]=='0' && str[1]=='o') + return check_oct_string(str,len); + else if('0'<=str[0] && str[0]<='9') + return check_dec_string(str,len); + return false; +} + +/* + trans_string_to_number: + convert string to number +*/ +inline double hex_to_double(std::string str,int len) +{ + double ret=0,num_pow=1; + for(int i=len-1;i>1;--i) + { + if('0'<=str[i] && str[i]<='9') + ret+=num_pow*(str[i]-'0'); + else if('a'<=str[i] && str[i]<='f') + ret+=num_pow*(str[i]-'a'+10); + else if('A'<=str[i] && str[i]<='F') + ret+=num_pow*(str[i]-'A'+10); + num_pow*=16; + } + return ret; +} +inline double oct_to_double(std::string str,int len) +{ + double ret=0,num_pow=1; + for(int i=len-1;i>1;--i) + { + ret+=num_pow*(str[i]-'0'); + num_pow*=8; + } + return ret; +} +inline double dec_to_double(std::string str,int len) +{ + double ret=0; + int i=0; + while('0'<=str[i] && str[i]<='9' && i2 && str[0]=='0' && str[1]=='x') + ret_num=hex_to_double(str,len); + else if(len>2 && str[0]=='0' && str[1]=='o') + ret_num=oct_to_double(str,len); + else if('0'<=str[0] && str[0]<='9') + ret_num=dec_to_double(str,len); + return is_negative?-ret_num:ret_num; +} + +/* + trans_number_to_string: + convert number to string +*/ +std::string trans_number_to_string(double number) +{ + std::string trans_num_string=""; + if(number<0) + { + trans_num_string+='-'; + number=-number; + } + if(number==0) + return "0"; + double integer_bit=1; + while(number>=integer_bit) + integer_bit*=10; + integer_bit/=10; + if(integer_bit==0.1) + trans_num_string+='0'; + while(integer_bit!=0.1) + { + trans_num_string+=(char)('0'+(int(number/integer_bit))); + number-=(double)(int(number/integer_bit))*integer_bit; + integer_bit/=10; + } + if(number!=0) + trans_num_string+='.'; + while(number!=0) + { + trans_num_string+=(char)('0'+int(number*10)); + number*=10; + number-=(double)(int(number)); + } + return trans_num_string; +} + +/* + prt_hex: + transform int to hex format and print it out (std::cout) +*/ +void prt_hex(const int ptr) +{ + char hex[9]; + hex[8]=0; + int tmp_plc=ptr; + if(tmp_plc<0) + { + tmp_plc=-tmp_plc; + std::cout<<"-0x"; + } + 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); + hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10); + tmp_plc>>=4; + } + std::cout<=tok_list_size? tok_list_size-1:ptr].line) -#endif - -private: - int tok_list_size; - int ptr; - int error; - nasal_ast root; - std::vector tok_list; - void reset(); - bool check_multi_definition(); - bool check_multi_scalar(); - bool check_function_end(nasal_ast&); - bool check_special_call(); - bool need_semi_check(nasal_ast&); - nasal_ast null_node_gen(); - nasal_ast nil_gen(); - nasal_ast number_gen(); - nasal_ast string_gen(); - nasal_ast id_gen(); - nasal_ast vector_gen(); - nasal_ast hash_gen(); - nasal_ast hash_member_gen(); - nasal_ast func_gen(); - nasal_ast args_list_gen(); - nasal_ast expr(); - nasal_ast exprs_gen(); - nasal_ast calculation(); - nasal_ast or_expr(); - nasal_ast and_expr(); - nasal_ast cmp_expr(); - nasal_ast additive_expr(); - nasal_ast multive_expr(); - nasal_ast unary(); - nasal_ast scalar(); - nasal_ast call_scalar(); - nasal_ast call_hash(); - nasal_ast call_vector(); - nasal_ast call_func(); - nasal_ast subvec(); - nasal_ast definition(); - nasal_ast normal_def(); - nasal_ast var_incurve_def(); - nasal_ast var_outcurve_def(); - nasal_ast multi_id(); - nasal_ast multi_scalar(); - nasal_ast multi_assgin(); - nasal_ast loop(); - nasal_ast while_loop(); - nasal_ast for_loop(); - nasal_ast forei_loop(); - nasal_ast new_iter_gen(); - nasal_ast conditional(); - nasal_ast continue_expr(); - nasal_ast break_expr(); - nasal_ast return_expr(); -public: - int get_error(); - void clear(); - void set_toklist(std::vector&); - void main_process(); - nasal_ast& get_root(); -}; - -int nasal_parse::get_error() -{ - return this->error; -} - -void nasal_parse::clear() -{ - this->tok_list_size=0; - this->ptr=0; - this->error=0; - this->tok_list.clear(); - this->root.clear(); - return; -} - -void nasal_parse::set_toklist(std::vector& lex_token) -{ - this->tok_list=lex_token; - this->tok_list_size=this->tok_list.size(); - return; -} - -void nasal_parse::main_process() -{ - this->reset(); - root.set_line(1); - root.set_type(ast_root); - while(ptrptr=0; - this->error=0; - this->root.clear(); - return; -} - -bool nasal_parse::check_multi_definition() -{ - return ptr+1=tok_list_size) return node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_nil); - return node; -} - -nasal_ast nasal_parse::number_gen() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_number); - node.set_str(tok_list[ptr].str); - return node; -} - -nasal_ast nasal_parse::string_gen() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_string); - node.set_str(tok_list[ptr].str); - return node; -} - -nasal_ast nasal_parse::id_gen() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_identifier); - node.set_str(tok_list[ptr].str); - return node; -} - -nasal_ast nasal_parse::vector_gen() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_vector); - ++ptr; - while(ptr=tok_list_size || tok_list[ptr].type!=tok_right_bracket) - { - ++error; - error_info(error_line,lack_right_bracket); - } - return node; -} -nasal_ast nasal_parse::hash_gen() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_hash); - ++ptr; - while (ptr=tok_list_size) break; - if(tok_list[ptr].type==tok_comma) ++ptr; - else if(tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_brace) - { - error_info(error_line,lack_comma); - ++error; - break; - } - } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_brace) - { - ++error; - error_info(error_line,lack_right_brace); - } - return node; -} -nasal_ast nasal_parse::hash_member_gen() -{ - nasal_ast node; - if(ptr>=tok_list_size || (tok_list[ptr].type!=tok_identifier && tok_list[ptr].type!=tok_string)) - { - error_info(error_line,lack_identifier); - ++error; - return node; - } - node.set_line(tok_list[ptr].line); - node.set_type(ast_hashmember); - node.add_child(tok_list[ptr].type==tok_identifier?id_gen():string_gen()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_colon) - { - error_info(error_line,lack_colon); - ++error; - return node; - } - ++ptr; - if(ptr=tok_list_size) - { - error_info(error_line,lack_left_curve); - ++error; - return node; - } - if(tok_list[ptr].type!=tok_left_curve && tok_list[ptr].type!=tok_left_brace) - { - ++error; - error_info(error_line,lack_func_content); - return node; - } - if(tok_list[ptr].type==tok_left_curve) - { - node.add_child(args_list_gen()); - ++ptr; - } - else - { - nasal_ast null_argument_list; - node.add_child(null_argument_list); - } - if(ptr>=tok_list_size) - { - error_info(error_line,lack_left_brace); - ++error; - return node; - } - node.add_child(exprs_gen()); - return node; -} -nasal_ast nasal_parse::args_list_gen() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_args); - ++ptr; - while(ptr=tok_list_size || (tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_curve)) - { - ++error; - error_info(error_line,lack_comma); - return node; - } - if(tok_list[ptr].type==tok_comma) - ++ptr; - } - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_right_curve); - } - - std::string args_format="func("; - int node_child_size=node.get_children().size(); - for(int i=0;i argname_table; - for(int i=0;i=tok_list_size) - { - ++error; - error_info(error_line,lack_exprs); - return node; - } - node.set_line(tok_list[ptr].line); - node.set_type(ast_block); - if(tok_list[ptr].type==tok_left_brace) - { - int left_brace_line=tok_list[ptr].line; - ++ptr; - while(ptr=tok_list_size || tok_list[ptr].type!=tok_right_brace) - { - ++error; - error_info(error_line,lack_semi); - break; - } - } - } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_brace) - { - ++error; - error_info(left_brace_line,exprs_lack_rbrace); - } - } - else - { - node.add_child(expr()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - --ptr; - } - return node; -} -nasal_ast nasal_parse::calculation() -{ - nasal_ast node; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_calculation); - return node; - } - node=or_expr(); - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_colon) - { - ++error; - error_info(error_line,lack_colon); - return node; - } - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - } - } - else - { - ++error; - error_info(error_line,lack_scalar); - return node; - } - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_bracket) - { - ++error; - error_info(error_line,lack_comma); - break; - } - } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_bracket) - { - ++error; - error_info(error_line,lack_right_bracket); - } - return node; -} -nasal_ast nasal_parse::call_func() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_call_func); - bool special_call=check_special_call(); - ++ptr; - while(ptr=tok_list_size || (tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_curve)) - { - ++error; - error_info(error_line,lack_comma); - break; - } - } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - } - return node; -} -nasal_ast nasal_parse::subvec() -{ - nasal_ast node; - if(tok_list[ptr].type==tok_colon) - { - --ptr; - node=nil_gen(); - } - else node=calculation(); - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_equal) - { - ++error; - if(ptr=tok_list_size) - { - ++error; - error_info(error_line,lack_scalar); - return node; - } - if(tok_list[ptr].type==tok_left_curve) - node.add_child(check_multi_scalar()?multi_scalar():calculation()); - else - node.add_child(calculation()); - return node; -} -nasal_ast nasal_parse::normal_def() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_str(tok_list[ptr].str); - node.set_type(ast_identifier); - return node; -} -nasal_ast nasal_parse::var_incurve_def() -{ - nasal_ast node; - ++ptr;// check_multi_definition will check the 'var' - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) - { - ++error; - error_info(error_line,lack_identifier); - return node; - } - node=multi_id(); - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - } - return node; -} -nasal_ast nasal_parse::var_outcurve_def() -{ - nasal_ast node; - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) - { - ++error; - error_info(error_line,lack_identifier); - return node; - } - node=multi_id(); - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - } - return node; -} -nasal_ast nasal_parse::multi_id() -{ - nasal_ast node; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) - { - ++error; - error_info(error_line,lack_identifier); - return node; - } - node.set_line(tok_list[ptr].line); - node.set_type(ast_multi_id); - node.add_child(id_gen()); - ++ptr; - while(ptr=tok_list_size) break; - if(tok_list[ptr].type==tok_comma) ++ptr; - else if(tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_comma); - break; - } - } - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - } - return node; -} -nasal_ast nasal_parse::multi_assgin() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_multi_assign); - node.add_child(multi_scalar()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_equal) - { - ++error; - error_info(error_line,lack_equal); - return node; - } - ++ptr; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,multi_assign_lack_val); - return node; - } - if(tok_list[ptr].type==tok_left_curve) - node.add_child(check_multi_scalar()?multi_scalar():calculation()); - else - node.add_child(calculation()); - return node; -} -nasal_ast nasal_parse::loop() -{ - nasal_ast node; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_token,"loop"); - return node; - } - switch(tok_list[ptr].type) - { - case tok_while: node=while_loop(); break; - case tok_for: node=for_loop(); break; - case tok_forindex: - case tok_foreach: node=forei_loop(); break; - } - return node; -} -nasal_ast nasal_parse::while_loop() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_while); - ++ptr; - if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - return node; - } - ++ptr; - node.add_child(exprs_gen()); - return node; -} -nasal_ast nasal_parse::for_loop() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - node.set_type(ast_for); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_left_curve) - { - ++error; - error_info(error_line,lack_left_curve); - return node; - } - // first expression - ++ptr; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_definition); - return node; - } - if(tok_list[ptr].type==tok_semi) - { - node.add_child(null_node_gen()); - --ptr; - } - else if(tok_list[ptr].type==tok_var) - node.add_child(definition()); - else - node.add_child(calculation()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - { - ++error; - error_info(error_line,lack_semi); - return node; - } - // conditional expression - ++ptr; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_calculation); - return node; - } - if(tok_list[ptr].type==tok_semi) - { - node.add_child(null_node_gen()); - --ptr; - } - else - node.add_child(calculation()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - { - ++error; - error_info(error_line,lack_semi); - return node; - } - //after loop expression - ++ptr; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_calculation); - return node; - } - if(tok_list[ptr].type==tok_right_curve) - { - node.add_child(null_node_gen()); - --ptr; - } - else - node.add_child(calculation()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - return node; - } - ++ptr; - node.add_child(exprs_gen()); - return node; -} -nasal_ast nasal_parse::forei_loop() -{ - nasal_ast node; - node.set_line(tok_list[ptr].line); - switch(tok_list[ptr].type) - { - case tok_forindex: node.set_type(ast_forindex);break; - case tok_foreach: node.set_type(ast_foreach); break; - } - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_left_curve) - { - ++error; - error_info(error_line,lack_left_curve); - return node; - } - // first expression - // foreach/forindex must have an iterator to loop through - ++ptr; - if(ptr>=tok_list_size || (tok_list[ptr].type!=tok_var && tok_list[ptr].type!=tok_identifier)) - { - ++error; - error_info(error_line,lack_loop_iter); - return node; - } - node.add_child(new_iter_gen()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) - { - ++error; - error_info(error_line,lack_semi); - return node; - } - ++ptr; - if(ptr>=tok_list_size) - { - ++error; - error_info(error_line,lack_calculation); - return node; - } - node.add_child(calculation()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - return node; - } - ++ptr; - node.add_child(exprs_gen()); - return node; -} - -nasal_ast nasal_parse::new_iter_gen() -{ - nasal_ast node; - if(tok_list[ptr].type==tok_var) - { - node.set_line(tok_list[ptr].line); - node.set_type(ast_new_iter); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) - { - ++error; - error_info(error_line,lack_identifier); - return node; - } - node.add_child(id_gen()); - } - else - { - node.set_line(tok_list[ptr].line); - node.set_type(ast_call); - node.add_child(id_gen()); - ++ptr; - while(ptr=tok_list_size || tok_list[ptr].type!=tok_left_curve) - { - ++error; - error_info(error_line,lack_left_curve); - return node; - } - ++ptr; - tmp.add_child(calculation()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - return node; - } - ++ptr; - tmp.add_child(exprs_gen()); - node.add_child(tmp); - // end of if-expression - ++ptr; - while(ptr=tok_list_size || tok_list[ptr].type!=tok_left_curve) - { - ++error; - error_info(error_line,lack_left_curve); - return node; - } - tmp.set_line(tok_list[ptr].line); - tmp.set_type(ast_elsif); - tmp.get_children().clear(); - ++ptr; - tmp.add_child(calculation()); - ++ptr; - if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) - { - ++error; - error_info(error_line,lack_right_curve); - return node; - } - ++ptr; - tmp.add_child(exprs_gen()); - node.add_child(tmp); - ++ptr; - } - // end of elsif-expression - // after this process,ptr will point to the next token of exprs_gen()'s last token - // for example - // else if(scalar){} else {} - // ptr^ - if(ptr=tok_list_size? tok_list_size-1:ptr].line) +#endif + +private: + int tok_list_size; + int ptr; + int error; + nasal_ast root; + std::vector tok_list; + void reset(); + bool check_multi_definition(); + bool check_multi_scalar(); + bool check_function_end(nasal_ast&); + bool check_special_call(); + bool need_semi_check(nasal_ast&); + nasal_ast null_node_gen(); + nasal_ast nil_gen(); + nasal_ast number_gen(); + nasal_ast string_gen(); + nasal_ast id_gen(); + nasal_ast vector_gen(); + nasal_ast hash_gen(); + nasal_ast hash_member_gen(); + nasal_ast func_gen(); + nasal_ast args_list_gen(); + nasal_ast expr(); + nasal_ast exprs_gen(); + nasal_ast calculation(); + nasal_ast or_expr(); + nasal_ast and_expr(); + nasal_ast cmp_expr(); + nasal_ast additive_expr(); + nasal_ast multive_expr(); + nasal_ast unary(); + nasal_ast scalar(); + nasal_ast call_scalar(); + nasal_ast call_hash(); + nasal_ast call_vector(); + nasal_ast call_func(); + nasal_ast subvec(); + nasal_ast definition(); + nasal_ast normal_def(); + nasal_ast var_incurve_def(); + nasal_ast var_outcurve_def(); + nasal_ast multi_id(); + nasal_ast multi_scalar(); + nasal_ast multi_assgin(); + nasal_ast loop(); + nasal_ast while_loop(); + nasal_ast for_loop(); + nasal_ast forei_loop(); + nasal_ast new_iter_gen(); + nasal_ast conditional(); + nasal_ast continue_expr(); + nasal_ast break_expr(); + nasal_ast return_expr(); +public: + int get_error(); + void clear(); + void set_toklist(std::vector&); + void main_process(); + nasal_ast& get_root(); +}; + +int nasal_parse::get_error() +{ + return this->error; +} + +void nasal_parse::clear() +{ + this->tok_list_size=0; + this->ptr=0; + this->error=0; + this->tok_list.clear(); + this->root.clear(); + return; +} + +void nasal_parse::set_toklist(std::vector& lex_token) +{ + this->tok_list=lex_token; + this->tok_list_size=this->tok_list.size(); + return; +} + +void nasal_parse::main_process() +{ + this->reset(); + root.set_line(1); + root.set_type(ast_root); + while(ptrptr=0; + this->error=0; + this->root.clear(); + return; +} + +bool nasal_parse::check_multi_definition() +{ + return ptr+1=tok_list_size) return node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_nil); + return node; +} + +nasal_ast nasal_parse::number_gen() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_number); + node.set_str(tok_list[ptr].str); + return node; +} + +nasal_ast nasal_parse::string_gen() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_string); + node.set_str(tok_list[ptr].str); + return node; +} + +nasal_ast nasal_parse::id_gen() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_identifier); + node.set_str(tok_list[ptr].str); + return node; +} + +nasal_ast nasal_parse::vector_gen() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_vector); + ++ptr; + while(ptr=tok_list_size || tok_list[ptr].type!=tok_right_bracket) + { + ++error; + error_info(error_line,lack_right_bracket); + } + return node; +} +nasal_ast nasal_parse::hash_gen() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_hash); + ++ptr; + while (ptr=tok_list_size) break; + if(tok_list[ptr].type==tok_comma) ++ptr; + else if(tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_brace) + { + error_info(error_line,lack_comma); + ++error; + break; + } + } + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_brace) + { + ++error; + error_info(error_line,lack_right_brace); + } + return node; +} +nasal_ast nasal_parse::hash_member_gen() +{ + nasal_ast node; + if(ptr>=tok_list_size || (tok_list[ptr].type!=tok_identifier && tok_list[ptr].type!=tok_string)) + { + error_info(error_line,lack_identifier); + ++error; + return node; + } + node.set_line(tok_list[ptr].line); + node.set_type(ast_hashmember); + node.add_child(tok_list[ptr].type==tok_identifier?id_gen():string_gen()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_colon) + { + error_info(error_line,lack_colon); + ++error; + return node; + } + ++ptr; + if(ptr=tok_list_size) + { + error_info(error_line,lack_left_curve); + ++error; + return node; + } + if(tok_list[ptr].type!=tok_left_curve && tok_list[ptr].type!=tok_left_brace) + { + ++error; + error_info(error_line,lack_func_content); + return node; + } + if(tok_list[ptr].type==tok_left_curve) + { + node.add_child(args_list_gen()); + ++ptr; + } + else + { + nasal_ast null_argument_list; + node.add_child(null_argument_list); + } + if(ptr>=tok_list_size) + { + error_info(error_line,lack_left_brace); + ++error; + return node; + } + node.add_child(exprs_gen()); + return node; +} +nasal_ast nasal_parse::args_list_gen() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_args); + ++ptr; + while(ptr=tok_list_size || (tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_curve)) + { + ++error; + error_info(error_line,lack_comma); + return node; + } + if(tok_list[ptr].type==tok_comma) + ++ptr; + } + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_right_curve); + } + + std::string args_format="func("; + int node_child_size=node.get_children().size(); + for(int i=0;i argname_table; + for(int i=0;i=tok_list_size) + { + ++error; + error_info(error_line,lack_exprs); + return node; + } + node.set_line(tok_list[ptr].line); + node.set_type(ast_block); + if(tok_list[ptr].type==tok_left_brace) + { + int left_brace_line=tok_list[ptr].line; + ++ptr; + while(ptr=tok_list_size || tok_list[ptr].type!=tok_right_brace) + { + ++error; + error_info(error_line,lack_semi); + break; + } + } + } + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_brace) + { + ++error; + error_info(left_brace_line,exprs_lack_rbrace); + } + } + else + { + node.add_child(expr()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) + --ptr; + } + return node; +} +nasal_ast nasal_parse::calculation() +{ + nasal_ast node; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_calculation); + return node; + } + node=or_expr(); + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_colon) + { + ++error; + error_info(error_line,lack_colon); + return node; + } + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + } + } + else + { + ++error; + error_info(error_line,lack_scalar); + return node; + } + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_bracket) + { + ++error; + error_info(error_line,lack_comma); + break; + } + } + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_bracket) + { + ++error; + error_info(error_line,lack_right_bracket); + } + return node; +} +nasal_ast nasal_parse::call_func() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_call_func); + bool special_call=check_special_call(); + ++ptr; + while(ptr=tok_list_size || (tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_curve)) + { + ++error; + error_info(error_line,lack_comma); + break; + } + } + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + } + return node; +} +nasal_ast nasal_parse::subvec() +{ + nasal_ast node; + if(tok_list[ptr].type==tok_colon) + { + --ptr; + node=nil_gen(); + } + else node=calculation(); + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_equal) + { + ++error; + if(ptr=tok_list_size) + { + ++error; + error_info(error_line,lack_scalar); + return node; + } + if(tok_list[ptr].type==tok_left_curve) + node.add_child(check_multi_scalar()?multi_scalar():calculation()); + else + node.add_child(calculation()); + return node; +} +nasal_ast nasal_parse::normal_def() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_str(tok_list[ptr].str); + node.set_type(ast_identifier); + return node; +} +nasal_ast nasal_parse::var_incurve_def() +{ + nasal_ast node; + ++ptr;// check_multi_definition will check the 'var' + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) + { + ++error; + error_info(error_line,lack_identifier); + return node; + } + node=multi_id(); + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + } + return node; +} +nasal_ast nasal_parse::var_outcurve_def() +{ + nasal_ast node; + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) + { + ++error; + error_info(error_line,lack_identifier); + return node; + } + node=multi_id(); + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + } + return node; +} +nasal_ast nasal_parse::multi_id() +{ + nasal_ast node; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) + { + ++error; + error_info(error_line,lack_identifier); + return node; + } + node.set_line(tok_list[ptr].line); + node.set_type(ast_multi_id); + node.add_child(id_gen()); + ++ptr; + while(ptr=tok_list_size) break; + if(tok_list[ptr].type==tok_comma) ++ptr; + else if(tok_list[ptr].type!=tok_comma && tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_comma); + break; + } + } + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + } + return node; +} +nasal_ast nasal_parse::multi_assgin() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_multi_assign); + node.add_child(multi_scalar()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_equal) + { + ++error; + error_info(error_line,lack_equal); + return node; + } + ++ptr; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,multi_assign_lack_val); + return node; + } + if(tok_list[ptr].type==tok_left_curve) + node.add_child(check_multi_scalar()?multi_scalar():calculation()); + else + node.add_child(calculation()); + return node; +} +nasal_ast nasal_parse::loop() +{ + nasal_ast node; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_token,"loop"); + return node; + } + switch(tok_list[ptr].type) + { + case tok_while: node=while_loop(); break; + case tok_for: node=for_loop(); break; + case tok_forindex: + case tok_foreach: node=forei_loop(); break; + } + return node; +} +nasal_ast nasal_parse::while_loop() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_while); + ++ptr; + if(ptr=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + return node; + } + ++ptr; + node.add_child(exprs_gen()); + return node; +} +nasal_ast nasal_parse::for_loop() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + node.set_type(ast_for); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_left_curve) + { + ++error; + error_info(error_line,lack_left_curve); + return node; + } + // first expression + ++ptr; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_definition); + return node; + } + if(tok_list[ptr].type==tok_semi) + { + node.add_child(null_node_gen()); + --ptr; + } + else if(tok_list[ptr].type==tok_var) + node.add_child(definition()); + else + node.add_child(calculation()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) + { + ++error; + error_info(error_line,lack_semi); + return node; + } + // conditional expression + ++ptr; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_calculation); + return node; + } + if(tok_list[ptr].type==tok_semi) + { + node.add_child(null_node_gen()); + --ptr; + } + else + node.add_child(calculation()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) + { + ++error; + error_info(error_line,lack_semi); + return node; + } + //after loop expression + ++ptr; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_calculation); + return node; + } + if(tok_list[ptr].type==tok_right_curve) + { + node.add_child(null_node_gen()); + --ptr; + } + else + node.add_child(calculation()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + return node; + } + ++ptr; + node.add_child(exprs_gen()); + return node; +} +nasal_ast nasal_parse::forei_loop() +{ + nasal_ast node; + node.set_line(tok_list[ptr].line); + switch(tok_list[ptr].type) + { + case tok_forindex: node.set_type(ast_forindex);break; + case tok_foreach: node.set_type(ast_foreach); break; + } + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_left_curve) + { + ++error; + error_info(error_line,lack_left_curve); + return node; + } + // first expression + // foreach/forindex must have an iterator to loop through + ++ptr; + if(ptr>=tok_list_size || (tok_list[ptr].type!=tok_var && tok_list[ptr].type!=tok_identifier)) + { + ++error; + error_info(error_line,lack_loop_iter); + return node; + } + node.add_child(new_iter_gen()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_semi) + { + ++error; + error_info(error_line,lack_semi); + return node; + } + ++ptr; + if(ptr>=tok_list_size) + { + ++error; + error_info(error_line,lack_calculation); + return node; + } + node.add_child(calculation()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + return node; + } + ++ptr; + node.add_child(exprs_gen()); + return node; +} + +nasal_ast nasal_parse::new_iter_gen() +{ + nasal_ast node; + if(tok_list[ptr].type==tok_var) + { + node.set_line(tok_list[ptr].line); + node.set_type(ast_new_iter); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_identifier) + { + ++error; + error_info(error_line,lack_identifier); + return node; + } + node.add_child(id_gen()); + } + else + { + node.set_line(tok_list[ptr].line); + node.set_type(ast_call); + node.add_child(id_gen()); + ++ptr; + while(ptr=tok_list_size || tok_list[ptr].type!=tok_left_curve) + { + ++error; + error_info(error_line,lack_left_curve); + return node; + } + ++ptr; + tmp.add_child(calculation()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + return node; + } + ++ptr; + tmp.add_child(exprs_gen()); + node.add_child(tmp); + // end of if-expression + ++ptr; + while(ptr=tok_list_size || tok_list[ptr].type!=tok_left_curve) + { + ++error; + error_info(error_line,lack_left_curve); + return node; + } + tmp.set_line(tok_list[ptr].line); + tmp.set_type(ast_elsif); + tmp.get_children().clear(); + ++ptr; + tmp.add_child(calculation()); + ++ptr; + if(ptr>=tok_list_size || tok_list[ptr].type!=tok_right_curve) + { + ++error; + error_info(error_line,lack_right_curve); + return node; + } + ++ptr; + tmp.add_child(exprs_gen()); + node.add_child(tmp); + ++ptr; + } + // end of elsif-expression + // after this process,ptr will point to the next token of exprs_gen()'s last token + // for example + // else if(scalar){} else {} + // ptr^ + if(ptr res; -public: - bool input_file(std::string); - void clear(); - void print_file(); - std::vector& get_file(); -}; - -bool nasal_resource::input_file(std::string filename) -{ - res.clear(); - std::ifstream fin(filename,std::ios::binary); - if(fin.fail()) - { - std::cout<<">> [resource] cannot open file \""<=0 && unicode_str.length()) - { - std::cout<& nasal_resource::get_file() -{ - return res; -} - +#ifndef __NASAL_RESOURCE_H__ +#define __NASAL_RESOURCE_H__ + +class nasal_resource +{ +private: + std::vector res; +public: + bool input_file(std::string); + void clear(); + void print_file(); + std::vector& get_file(); +}; + +bool nasal_resource::input_file(std::string filename) +{ + res.clear(); + std::ifstream fin(filename,std::ios::binary); + if(fin.fail()) + { + std::cout<<">> [resource] cannot open file \""<=0 && unicode_str.length()) + { + std::cout<& nasal_resource::get_file() +{ + return res; +} + #endif \ No newline at end of file diff --git a/version3.0/nasal_runtime.h b/nasal_runtime.h similarity index 97% rename from version3.0/nasal_runtime.h rename to nasal_runtime.h index ff970c4..de21035 100644 --- a/version3.0/nasal_runtime.h +++ b/nasal_runtime.h @@ -1,1661 +1,1661 @@ -#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: - std::map builtin_func_hashmap; - // function_return_address is an address in garbage_collector_memory - int function_returned_address; - // global_scope_address is an address in garbage_collector_memory - int global_scope_address; - - nasal_ast root; - - // if error occurred,this value will add 1 - int error; - - // 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&,std::string,int,int,int); - int call_builtin_function(std::string,int); - // get scalars' memory place in complex data structure like vector/hash/function/closure(scope) - int call_scalar_mem(nasal_ast&,int); - int call_vector_mem(nasal_ast&,int,int); - int call_hash_mem(nasal_ast&,int,int); - // calculate scalars - int calculation(nasal_ast&,int); - void definition(nasal_ast&,int); - void multi_assignment(nasal_ast&,int); - - // builtin_func defined here - int builtin_print(int); - int builtin_append(int); - int builtin_setsize(int); - int builtin_system(int); - int builtin_input(int); - int builtin_sleep(int); - int builtin_finput(int); - int builtin_foutput(int); - int builtin_split(int); - int builtin_rand(int); - int builtin_id(int); - int builtin_int(int); - int builtin_num(int); - int builtin_pop(int); - int builtin_str(int); - int builtin_size(int); - int builtin_xor(int); - int builtin_and(int); - int builtin_or(int); - int builtin_nand(int); - int builtin_not(int); - int builtin_sin(int); - int builtin_cos(int); - int builtin_tan(int); - int builtin_exp(int); - int builtin_ln(int); - int builtin_sqrt(int); - int builtin_atan2(int); - int builtin_time(int); - int builtin_contains(int); - int builtin_delete(int); - int builtin_getkeys(int); - int builtin_import(int); - int builtin_die(int); - int builtin_type(int); - void load_builtin_function(); -public: - nasal_runtime(); - ~nasal_runtime(); - void set_root(nasal_ast&); - void run(); -}; - -nasal_runtime::nasal_runtime() -{ - error=0; - this->root.clear(); - this->global_scope_address=-1; - this->load_builtin_function(); - return; -} -nasal_runtime::~nasal_runtime() -{ - error=0; - this->root.clear(); - this->global_scope_address=-1; - this->builtin_func_hashmap.clear(); - return; -} -void nasal_runtime::load_builtin_function() -{ - struct FUNC_TABLE - { - std::string func_name; - int (nasal_runtime::*func_pointer)(int x); - } builtin_func_table[]= - { - {"nasal_call_builtin_std_cout", nasal_runtime::builtin_print}, - {"nasal_call_builtin_push_back", nasal_runtime::builtin_append}, - {"nasal_call_builtin_set_size", nasal_runtime::builtin_setsize}, - {"nasal_call_builtin_system", nasal_runtime::builtin_system}, - {"nasal_call_builtin_input", nasal_runtime::builtin_input}, - {"nasal_call_builtin_sleep", nasal_runtime::builtin_sleep}, - {"nasal_call_builtin_finput", nasal_runtime::builtin_finput}, - {"nasal_call_builtin_foutput", nasal_runtime::builtin_foutput}, - {"nasal_call_builtin_split", nasal_runtime::builtin_split}, - {"nasal_call_builtin_rand", nasal_runtime::builtin_rand}, - {"nasal_call_builtin_get_id", nasal_runtime::builtin_id}, - {"nasal_call_builtin_trans_int", nasal_runtime::builtin_int}, - {"nasal_call_builtin_trans_num", nasal_runtime::builtin_num}, - {"nasal_call_builtin_pop_back", nasal_runtime::builtin_pop}, - {"nasal_call_builtin_trans_str", nasal_runtime::builtin_str}, - {"nasal_call_builtin_size", nasal_runtime::builtin_size}, - {"nasal_call_builtin_xor", nasal_runtime::builtin_xor}, - {"nasal_call_builtin_and", nasal_runtime::builtin_and}, - {"nasal_call_builtin_or", nasal_runtime::builtin_or}, - {"nasal_call_builtin_nand", nasal_runtime::builtin_nand}, - {"nasal_call_builtin_not", nasal_runtime::builtin_not}, - {"nasal_call_builtin_sin", nasal_runtime::builtin_sin}, - {"nasal_call_builtin_cos", nasal_runtime::builtin_cos}, - {"nasal_call_builtin_tan", nasal_runtime::builtin_tan}, - {"nasal_call_builtin_exp", nasal_runtime::builtin_exp}, - {"nasal_call_builtin_cpp_math_ln", nasal_runtime::builtin_ln}, - {"nasal_call_builtin_cpp_math_sqrt", nasal_runtime::builtin_sqrt}, - {"nasal_call_builtin_cpp_atan2", nasal_runtime::builtin_atan2}, - {"nasal_call_builtin_time", nasal_runtime::builtin_time}, - {"nasal_call_builtin_contains", nasal_runtime::builtin_contains}, - {"nasal_call_builtin_delete", nasal_runtime::builtin_delete}, - {"nasal_call_builtin_get_keys", nasal_runtime::builtin_getkeys}, - {"nasal_call_import", nasal_runtime::builtin_import}, - {"nasal_call_builtin_die", nasal_runtime::builtin_die}, - {"nasal_call_builtin_type", nasal_runtime::builtin_type}, - {"", NULL} - }; - for(int i=0;builtin_func_table[i].func_pointer;++i) - builtin_func_hashmap[builtin_func_table[i].func_name]=builtin_func_table[i].func_pointer; - return; -} -void nasal_runtime::set_root(nasal_ast& parse_result) -{ - this->root=parse_result; - return; -} -void nasal_runtime::run() -{ - this->error=0; - this->function_returned_address=-1; - - 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(); - - time_t begin_time=std::time(NULL); - int returned_statement=main_progress(); - time_t end_time=std::time(NULL); - - nasal_vm.gc_get(global_scope_address).get_closure().del_scope(); - nasal_vm.del_reference(global_scope_address); - nasal_vm.clear(); - - time_t total_run_time=end_time-begin_time; - if(total_run_time>=1) - std::cout<<">> [runtime] process exited after "<=0) - ref_of_this_function.set_closure_addr(local_scope_addr); - else - { - int new_closure=nasal_vm.gc_alloc(); - nasal_vm.gc_get(new_closure).set_type(vm_closure); - ref_of_this_function.set_closure_addr(new_closure); - nasal_vm.del_reference(new_closure); - } - 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.\n";++error;break; - case rt_continue:std::cout<<">> [runtime] main_progress: cannot use continue in main progress.\n";++error;break; - case rt_return:std::cout<<">> [runtime] main_progress: cannot use return in main progress.\n";++error;break; - case rt_error:std::cout<<">> [runtime] main_progress: error occurred when executing main progress.\n";++error;break; - } - if(error) - { - ret_state=rt_error; - break; - } - } - return ret_state; -} -int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allow_return) -{ - int ret_state=rt_exit_without_error; - // if local_scope does not exist,create a new one. - if(local_scope_addr<0) - { - local_scope_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(local_scope_addr).set_type(vm_closure); - nasal_vm.gc_get(local_scope_addr).get_closure().add_scope(); - } - else - { - nasal_vm.add_reference(local_scope_addr); - nasal_vm.gc_get(local_scope_addr).get_closure().add_scope(); - } - int expr_number=node.get_children().size(); - int process_returned_value_addr=-1; - for(int i=0;i> [runtime] block_progress: return expression is not allowed here.\n"; - ++error; - } - break; - } - if(ret_state==rt_error) - { - std::cout<<">> [runtime] block_progress: error occurred when executing sub-progress.\n"; - ++error; - } - if(error || ret_state==rt_break || ret_state==rt_continue || ret_state==rt_return) - break; - } - nasal_vm.gc_get(local_scope_addr).get_closure().del_scope(); - nasal_vm.del_reference(local_scope_addr); - return ret_state; -} -int nasal_runtime::before_for_loop(nasal_ast& node,int local_scope_addr) -{ - int before_loop_node_type=node.get_type(); - switch(before_loop_node_type) - { - case ast_null:break; - case ast_definition:definition(node,local_scope_addr);break; - case ast_multi_assign:multi_assignment(node,local_scope_addr);break; - case ast_nil:case ast_number:case ast_string:case ast_function:break; - case ast_vector:case ast_hash: - case ast_call: - case ast_equal:case ast_add_equal:case ast_sub_equal:case ast_mult_equal:case ast_div_equal:case ast_link_equal: - case ast_unary_sub:case ast_unary_not: - case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link: - case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break; - default:std::cout<<">> [runtime] before_for_loop: cannot use this expression before for-loop.\n";++error;break; - } - if(error) - return rt_error; - return rt_exit_without_error; -} -int nasal_runtime::after_each_for_loop(nasal_ast& node,int local_scope_addr) -{ - int node_type=node.get_type(); - switch(node_type) - { - case ast_null:break; - case ast_definition:definition(node,local_scope_addr);break; - case ast_multi_assign:multi_assignment(node,local_scope_addr);break; - case ast_nil:case ast_number:case ast_string:case ast_function:break; - case ast_vector:case ast_hash: - case ast_call: - case ast_equal:case ast_add_equal:case ast_sub_equal:case ast_mult_equal:case ast_div_equal:case ast_link_equal: - case ast_unary_sub:case ast_unary_not: - case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link: - case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break; - default:std::cout<<">> [runtime] after_each_for_loop: cannot use this expression after each for-loop.\n";++error;break; - } - if(error) - return rt_error; - return rt_exit_without_error; -} -int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow_return) -{ - int ret_state=rt_exit_without_error; - int loop_type=node.get_type(); - if(loop_type==ast_while) - { - nasal_ast& condition_node=node.get_children()[0]; - nasal_ast& run_block_node=node.get_children()[1]; - // create a new local scope to store iterator if local_scope_addr=-1 - int while_local_scope_addr=local_scope_addr; - if(while_local_scope_addr<0) - { - while_local_scope_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(while_local_scope_addr).set_type(vm_closure); - nasal_vm.gc_get(while_local_scope_addr).get_closure().add_scope(); - } - else - { - nasal_vm.add_reference(local_scope_addr); - nasal_vm.gc_get(while_local_scope_addr).get_closure().add_scope(); - } - // check condition and begin loop - int condition_value_addr=calculation(condition_node,while_local_scope_addr); - bool result=check_condition(condition_value_addr); - nasal_vm.del_reference(condition_value_addr); - while(result) - { - // return expression will be checked in block_progress - ret_state=block_progress(run_block_node,local_scope_addr,allow_return); - if(ret_state==rt_break || ret_state==rt_error || ret_state==rt_return || error) - break; - condition_value_addr=calculation(condition_node,while_local_scope_addr); - result=check_condition(condition_value_addr); - nasal_vm.del_reference(condition_value_addr); - } - nasal_vm.gc_get(while_local_scope_addr).get_closure().del_scope(); - nasal_vm.del_reference(while_local_scope_addr); - } - else if(loop_type==ast_forindex || loop_type==ast_foreach) - { - nasal_ast& iter_node=node.get_children()[0]; - nasal_ast& vector_node=node.get_children()[1]; - nasal_ast& run_block_node=node.get_children()[2]; - // check vector to make sure iterator can be used without problem - int vector_value_addr=calculation(vector_node,local_scope_addr); - if(vector_value_addr<0 || nasal_vm.gc_get(vector_value_addr).get_type()!=vm_vector) - { - std::cout<<">> [runtime] loop_progress: "<<(loop_type==ast_forindex? "forindex":"foreach")<<" gets a value that is not a vector.\n"; - ++error; - return rt_error; - } - // create a new local scope to store iterator if local_scope_addr=-1 - int forei_local_scope_addr=local_scope_addr; - if(forei_local_scope_addr<0) - { - forei_local_scope_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(forei_local_scope_addr).set_type(vm_closure); - nasal_vm.gc_get(forei_local_scope_addr).get_closure().add_scope(); - } - else - { - nasal_vm.add_reference(local_scope_addr); - nasal_vm.gc_get(forei_local_scope_addr).get_closure().add_scope(); - } - // begin loop progress - int mem_addr=-1; - if(iter_node.get_type()==ast_new_iter) - { - int new_value_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(new_value_addr).set_type(vm_nil); - std::string val_name=iter_node.get_children()[0].get_str(); - nasal_vm.gc_get(forei_local_scope_addr).get_closure().add_new_value(val_name,new_value_addr); - mem_addr=nasal_vm.gc_get(forei_local_scope_addr).get_closure().get_mem_address(val_name); - } - else - mem_addr=call_scalar_mem(iter_node,local_scope_addr); - if(mem_addr<0) - { - std::cout<<">> [runtime] loop_progress: get null iterator.\n"; - ++error; - return rt_error; - } - // ref_vector's size may change when running,so this loop will check size each time - nasal_vector& ref_vector=nasal_vm.gc_get(vector_value_addr).get_vector(); - for(int i=0;i> [runtime] check_condition: error value type when checking condition.\n"; - ++error; - return false; - } - else if(type==vm_string) - { - std::string str=nasal_vm.gc_get(value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] check_condition: error value type, \'"<=0) - value_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(val_name); - if(value_address<0) - value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(val_name); - if(value_address<0) - { - value_address=call_builtin_function(val_name,local_scope_addr); - if(value_address>=0) - return value_address; - } - if(value_address<0) - { - if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end()) - std::cout<<">> [runtime] call_scalar: call "<> [runtime] call_scalar: cannot find value named \""<> [runtime] call_vector: incorrect value type,expected a vector/hash/string.\n"; - ++error; - return -1; - } - int call_size=node.get_children().size(); - - if(base_value_type==vm_vector) - { - std::vector 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.\n"; - ++error; - return -1; - } - if(end_value_type!=vm_nil && end_value_type!=vm_number && end_value_type!=vm_string) - { - std::cout<<">> [runtime] call_vector: end index is not a number/numerable string.\n"; - ++error; - return -1; - } - if(begin_value_type==vm_string) - { - std::string str=nasal_vm.gc_get(begin_value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] call_vector: begin index is not a numerable string.\n"; - ++error; - return -1; - } - begin_index=(int)trans_string_to_number(str); - begin_is_nil=false; - } - else if(begin_value_type==vm_number) - { - begin_index=(int)nasal_vm.gc_get(begin_value_addr).get_number(); - begin_is_nil=false; - } - - if(end_value_type==vm_string) - { - std::string str=nasal_vm.gc_get(end_value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] call_vector: end index is not a numerable string.\n"; - ++error; - return -1; - } - end_index=(int)trans_string_to_number(str); - end_is_nil=false; - } - else if(end_value_type==vm_number) - { - end_index=(int)nasal_vm.gc_get(end_value_addr).get_number(); - end_is_nil=false; - } - - if(begin_is_nil && end_is_nil) - { - begin_index=0; - end_index=reference_value.size()-1; - } - else if(begin_is_nil && !end_is_nil) - { - begin_index=end_index<0? -reference_value.size():0; - } - else if(!begin_is_nil && end_is_nil) - { - end_index=begin_index<0? -1:reference_value.size()-1; - } - else if(!begin_is_nil && !end_is_nil) - { - if(begin_index>=end_index) - { - std::cout<<">> [runtime] call_vector: begin index must be less than end index.\n"; - ++error; - return -1; - } - } - for(int i=begin_index;i> [runtime] call_vector: index is not a number/numerable string.\n"; - ++error; - return -1; - } - int index_num=0; - if(index_value_type==vm_string) - { - std::string str=nasal_vm.gc_get(index_value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] call_vector: index is not a numerable string.\n"; - ++error; - return -1; - } - index_num=(int)trans_string_to_number(str); - } - else - index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); - nasal_vm.del_reference(index_value_addr); - called_value_addrs.push_back(reference_value.get_value_address(index_num)); - } - } - // generate sub-vector - if(called_value_addrs.size()==1) - { - int value_addr=called_value_addrs[0]; - nasal_vm.add_reference(value_addr); - return_value_addr=value_addr; - } - else - { - return_value_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(return_value_addr).set_type(vm_vector); - nasal_vector& return_vector=nasal_vm.gc_get(return_value_addr).get_vector(); - int vec_size=called_value_addrs.size(); - for(int i=0;i1) - { - std::cout<<">> [runtime] call_vector: when calling a hash,only one key is alowed.\n"; - ++error; - return -1; - } - if(node.get_children()[0].get_type()==ast_subvec) - { - std::cout<<">> [runtime] call_vector: cannot slice hash.\n"; - ++error; - return -1; - } - std::string str=node.get_children()[0].get_str(); - int value_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_value_address(str); - nasal_vm.add_reference(value_addr); - return_value_addr=value_addr; - } - else - { - if(call_size>1) - { - std::cout<<">> [runtime] call_vector: when calling a string,only one index is alowed.\n"; - ++error; - return -1; - } - if(node.get_children()[0].get_type()==ast_subvec) - { - std::cout<<">> [runtime] call_vector: cannot slice string.\n"; - ++error; - return -1; - } - int index_value_addr=calculation(node.get_children()[0],local_scope_addr); - int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); - if(index_value_type!=vm_number && index_value_type!=vm_string) - { - std::cout<<">> [runtime] call_vector: index is not a number/numerable string.\n"; - ++error; - return -1; - } - int index_num=0; - if(index_value_type==vm_string) - { - std::string str=nasal_vm.gc_get(index_value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] call_vector: index is not a numerable string.\n"; - ++error; - return -1; - } - index_num=(int)trans_string_to_number(str); - } - else - index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); - nasal_vm.del_reference(index_value_addr); - return_value_addr=nasal_vm.gc_alloc(); - nasal_vm.gc_get(return_value_addr).set_type(vm_number); - std::string str=nasal_vm.gc_get(base_value_addr).get_string(); - int str_size=str.length(); - if(index_num>=str_size || index_num<-str_size) - { - std::cout<<">> [runtime] call_vector: index out of range.\n"; - ++error; - return -1; - } - nasal_vm.gc_get(return_value_addr).set_number((double)str[(index_num+str_size)%str_size]); - } - return return_value_addr; -} -int nasal_runtime::call_hash(nasal_ast& node,int base_value_addr,int local_scope_addr) -{ - int value_type=nasal_vm.gc_get(base_value_addr).get_type(); - if(value_type!=vm_hash) - { - std::cout<<">> [runtime] call_hash: incorrect value type,expected a hash.\n"; - ++error; - return -1; - } - int ret_value_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_value_address(node.get_str()); - nasal_vm.add_reference(ret_value_addr); - return ret_value_addr; -} -int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_value_addr,int last_call_hash_addr,int local_scope_addr) -{ - int ret_value_addr=-1; - int value_type=nasal_vm.gc_get(base_value_addr).get_type(); - if(value_type!=vm_function) - { - std::cout<<">> [runtime] call_function: incorrect value type,expected a function.\n"; - ++error; - return -1; - } - nasal_function& reference_of_func=nasal_vm.gc_get(base_value_addr).get_func(); - int run_closure_addr=reference_of_func.get_closure_addr(); - nasal_closure& run_closure=nasal_vm.gc_get(run_closure_addr).get_closure(); - run_closure.add_scope(); - // set self - if(func_name.length()) - { - nasal_vm.add_reference(base_value_addr); - run_closure.add_new_value(func_name,base_value_addr); - } - // set hash.me - if(last_call_hash_addr>=0) - { - nasal_vm.add_reference(last_call_hash_addr); - run_closure.add_new_value("me",last_call_hash_addr); - } - nasal_ast& argument_format=reference_of_func.get_arguments(); - if(!node.get_children().size()) - { - if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()!=ast_default_arg && argument_format.get_children()[0].get_type()!=ast_dynamic_id) - { - int size=argument_format.get_children().size(); - int sum=0; - for(int i=0;i> [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.\n"; - ++error; - return -1; - } - } - else - { - std::vector 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.\n"; - ++error; - return -1; - } - args.push_back(tmp_val_addr); - } - int arg_format_size=argument_format.get_children().size(); - if(size>arg_format_size && argument_format.get_children().back().get_type()!=ast_dynamic_id) - { - std::cout<<">> [runtime] call_function: too much arguments.\n"; - ++error; - return -1; - } - for(int i=0;i> [runtime] call_function: lack argument(s).stop.\n"; - ++error; - return -1; - } - } - else // default_args - { - if(i> [runtime] call_function: break and continue are not allowed to be used here.\n"; - ++error; - return -1; - } - else if(ret_state==rt_error) - return -1; - - if(function_returned_address>=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_builtin_function(std::string val_name,int local_scope_addr) -{ - int ret_value_addr=-1; - int builtin_func_num=-1; - if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end()) - ret_value_addr=(this->*builtin_func_hashmap[val_name])(local_scope_addr); - return ret_value_addr; -} -int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr) -{ - int mem_address=-1; - if(node.get_type()==ast_identifier) - { - if(local_scope_addr>=0) - mem_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_mem_address(node.get_str()); - if(mem_address<0) - mem_address=nasal_vm.gc_get(global_scope_address).get_closure().get_mem_address(node.get_str()); - if(mem_address<0) - { - std::cout<<">> [runtime] call_scalar_mem: cannot find value named \'"<=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.\n"; - ++error; - return -1; - break; - } - mem_address=tmp_mem_addr; - if(mem_address<0) - { - ++error; - std::cout<<">> [runtime] call_scalar_mem: cannot find correct memory space.\n"; - break; - } - } - return mem_address; -} -int nasal_runtime::call_vector_mem(nasal_ast& node,int base_mem_addr,int local_scope_addr) -{ - int return_mem_addr=-1; - int base_value_addr=nasal_vm.mem_get(base_mem_addr); - int base_value_type=nasal_vm.gc_get(base_value_addr).get_type(); - if(base_value_type!=vm_vector && base_value_type!=vm_hash) - { - std::cout<<">> [runtime] call_vector_mem: incorrect value type,expected a vector/hash.\n"; - ++error; - return -1; - } - int call_size=node.get_children().size(); - if(call_size>1) - { - std::cout<<">> [runtime] call_vector_mem: when searching a memory space in a vector,only one index is alowed.\n"; - ++error; - return -1; - } - if(base_value_type==vm_vector) - { - nasal_vector& reference_value=nasal_vm.gc_get(base_value_addr).get_vector(); - if(node.get_children()[0].get_type()==ast_subvec) - { - std::cout<<">> [runtime] call_vector_mem: sub-vector in this progress is a temporary value and cannot be changed.\n"; - ++error; - return -1; - } - int index_value_addr=calculation(node.get_children()[0],local_scope_addr); - int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); - if(index_value_type!=vm_number && index_value_type!=vm_string) - { - std::cout<<">> [runtime] call_vector_mem: index is not a number/numerable string.\n"; - ++error; - return -1; - } - int index_num=0; - if(index_value_type==vm_string) - { - std::string str=nasal_vm.gc_get(index_value_addr).get_string(); - if(!check_numerable_string(str)) - { - std::cout<<">> [runtime] call_vector_mem: index is not a numerable string.\n"; - ++error; - return -1; - } - index_num=(int)trans_string_to_number(str); - } - else - index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); - nasal_vm.del_reference(index_value_addr); - return_mem_addr=reference_value.get_mem_address(index_num); - } - else - { - if(call_size>1) - { - std::cout<<">> [runtime] call_vector_mem: when calling a hash,only one key is alowed.\n"; - ++error; - return -1; - } - std::string str=node.get_children()[0].get_str(); - return_mem_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_mem_address(str); - } - return return_mem_addr; -} -int nasal_runtime::call_hash_mem(nasal_ast& node,int base_mem_addr,int local_scope_addr) -{ - int base_value_addr=nasal_vm.mem_get(base_mem_addr); - int value_type=nasal_vm.gc_get(base_value_addr).get_type(); - if(value_type!=vm_hash) - { - std::cout<<">> [runtime] call_hash_mem: incorrect value type,expected a hash.\n"; - ++error; - return -1; - } - int ret_mem_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_mem_address(node.get_str()); - return ret_mem_addr; -} -int nasal_runtime::calculation(nasal_ast& node,int local_scope_addr) -{ - // after this process, a new address(in nasal_vm.garbage_collector_memory) will be returned - int ret_address=-1; - int calculation_type=node.get_type(); - if(calculation_type==ast_nil) - { - ret_address=nasal_vm.gc_alloc(); - nasal_vm.gc_get(ret_address).set_type(vm_nil); - } - else if(calculation_type==ast_number) - ret_address=number_generation(node); - else if(calculation_type==ast_string) - ret_address=string_generation(node); - else if(calculation_type==ast_identifier) - { - if(local_scope_addr>=0) - ret_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(node.get_str()); - if(ret_address<0) - ret_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(node.get_str()); - if(ret_address<0) - { - std::cout<<">> [runtime] calculation: cannot find value named \'"<> [runtime] calculation: this expression cannot be calculated.expression type:"<> [runtime] calculation: incorrect values are used in calculation.\n"; - ++error; - } - return ret_address; -} -void nasal_runtime::definition(nasal_ast& node,int local_scope_addr) -{ - nasal_ast& define_node=node.get_children()[0]; - nasal_ast& value_node=node.get_children()[1]; - if(define_node.get_type()==ast_identifier && value_node.get_type()==ast_multi_scalar) - { - std::cout<<">> [runtime] definition: one identifier cannot accept too many values.\n"; - ++error; - return; - } - if(define_node.get_type()==ast_identifier) - { - std::string new_name=define_node.get_str(); - int value_addr=calculation(value_node,local_scope_addr); - if(value_addr<0) - return; - nasal_vm.gc_get(local_scope_addr<0?global_scope_address:local_scope_addr).get_closure().add_new_value(new_name,value_addr); - } - else - { - std::vector identifier_table; - int id_size=define_node.get_children().size(); - for(int i=0;i> [runtime] definition: size of identifiers and size of values do not match.\n"; - ++error; - return; - } - for(int i=0;i> [runtime] definition: must use vector in multi-definition.\n"; - ++error; - return; - } - nasal_vector& ref_vector=nasal_vm.gc_get(value_addr).get_vector(); - if(ref_vector.size()!=id_size) - { - std::cout<<">> [runtime] definition: size of identifiers and size of values do not match.\n"; - ++error; - return; - } - for(int i=0;i 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.\n"; - ++error; - return; - } - mem_table.push_back(call_scalar_mem(tmp_node,local_scope_addr)); - } - if(value_node.get_type()==ast_multi_scalar) - { - int val_size=value_node.get_children().size(); - if(id_size!=val_size) - { - std::cout<<">> [runtime] multi_assignment: size of calls and size of values do not match.\n"; - ++error; - return; - } - std::vector value_table; - for(int i=0;i> [runtime] multi_assignment: must use vector in multi-assignment.\n"; - ++error; - return; - } - nasal_vector& ref_vector=nasal_vm.gc_get(value_addr).get_vector(); - if(ref_vector.size()!=id_size) - { - std::cout<<">> [runtime] multi_assignment: size of calls and size of values do not match.\n"; - ++error; - return; - } - std::vector value_table; - for(int i=0;i builtin_func_hashmap; + // function_return_address is an address in garbage_collector_memory + int function_returned_address; + // global_scope_address is an address in garbage_collector_memory + int global_scope_address; + + nasal_ast root; + + // if error occurred,this value will add 1 + int error; + + // 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&,std::string,int,int,int); + int call_builtin_function(std::string,int); + // get scalars' memory place in complex data structure like vector/hash/function/closure(scope) + int call_scalar_mem(nasal_ast&,int); + int call_vector_mem(nasal_ast&,int,int); + int call_hash_mem(nasal_ast&,int,int); + // calculate scalars + int calculation(nasal_ast&,int); + void definition(nasal_ast&,int); + void multi_assignment(nasal_ast&,int); + + // builtin_func defined here + int builtin_print(int); + int builtin_append(int); + int builtin_setsize(int); + int builtin_system(int); + int builtin_input(int); + int builtin_sleep(int); + int builtin_finput(int); + int builtin_foutput(int); + int builtin_split(int); + int builtin_rand(int); + int builtin_id(int); + int builtin_int(int); + int builtin_num(int); + int builtin_pop(int); + int builtin_str(int); + int builtin_size(int); + int builtin_xor(int); + int builtin_and(int); + int builtin_or(int); + int builtin_nand(int); + int builtin_not(int); + int builtin_sin(int); + int builtin_cos(int); + int builtin_tan(int); + int builtin_exp(int); + int builtin_ln(int); + int builtin_sqrt(int); + int builtin_atan2(int); + int builtin_time(int); + int builtin_contains(int); + int builtin_delete(int); + int builtin_getkeys(int); + int builtin_import(int); + int builtin_die(int); + int builtin_type(int); + void load_builtin_function(); +public: + nasal_runtime(); + ~nasal_runtime(); + void set_root(nasal_ast&); + void run(); +}; + +nasal_runtime::nasal_runtime() +{ + error=0; + this->root.clear(); + this->global_scope_address=-1; + this->load_builtin_function(); + return; +} +nasal_runtime::~nasal_runtime() +{ + error=0; + this->root.clear(); + this->global_scope_address=-1; + this->builtin_func_hashmap.clear(); + return; +} +void nasal_runtime::load_builtin_function() +{ + struct FUNC_TABLE + { + std::string func_name; + int (nasal_runtime::*func_pointer)(int x); + } builtin_func_table[]= + { + {"nasal_call_builtin_std_cout", nasal_runtime::builtin_print}, + {"nasal_call_builtin_push_back", nasal_runtime::builtin_append}, + {"nasal_call_builtin_set_size", nasal_runtime::builtin_setsize}, + {"nasal_call_builtin_system", nasal_runtime::builtin_system}, + {"nasal_call_builtin_input", nasal_runtime::builtin_input}, + {"nasal_call_builtin_sleep", nasal_runtime::builtin_sleep}, + {"nasal_call_builtin_finput", nasal_runtime::builtin_finput}, + {"nasal_call_builtin_foutput", nasal_runtime::builtin_foutput}, + {"nasal_call_builtin_split", nasal_runtime::builtin_split}, + {"nasal_call_builtin_rand", nasal_runtime::builtin_rand}, + {"nasal_call_builtin_get_id", nasal_runtime::builtin_id}, + {"nasal_call_builtin_trans_int", nasal_runtime::builtin_int}, + {"nasal_call_builtin_trans_num", nasal_runtime::builtin_num}, + {"nasal_call_builtin_pop_back", nasal_runtime::builtin_pop}, + {"nasal_call_builtin_trans_str", nasal_runtime::builtin_str}, + {"nasal_call_builtin_size", nasal_runtime::builtin_size}, + {"nasal_call_builtin_xor", nasal_runtime::builtin_xor}, + {"nasal_call_builtin_and", nasal_runtime::builtin_and}, + {"nasal_call_builtin_or", nasal_runtime::builtin_or}, + {"nasal_call_builtin_nand", nasal_runtime::builtin_nand}, + {"nasal_call_builtin_not", nasal_runtime::builtin_not}, + {"nasal_call_builtin_sin", nasal_runtime::builtin_sin}, + {"nasal_call_builtin_cos", nasal_runtime::builtin_cos}, + {"nasal_call_builtin_tan", nasal_runtime::builtin_tan}, + {"nasal_call_builtin_exp", nasal_runtime::builtin_exp}, + {"nasal_call_builtin_cpp_math_ln", nasal_runtime::builtin_ln}, + {"nasal_call_builtin_cpp_math_sqrt", nasal_runtime::builtin_sqrt}, + {"nasal_call_builtin_cpp_atan2", nasal_runtime::builtin_atan2}, + {"nasal_call_builtin_time", nasal_runtime::builtin_time}, + {"nasal_call_builtin_contains", nasal_runtime::builtin_contains}, + {"nasal_call_builtin_delete", nasal_runtime::builtin_delete}, + {"nasal_call_builtin_get_keys", nasal_runtime::builtin_getkeys}, + {"nasal_call_import", nasal_runtime::builtin_import}, + {"nasal_call_builtin_die", nasal_runtime::builtin_die}, + {"nasal_call_builtin_type", nasal_runtime::builtin_type}, + {"", NULL} + }; + for(int i=0;builtin_func_table[i].func_pointer;++i) + builtin_func_hashmap[builtin_func_table[i].func_name]=builtin_func_table[i].func_pointer; + return; +} +void nasal_runtime::set_root(nasal_ast& parse_result) +{ + this->root=parse_result; + return; +} +void nasal_runtime::run() +{ + this->error=0; + this->function_returned_address=-1; + + 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(); + + time_t begin_time=std::time(NULL); + int returned_statement=main_progress(); + time_t end_time=std::time(NULL); + + nasal_vm.gc_get(global_scope_address).get_closure().del_scope(); + nasal_vm.del_reference(global_scope_address); + nasal_vm.clear(); + + time_t total_run_time=end_time-begin_time; + if(total_run_time>=1) + std::cout<<">> [runtime] process exited after "<=0) + ref_of_this_function.set_closure_addr(local_scope_addr); + else + { + int new_closure=nasal_vm.gc_alloc(); + nasal_vm.gc_get(new_closure).set_type(vm_closure); + ref_of_this_function.set_closure_addr(new_closure); + nasal_vm.del_reference(new_closure); + } + 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.\n";++error;break; + case rt_continue:std::cout<<">> [runtime] main_progress: cannot use continue in main progress.\n";++error;break; + case rt_return:std::cout<<">> [runtime] main_progress: cannot use return in main progress.\n";++error;break; + case rt_error:std::cout<<">> [runtime] main_progress: error occurred when executing main progress.\n";++error;break; + } + if(error) + { + ret_state=rt_error; + break; + } + } + return ret_state; +} +int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allow_return) +{ + int ret_state=rt_exit_without_error; + // if local_scope does not exist,create a new one. + if(local_scope_addr<0) + { + local_scope_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(local_scope_addr).set_type(vm_closure); + nasal_vm.gc_get(local_scope_addr).get_closure().add_scope(); + } + else + { + nasal_vm.add_reference(local_scope_addr); + nasal_vm.gc_get(local_scope_addr).get_closure().add_scope(); + } + int expr_number=node.get_children().size(); + int process_returned_value_addr=-1; + for(int i=0;i> [runtime] block_progress: return expression is not allowed here.\n"; + ++error; + } + break; + } + if(ret_state==rt_error) + { + std::cout<<">> [runtime] block_progress: error occurred when executing sub-progress.\n"; + ++error; + } + if(error || ret_state==rt_break || ret_state==rt_continue || ret_state==rt_return) + break; + } + nasal_vm.gc_get(local_scope_addr).get_closure().del_scope(); + nasal_vm.del_reference(local_scope_addr); + return ret_state; +} +int nasal_runtime::before_for_loop(nasal_ast& node,int local_scope_addr) +{ + int before_loop_node_type=node.get_type(); + switch(before_loop_node_type) + { + case ast_null:break; + case ast_definition:definition(node,local_scope_addr);break; + case ast_multi_assign:multi_assignment(node,local_scope_addr);break; + case ast_nil:case ast_number:case ast_string:case ast_function:break; + case ast_vector:case ast_hash: + case ast_call: + case ast_equal:case ast_add_equal:case ast_sub_equal:case ast_mult_equal:case ast_div_equal:case ast_link_equal: + case ast_unary_sub:case ast_unary_not: + case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link: + case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break; + default:std::cout<<">> [runtime] before_for_loop: cannot use this expression before for-loop.\n";++error;break; + } + if(error) + return rt_error; + return rt_exit_without_error; +} +int nasal_runtime::after_each_for_loop(nasal_ast& node,int local_scope_addr) +{ + int node_type=node.get_type(); + switch(node_type) + { + case ast_null:break; + case ast_definition:definition(node,local_scope_addr);break; + case ast_multi_assign:multi_assignment(node,local_scope_addr);break; + case ast_nil:case ast_number:case ast_string:case ast_function:break; + case ast_vector:case ast_hash: + case ast_call: + case ast_equal:case ast_add_equal:case ast_sub_equal:case ast_mult_equal:case ast_div_equal:case ast_link_equal: + case ast_unary_sub:case ast_unary_not: + case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link: + case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break; + default:std::cout<<">> [runtime] after_each_for_loop: cannot use this expression after each for-loop.\n";++error;break; + } + if(error) + return rt_error; + return rt_exit_without_error; +} +int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow_return) +{ + int ret_state=rt_exit_without_error; + int loop_type=node.get_type(); + if(loop_type==ast_while) + { + nasal_ast& condition_node=node.get_children()[0]; + nasal_ast& run_block_node=node.get_children()[1]; + // create a new local scope to store iterator if local_scope_addr=-1 + int while_local_scope_addr=local_scope_addr; + if(while_local_scope_addr<0) + { + while_local_scope_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(while_local_scope_addr).set_type(vm_closure); + nasal_vm.gc_get(while_local_scope_addr).get_closure().add_scope(); + } + else + { + nasal_vm.add_reference(local_scope_addr); + nasal_vm.gc_get(while_local_scope_addr).get_closure().add_scope(); + } + // check condition and begin loop + int condition_value_addr=calculation(condition_node,while_local_scope_addr); + bool result=check_condition(condition_value_addr); + nasal_vm.del_reference(condition_value_addr); + while(result) + { + // return expression will be checked in block_progress + ret_state=block_progress(run_block_node,local_scope_addr,allow_return); + if(ret_state==rt_break || ret_state==rt_error || ret_state==rt_return || error) + break; + condition_value_addr=calculation(condition_node,while_local_scope_addr); + result=check_condition(condition_value_addr); + nasal_vm.del_reference(condition_value_addr); + } + nasal_vm.gc_get(while_local_scope_addr).get_closure().del_scope(); + nasal_vm.del_reference(while_local_scope_addr); + } + else if(loop_type==ast_forindex || loop_type==ast_foreach) + { + nasal_ast& iter_node=node.get_children()[0]; + nasal_ast& vector_node=node.get_children()[1]; + nasal_ast& run_block_node=node.get_children()[2]; + // check vector to make sure iterator can be used without problem + int vector_value_addr=calculation(vector_node,local_scope_addr); + if(vector_value_addr<0 || nasal_vm.gc_get(vector_value_addr).get_type()!=vm_vector) + { + std::cout<<">> [runtime] loop_progress: "<<(loop_type==ast_forindex? "forindex":"foreach")<<" gets a value that is not a vector.\n"; + ++error; + return rt_error; + } + // create a new local scope to store iterator if local_scope_addr=-1 + int forei_local_scope_addr=local_scope_addr; + if(forei_local_scope_addr<0) + { + forei_local_scope_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(forei_local_scope_addr).set_type(vm_closure); + nasal_vm.gc_get(forei_local_scope_addr).get_closure().add_scope(); + } + else + { + nasal_vm.add_reference(local_scope_addr); + nasal_vm.gc_get(forei_local_scope_addr).get_closure().add_scope(); + } + // begin loop progress + int mem_addr=-1; + if(iter_node.get_type()==ast_new_iter) + { + int new_value_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(new_value_addr).set_type(vm_nil); + std::string val_name=iter_node.get_children()[0].get_str(); + nasal_vm.gc_get(forei_local_scope_addr).get_closure().add_new_value(val_name,new_value_addr); + mem_addr=nasal_vm.gc_get(forei_local_scope_addr).get_closure().get_mem_address(val_name); + } + else + mem_addr=call_scalar_mem(iter_node,local_scope_addr); + if(mem_addr<0) + { + std::cout<<">> [runtime] loop_progress: get null iterator.\n"; + ++error; + return rt_error; + } + // ref_vector's size may change when running,so this loop will check size each time + nasal_vector& ref_vector=nasal_vm.gc_get(vector_value_addr).get_vector(); + for(int i=0;i> [runtime] check_condition: error value type when checking condition.\n"; + ++error; + return false; + } + else if(type==vm_string) + { + std::string str=nasal_vm.gc_get(value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] check_condition: error value type, \'"<=0) + value_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(val_name); + if(value_address<0) + value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(val_name); + if(value_address<0) + { + value_address=call_builtin_function(val_name,local_scope_addr); + if(value_address>=0) + return value_address; + } + if(value_address<0) + { + if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end()) + std::cout<<">> [runtime] call_scalar: call "<> [runtime] call_scalar: cannot find value named \""<> [runtime] call_vector: incorrect value type,expected a vector/hash/string.\n"; + ++error; + return -1; + } + int call_size=node.get_children().size(); + + if(base_value_type==vm_vector) + { + std::vector 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.\n"; + ++error; + return -1; + } + if(end_value_type!=vm_nil && end_value_type!=vm_number && end_value_type!=vm_string) + { + std::cout<<">> [runtime] call_vector: end index is not a number/numerable string.\n"; + ++error; + return -1; + } + if(begin_value_type==vm_string) + { + std::string str=nasal_vm.gc_get(begin_value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] call_vector: begin index is not a numerable string.\n"; + ++error; + return -1; + } + begin_index=(int)trans_string_to_number(str); + begin_is_nil=false; + } + else if(begin_value_type==vm_number) + { + begin_index=(int)nasal_vm.gc_get(begin_value_addr).get_number(); + begin_is_nil=false; + } + + if(end_value_type==vm_string) + { + std::string str=nasal_vm.gc_get(end_value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] call_vector: end index is not a numerable string.\n"; + ++error; + return -1; + } + end_index=(int)trans_string_to_number(str); + end_is_nil=false; + } + else if(end_value_type==vm_number) + { + end_index=(int)nasal_vm.gc_get(end_value_addr).get_number(); + end_is_nil=false; + } + + if(begin_is_nil && end_is_nil) + { + begin_index=0; + end_index=reference_value.size()-1; + } + else if(begin_is_nil && !end_is_nil) + { + begin_index=end_index<0? -reference_value.size():0; + } + else if(!begin_is_nil && end_is_nil) + { + end_index=begin_index<0? -1:reference_value.size()-1; + } + else if(!begin_is_nil && !end_is_nil) + { + if(begin_index>=end_index) + { + std::cout<<">> [runtime] call_vector: begin index must be less than end index.\n"; + ++error; + return -1; + } + } + for(int i=begin_index;i> [runtime] call_vector: index is not a number/numerable string.\n"; + ++error; + return -1; + } + int index_num=0; + if(index_value_type==vm_string) + { + std::string str=nasal_vm.gc_get(index_value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] call_vector: index is not a numerable string.\n"; + ++error; + return -1; + } + index_num=(int)trans_string_to_number(str); + } + else + index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); + nasal_vm.del_reference(index_value_addr); + called_value_addrs.push_back(reference_value.get_value_address(index_num)); + } + } + // generate sub-vector + if(called_value_addrs.size()==1) + { + int value_addr=called_value_addrs[0]; + nasal_vm.add_reference(value_addr); + return_value_addr=value_addr; + } + else + { + return_value_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(return_value_addr).set_type(vm_vector); + nasal_vector& return_vector=nasal_vm.gc_get(return_value_addr).get_vector(); + int vec_size=called_value_addrs.size(); + for(int i=0;i1) + { + std::cout<<">> [runtime] call_vector: when calling a hash,only one key is alowed.\n"; + ++error; + return -1; + } + if(node.get_children()[0].get_type()==ast_subvec) + { + std::cout<<">> [runtime] call_vector: cannot slice hash.\n"; + ++error; + return -1; + } + std::string str=node.get_children()[0].get_str(); + int value_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_value_address(str); + nasal_vm.add_reference(value_addr); + return_value_addr=value_addr; + } + else + { + if(call_size>1) + { + std::cout<<">> [runtime] call_vector: when calling a string,only one index is alowed.\n"; + ++error; + return -1; + } + if(node.get_children()[0].get_type()==ast_subvec) + { + std::cout<<">> [runtime] call_vector: cannot slice string.\n"; + ++error; + return -1; + } + int index_value_addr=calculation(node.get_children()[0],local_scope_addr); + int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); + if(index_value_type!=vm_number && index_value_type!=vm_string) + { + std::cout<<">> [runtime] call_vector: index is not a number/numerable string.\n"; + ++error; + return -1; + } + int index_num=0; + if(index_value_type==vm_string) + { + std::string str=nasal_vm.gc_get(index_value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] call_vector: index is not a numerable string.\n"; + ++error; + return -1; + } + index_num=(int)trans_string_to_number(str); + } + else + index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); + nasal_vm.del_reference(index_value_addr); + return_value_addr=nasal_vm.gc_alloc(); + nasal_vm.gc_get(return_value_addr).set_type(vm_number); + std::string str=nasal_vm.gc_get(base_value_addr).get_string(); + int str_size=str.length(); + if(index_num>=str_size || index_num<-str_size) + { + std::cout<<">> [runtime] call_vector: index out of range.\n"; + ++error; + return -1; + } + nasal_vm.gc_get(return_value_addr).set_number((double)str[(index_num+str_size)%str_size]); + } + return return_value_addr; +} +int nasal_runtime::call_hash(nasal_ast& node,int base_value_addr,int local_scope_addr) +{ + int value_type=nasal_vm.gc_get(base_value_addr).get_type(); + if(value_type!=vm_hash) + { + std::cout<<">> [runtime] call_hash: incorrect value type,expected a hash.\n"; + ++error; + return -1; + } + int ret_value_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_value_address(node.get_str()); + nasal_vm.add_reference(ret_value_addr); + return ret_value_addr; +} +int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_value_addr,int last_call_hash_addr,int local_scope_addr) +{ + int ret_value_addr=-1; + int value_type=nasal_vm.gc_get(base_value_addr).get_type(); + if(value_type!=vm_function) + { + std::cout<<">> [runtime] call_function: incorrect value type,expected a function.\n"; + ++error; + return -1; + } + nasal_function& reference_of_func=nasal_vm.gc_get(base_value_addr).get_func(); + int run_closure_addr=reference_of_func.get_closure_addr(); + nasal_closure& run_closure=nasal_vm.gc_get(run_closure_addr).get_closure(); + run_closure.add_scope(); + // set self + if(func_name.length()) + { + nasal_vm.add_reference(base_value_addr); + run_closure.add_new_value(func_name,base_value_addr); + } + // set hash.me + if(last_call_hash_addr>=0) + { + nasal_vm.add_reference(last_call_hash_addr); + run_closure.add_new_value("me",last_call_hash_addr); + } + nasal_ast& argument_format=reference_of_func.get_arguments(); + if(!node.get_children().size()) + { + if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()!=ast_default_arg && argument_format.get_children()[0].get_type()!=ast_dynamic_id) + { + int size=argument_format.get_children().size(); + int sum=0; + for(int i=0;i> [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.\n"; + ++error; + return -1; + } + } + else + { + std::vector 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.\n"; + ++error; + return -1; + } + args.push_back(tmp_val_addr); + } + int arg_format_size=argument_format.get_children().size(); + if(size>arg_format_size && argument_format.get_children().back().get_type()!=ast_dynamic_id) + { + std::cout<<">> [runtime] call_function: too much arguments.\n"; + ++error; + return -1; + } + for(int i=0;i> [runtime] call_function: lack argument(s).stop.\n"; + ++error; + return -1; + } + } + else // default_args + { + if(i> [runtime] call_function: break and continue are not allowed to be used here.\n"; + ++error; + return -1; + } + else if(ret_state==rt_error) + return -1; + + if(function_returned_address>=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_builtin_function(std::string val_name,int local_scope_addr) +{ + int ret_value_addr=-1; + int builtin_func_num=-1; + if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end()) + ret_value_addr=(this->*builtin_func_hashmap[val_name])(local_scope_addr); + return ret_value_addr; +} +int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr) +{ + int mem_address=-1; + if(node.get_type()==ast_identifier) + { + if(local_scope_addr>=0) + mem_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_mem_address(node.get_str()); + if(mem_address<0) + mem_address=nasal_vm.gc_get(global_scope_address).get_closure().get_mem_address(node.get_str()); + if(mem_address<0) + { + std::cout<<">> [runtime] call_scalar_mem: cannot find value named \'"<=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.\n"; + ++error; + return -1; + break; + } + mem_address=tmp_mem_addr; + if(mem_address<0) + { + ++error; + std::cout<<">> [runtime] call_scalar_mem: cannot find correct memory space.\n"; + break; + } + } + return mem_address; +} +int nasal_runtime::call_vector_mem(nasal_ast& node,int base_mem_addr,int local_scope_addr) +{ + int return_mem_addr=-1; + int base_value_addr=nasal_vm.mem_get(base_mem_addr); + int base_value_type=nasal_vm.gc_get(base_value_addr).get_type(); + if(base_value_type!=vm_vector && base_value_type!=vm_hash) + { + std::cout<<">> [runtime] call_vector_mem: incorrect value type,expected a vector/hash.\n"; + ++error; + return -1; + } + int call_size=node.get_children().size(); + if(call_size>1) + { + std::cout<<">> [runtime] call_vector_mem: when searching a memory space in a vector,only one index is alowed.\n"; + ++error; + return -1; + } + if(base_value_type==vm_vector) + { + nasal_vector& reference_value=nasal_vm.gc_get(base_value_addr).get_vector(); + if(node.get_children()[0].get_type()==ast_subvec) + { + std::cout<<">> [runtime] call_vector_mem: sub-vector in this progress is a temporary value and cannot be changed.\n"; + ++error; + return -1; + } + int index_value_addr=calculation(node.get_children()[0],local_scope_addr); + int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); + if(index_value_type!=vm_number && index_value_type!=vm_string) + { + std::cout<<">> [runtime] call_vector_mem: index is not a number/numerable string.\n"; + ++error; + return -1; + } + int index_num=0; + if(index_value_type==vm_string) + { + std::string str=nasal_vm.gc_get(index_value_addr).get_string(); + if(!check_numerable_string(str)) + { + std::cout<<">> [runtime] call_vector_mem: index is not a numerable string.\n"; + ++error; + return -1; + } + index_num=(int)trans_string_to_number(str); + } + else + index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); + nasal_vm.del_reference(index_value_addr); + return_mem_addr=reference_value.get_mem_address(index_num); + } + else + { + if(call_size>1) + { + std::cout<<">> [runtime] call_vector_mem: when calling a hash,only one key is alowed.\n"; + ++error; + return -1; + } + std::string str=node.get_children()[0].get_str(); + return_mem_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_mem_address(str); + } + return return_mem_addr; +} +int nasal_runtime::call_hash_mem(nasal_ast& node,int base_mem_addr,int local_scope_addr) +{ + int base_value_addr=nasal_vm.mem_get(base_mem_addr); + int value_type=nasal_vm.gc_get(base_value_addr).get_type(); + if(value_type!=vm_hash) + { + std::cout<<">> [runtime] call_hash_mem: incorrect value type,expected a hash.\n"; + ++error; + return -1; + } + int ret_mem_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_mem_address(node.get_str()); + return ret_mem_addr; +} +int nasal_runtime::calculation(nasal_ast& node,int local_scope_addr) +{ + // after this process, a new address(in nasal_vm.garbage_collector_memory) will be returned + int ret_address=-1; + int calculation_type=node.get_type(); + if(calculation_type==ast_nil) + { + ret_address=nasal_vm.gc_alloc(); + nasal_vm.gc_get(ret_address).set_type(vm_nil); + } + else if(calculation_type==ast_number) + ret_address=number_generation(node); + else if(calculation_type==ast_string) + ret_address=string_generation(node); + else if(calculation_type==ast_identifier) + { + if(local_scope_addr>=0) + ret_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(node.get_str()); + if(ret_address<0) + ret_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(node.get_str()); + if(ret_address<0) + { + std::cout<<">> [runtime] calculation: cannot find value named \'"<> [runtime] calculation: this expression cannot be calculated.expression type:"<> [runtime] calculation: incorrect values are used in calculation.\n"; + ++error; + } + return ret_address; +} +void nasal_runtime::definition(nasal_ast& node,int local_scope_addr) +{ + nasal_ast& define_node=node.get_children()[0]; + nasal_ast& value_node=node.get_children()[1]; + if(define_node.get_type()==ast_identifier && value_node.get_type()==ast_multi_scalar) + { + std::cout<<">> [runtime] definition: one identifier cannot accept too many values.\n"; + ++error; + return; + } + if(define_node.get_type()==ast_identifier) + { + std::string new_name=define_node.get_str(); + int value_addr=calculation(value_node,local_scope_addr); + if(value_addr<0) + return; + nasal_vm.gc_get(local_scope_addr<0?global_scope_address:local_scope_addr).get_closure().add_new_value(new_name,value_addr); + } + else + { + std::vector identifier_table; + int id_size=define_node.get_children().size(); + for(int i=0;i> [runtime] definition: size of identifiers and size of values do not match.\n"; + ++error; + return; + } + for(int i=0;i> [runtime] definition: must use vector in multi-definition.\n"; + ++error; + return; + } + nasal_vector& ref_vector=nasal_vm.gc_get(value_addr).get_vector(); + if(ref_vector.size()!=id_size) + { + std::cout<<">> [runtime] definition: size of identifiers and size of values do not match.\n"; + ++error; + return; + } + for(int i=0;i 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.\n"; + ++error; + return; + } + mem_table.push_back(call_scalar_mem(tmp_node,local_scope_addr)); + } + if(value_node.get_type()==ast_multi_scalar) + { + int val_size=value_node.get_children().size(); + if(id_size!=val_size) + { + std::cout<<">> [runtime] multi_assignment: size of calls and size of values do not match.\n"; + ++error; + return; + } + std::vector value_table; + for(int i=0;i> [runtime] multi_assignment: must use vector in multi-assignment.\n"; + ++error; + return; + } + nasal_vector& ref_vector=nasal_vm.gc_get(value_addr).get_vector(); + if(ref_vector.size()!=id_size) + { + std::cout<<">> [runtime] multi_assignment: size of calls and size of values do not match.\n"; + ++error; + return; + } + std::vector value_table; + for(int i=0;i0? x:0; + }, + diffrelu_func:func(x) + { + return x>0; + }, + leaky_relu_func:func(k,x) + { + return x>0? x:k*x; + }, + diffleaky_relu_func:func(k,x) + { + return x>0? 1:k; + } +}; + +var matrix= +{ + new:func(col,row) + { + var new_mat= + { + col:col, + row:row, + mat:[] + }; + for(var i=0;i0.5) + mat.mat[i][j]=-rand(); + else + mat.mat[i][j]=rand(); + } + return; + }, + prt_mat:func(mat) + { + var prt_s='[\n'; + foreach(var i;mat.mat) + { + var s='['; + foreach(var j;i) + s~=(j~','); + s~='],\n'; + prt_s~=s; + } + prt_s~=']'; + print(prt_s); + return nil; + }, + mult_mat:func(mat1,mat2) + { + if(mat1.col!=mat2.row) + { + die("[error-mult] mat1\'s col does not match mat2\'s row."); + return nil; + } + var new_mat=me.new(mat2.col,mat1.row); + for(var i=0;i0.01) + { + error=0; + for(var i=0;i<4;i+=1) + { + me.forward(i); + error+=me.backward(i); + } + print(error); + } + return; + } +}; +var main=func() +{ + bp.init(); + bp.set_learning_rate(0.1); + bp.set_training_set(); + bp.set_expect_set(); + bp.training_process(); + return nil; +} + +# var (a,b,c)=[1,2,3]; +# (a,b,c)=(b,c,a); +# print(a,b,c); +main(); diff --git a/test/ascii-art.nas b/test/ascii-art.nas new file mode 100644 index 0000000..bcb99ed --- /dev/null +++ b/test/ascii-art.nas @@ -0,0 +1,135 @@ +import("lib.nas"); +var char_ttf=[ + [" "," "," "," "," "," "], + [" ████╗"," ██╔██║"," ██╔╝██║"," ███████║","██╔═══██║","╚═╝ ╚═╝"], + ["██████╗ ","██╔══██╗","██████╔╝","██╔══██╗","██████╔╝","╚═════╝ "], + [" ██████╗","██╔════╝","██║ ","██║ ","╚██████╗"," ╚═════╝"], + ["██████╗ ","██╔══██╗","██║ ██║","██║ ██║","██████╔╝","╚═════╝ "], + ["███████╗","██╔════╝","█████╗ ","██╔══╝ ","███████╗","╚══════╝"], + ["███████╗","██╔════╝","█████╗ ","██╔══╝ ","██║ ","╚═╝ "], + [" █████╗ ","██╔═══╝ ","██║ ██╗ ","██║ ╚██╗","╚█████╔╝"," ╚════╝ "], + ["██╗ ██╗","██║ ██║","███████║","██╔══██║","██║ ██║","╚═╝ ╚═╝"], + [" ██████╗"," ██╔═╝"," ██║ "," ██║ "," ██████╗"," ╚═════╝"], + [" ██╗"," ██║"," ██║","██ ██║","╚█████╔╝"," ╚════╝ "], + ["██╗ ██╗","██║ ██╔╝","█████╔╝ ","██╔═██╗ ","██║ ██╗","╚═╝ ╚═╝"], + ["██╗ ","██║ ","██║ ","██║ ","███████╗","╚══════╝"], + ["██╗ ██╗","███╗ ███║","████████║","██╔██╔██║","██║╚═╝██║","╚═╝ ╚═╝"], + ["██╗ ██╗","███╗ ██║","█████╗██║","██╔█████║","██║ ╚███║","╚═╝ ╚══╝"], + [" ██████╗ ","██╔═══██╗","██║ ██║","██║ ██║","╚██████╔╝"," ╚═════╝ "], + ["██████╗ ","██╔══██╗","██████╔╝","██╔═══╝ ","██║ ","╚═╝ "], + [" ██████╗ ","██╔═══██╗","██║ ██║","██║ ██╔╝","╚████╔██╗"," ╚═══╝╚═╝"], + ["██████╗ ","██╔══██╗","██████╔╝","██╔══██╗","██║ ██║","╚═╝ ╚═╝"], + ["███████╗","██╔════╝","███████╗","╚════██║","███████║","╚══════╝"], + ["████████╗","╚══██╔══╝"," ██║ "," ██║ "," ██║ "," ╚═╝ "], + ["██╗ ██╗","██║ ██║","██║ ██║","██║ ██║","╚██████╔╝"," ╚═════╝ "], + ["██╗ ██╗","██║ ██║","██║ ██║","╚██╗ ██╔╝"," ╚████╔╝ "," ╚═══╝ "], + ["██╗ ██╗","██║██╗██║","████████║","███╔═███║","██╔╝ ╚██║","╚═╝ ╚═╝"], + ["██╗ ██╗","╚██╗██╔╝"," ╚███╔╝ "," ██╔██╗ ","██╔╝╚██╗","╚═╝ ╚═╝"], + ["██╗ ██╗","╚██╗ ██╔╝"," ╚████╔╝ "," ╚██╔╝ "," ██║ "," ╚═╝ "], + ["████████╗","╚════██╔╝"," ██╔═╝ "," ██╔═╝ ","████████╗","╚═══════╝"], +]; +var trans_ttf=func(string) +{ + var str=["","","","","",""]; + for(var i=0;i=0;i-=1) + { + var rand_index=int(i*rand()); + (arr[i],arr[rand_index])=(arr[rand_index],arr[i]); + } + # 0 1 2 3 4 5 6 7 8 + var shadow=[" ","░","▒","▓","█","▀","▄","▐","▌"]; + var s=""; + for(var i=0;i180) - position_val += value-360; - else if(position_val+value<-180) - position_val += value+360; - else - position_val += value; - return position_val; -} -var road_check_func = func(){ - - var lat = props.getNode("/position/latitude-deg",1).getValue(); - var lon = props.getNode("/position/longitude-deg",1).getValue(); - var position_info = geodinfo(lat,lon); - var position_names = position_info[1].names; - # the friction_factor of freeway runway and road is 1 - - if((position_names[0]=="Freeway") or (position_names[0]=="Road")) - { - var car_heading = 0; - var lat_change = 0; - var lon_change = 0; - var left_range = 0; - var right_range = 0; - - for(var i=0;i>-0.00005;i-=0.000001) - { - car_heading = props.getNode("/orientation/heading-deg",1).getValue(); - lat_change = math.sin(math.pi*car_heading/180); - lon_change = -math.cos(math.pi*car_heading/180); - lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180); - lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180); - var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change)); - var other_names = other_position_info[1].names; - if((other_names[0]=="Freeway") or (other_names[0]=="Road")) - right_range += 1; - else - break; - } - for(var i=0;i<0.00005;i+=0.000001) - { - car_heading = props.getNode("/orientation/heading-deg",1).getValue(); - lat_change = math.sin(math.pi*car_heading/180); - lon_change = -math.cos(math.pi*car_heading/180); - lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180); - lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180); - var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change)); - var other_names = other_position_info[1].names; - if((other_names[0]=="Freeway") or (other_names[0]=="Road")) - left_range+=1; - else - break; - } - #if(left_range>right_range) - #{ - # setprop("/controls/flight/rudder",-(right_range-left_range)*(right_range-left_range)/10000); - # print("right ",right_range); - #} - #else if(left_range180) + position_val += value-360; + else if(position_val+value<-180) + position_val += value+360; + else + position_val += value; + return position_val; +} +var road_check_func = func(){ + + var lat = props.getNode("/position/latitude-deg",1).getValue(); + var lon = props.getNode("/position/longitude-deg",1).getValue(); + var position_info = geodinfo(lat,lon); + var position_names = position_info[1].names; + # the friction_factor of freeway runway and road is 1 + + if((position_names[0]=="Freeway") or (position_names[0]=="Road")) + { + var car_heading = 0; + var lat_change = 0; + var lon_change = 0; + var left_range = 0; + var right_range = 0; + + for(var i=0;i>-0.00005;i-=0.000001) + { + car_heading = props.getNode("/orientation/heading-deg",1).getValue(); + lat_change = math.sin(math.pi*car_heading/180); + lon_change = -math.cos(math.pi*car_heading/180); + lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180); + lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180); + var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change)); + var other_names = other_position_info[1].names; + if((other_names[0]=="Freeway") or (other_names[0]=="Road")) + right_range += 1; + else + break; + } + for(var i=0;i<0.00005;i+=0.000001) + { + car_heading = props.getNode("/orientation/heading-deg",1).getValue(); + lat_change = math.sin(math.pi*car_heading/180); + lon_change = -math.cos(math.pi*car_heading/180); + lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180); + lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180); + var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change)); + var other_names = other_position_info[1].names; + if((other_names[0]=="Freeway") or (other_names[0]=="Road")) + left_range+=1; + else + break; + } + #if(left_range>right_range) + #{ + # setprop("/controls/flight/rudder",-(right_range-left_range)*(right_range-left_range)/10000); + # print("right ",right_range); + #} + #else if(left_range