diff --git a/README.md b/README.md index f5c5c0e..3fabe9b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # Nasal Script Language +## Introduction + [Nasal](http://wiki.flightgear.org/Nasal_scripting_language) is a script language that used in [FlightGear](https://www.flightgear.org/). -The interpreter is totally rewritten by ValKmjolnir using C++(standard c++11) without reusing the code in Andy Ross's nasal interpreter(https://github.com/andyross/nasal). But we really appreciate that Andy created this amazing programming language and his interpreter project. +The interpreter is totally rewritten by ValKmjolnir using C++(standard c++11) without reusing the code in Andy Ross's nasal interpreter(). But we really appreciate that Andy created this amazing programming language and his interpreter project. The interpreter is still in development(now it works well --2021/2/15). We really need your support! @@ -10,9 +12,9 @@ Also,i am a member of [FGPRC](https://www.fgprc.org/), welcome to join us! (2021/5/4) Now this project uses MIT license.Edit it if you want, use this project to learn or create more interesting things(But don't forget me XD). -# Why Writing Nasal Interpreter +## Why Writing Nasal Interpreter -Nasal is a script language first used in Flightgear, created by Andy Ross(https://github.com/andyross). +Nasal is a script language first used in Flightgear, created by Andy Ross(). But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax errors. @@ -26,7 +28,7 @@ Also, you could use this language to write some interesting programs and run the You could add your own built-in functions to change this interpreter to a useful tool in your own projects(such as a script in your own game). -# How to Compile +## How to Compile Better choose the latest update of the interpreter. @@ -34,7 +36,7 @@ MUST USE -O2 ! pragma gcc optimize(2) seems useless when using g++ > g++ -std=c++11 -O2 main.cpp -o main.exe -# Parser +## Parser LL(k) parser. @@ -47,7 +49,7 @@ These two expressions have the same first set,so LL(1) is useless for this langu Maybe in the future i can refactor it to LL(1) with special checks. -## version 1.0(last update 2019/10/14) +### version 1.0(last update 2019/10/14) First fully functional version of nasal_parser. @@ -59,17 +61,17 @@ In version 0.17(2019/9/15) 0.18(2019/9/18) 0.19(2019/10/1)i was playing the pars This project began at 2019/8/31. -# Abstract Syntax Tree +## Abstract Syntax Tree -## Version 1.2(last update 2019/10/31) +### Version 1.2(last update 2019/10/31) The ast has been completed in this version. -## Version 2.0(last update 2020/8/31) +### Version 2.0(last update 2020/8/31) A completed ast-interpreter with unfinished lib functions. -## Version 3.0(last update 2020/10/23) +### Version 3.0(last update 2020/10/23) The ast is refactored and is now easier to read and maintain. @@ -79,15 +81,15 @@ Now you can add your own functions as builtin-functions in this interpreter! I decide to save the ast interpreter after releasing v4.0. Because it took me a long time to think and write... -## Version 5.0(last update 2021/3/7) +### Version 5.0(last update 2021/3/7) I change my mind.AST interpreter leaves me too much things to do. If i continue saving this interpreter,it will be harder for me to make the bytecode vm become more efficient. -# Byte Code Interpreter +## Byte Code Interpreter -## Version 4.0(last update 2020/12/17) +### Version 4.0(last update 2020/12/17) I have just finished the first version of byte-code-interpreter. @@ -120,7 +122,7 @@ for(var i=0;i<4000000;i+=1); 0x0000000b: nop 0x00000000 ``` -## Version 5.0(last update 2021/3/7) +### Version 5.0(last update 2021/3/7) I decide to optimize bytecode vm in this version. @@ -128,7 +130,7 @@ Because it takes more than 1.5s to count i from 0 to 4000000-1.This is not effic 2021/1/23 update: Now it can count from 0 to 4000000-1 in 1.5s. -## Version 6.0(last update 2021/6/1) +### Version 6.0(last update 2021/6/1) Use loadg loadl callg calll mcallg mcalll to avoid branches. @@ -169,7 +171,7 @@ for(var i=0;i<4000000;i+=1); 0x0000000c: nop 0x00000000 ``` -## Version 6.5(latest) +### Version 6.5(latest) 2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error. @@ -213,9 +215,9 @@ f(1024,2048); 0x00000011: nop 0x00000000 ``` -# How to Use Nasal to Program +## How to Use Nasal to Program -## basic value type +### basic value type Nasal has 6 value types.Number,string,vector,hash,function,nil. @@ -281,7 +283,7 @@ var f=func(x,y,z,dynamic_para...) } ``` -## operators +### operators ```javascript 1+2; @@ -311,7 +313,7 @@ a/=1; a~='string'; ``` -## definition +### definition ```javascript var a=1; @@ -321,14 +323,14 @@ var (a,b,c)=(0,1,2); (var a,b,c)=(0,1,2); ``` -## multi-assignment +### multi-assignment ```javascript (a,b[0],c.d)=[0,1,2]; (a,b[1],c.e)=(0,1,2); ``` -## conditional expression +### conditional expression ```javascript if(1) @@ -349,7 +351,7 @@ else } ``` -## loop +### loop ```javascript while(condition) @@ -365,7 +367,7 @@ foreach(var i;elem) print(i); ``` -## subvec +### subvec Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr(). @@ -374,7 +376,7 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil]; "hello world"[0]; ``` -## special function call +### special function call This is of great use but is not very efficient(because hashmap use string as the key to compare). @@ -382,7 +384,7 @@ This is of great use but is not very efficient(because hashmap use string as the a(x:0,y:1,z:2); ``` -## lambda +### lambda Also functions have this kind of use: @@ -391,7 +393,7 @@ func(x,y){return x+y}(0,1); func(x){return 1/(1+math.exp(-x));}(0.5); ``` -## closure +### closure Use closure to OOP. @@ -419,7 +421,7 @@ var student=func(name,age) } ``` -## built-in functions +### built-in functions Must import lib.nas or has these functions' definitions inside your code. @@ -522,11 +524,3 @@ nasal_val* builtin_getkeys(std::vector& local_scope,nasal_gc& gc) return ret_addr; } ``` - -# 写在最后 - -我要怎么才能告诉gitee的逆天管理员gitee上的ValKmjolnir和github的ValKmjolnir是一个人? - -他居然告诉我,我从github同步的仓库是他人项目? - -我证明我是我自己?:sweat_smile: \ No newline at end of file diff --git a/main.cpp b/main.cpp index e0c7f9d..67a85d6 100644 --- a/main.cpp +++ b/main.cpp @@ -28,7 +28,7 @@ void logo() return; } -void die(std::string stage,std::string filename) +void die(const char* stage,std::string& filename) { std::cout<<">> ["<: error(s) occurred,stop.\n"; return; diff --git a/nasal_ast.h b/nasal_ast.h index c43528f..90fbbce 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -4,8 +4,7 @@ enum ast_node { ast_null=0, - ast_root, - ast_block, + ast_root,ast_block, ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec, ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec, ast_args,ast_default_arg,ast_dynamic_id, @@ -20,74 +19,31 @@ enum ast_node ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter, ast_conditional,ast_if,ast_elsif,ast_else, ast_multi_id,ast_multi_scalar, - ast_definition,ast_multi_assign, - ast_continue,ast_break,ast_return + ast_def,ast_multi_assign, + ast_continue,ast_break,ast_ret }; -std::string ast_name(int type) +const char* ast_name[]= { - switch(type) - { - case ast_null: return "null"; - case ast_root: return "root"; - case ast_block: return "block"; - case ast_nil: return "nil"; - case ast_num: return "number"; - case ast_str: return "string"; - case ast_id: return "id"; - case ast_func: return "function"; - case ast_hash: return "hash"; - case ast_vec: return "vector"; - case ast_hashmember: return "hashmember"; - case ast_call: return "call"; - case ast_callh: return "callh"; - case ast_callv: return "callv"; - case ast_callf: return "callf"; - case ast_subvec: return "subvec"; - case ast_args: return "args"; - case ast_default_arg: return "deflt_arg"; - case ast_dynamic_id: return "dyn_id"; - case ast_and: return "and"; - case ast_or: return "or"; - case ast_equal: return "="; - case ast_addeq: return "+="; - case ast_subeq: return "-="; - case ast_multeq: return "*="; - case ast_diveq: return "/="; - case ast_lnkeq: return "~="; - case ast_cmpeq: return "=="; - case ast_neq: return "!="; - case ast_less: return "<"; - case ast_leq: return "<="; - case ast_grt: return ">"; - case ast_geq: return ">="; - case ast_add: return "+"; - case ast_sub: return "-"; - case ast_mult: return "*"; - case ast_div: return "/"; - case ast_link: return "~"; - case ast_neg: return "unary-"; - case ast_not: return "unary!"; - case ast_trino: return "trino"; - case ast_for: return "for"; - case ast_forindex: return "forindex"; - case ast_foreach: return "foreach"; - case ast_while: return "while"; - case ast_new_iter: return "iter"; - case ast_conditional: return "conditional"; - case ast_if: return "if"; - case ast_elsif: return "elsif"; - case ast_else: return "else"; - case ast_multi_id: return "multi_id"; - case ast_multi_scalar: return "multi_scalar"; - case ast_definition: return "def"; - case ast_multi_assign: return "multi_assign"; - case ast_continue: return "continue"; - case ast_break: return "break"; - case ast_return: return "return"; - } - return "null"; -} + "null", + "root","block", + "nil","num","str","id","func","hash","vec", + "hashmember","call","callh","callv","callf","subvec", + "args","deflt_arg","dyn_id", + "and","or", + "=","+=","-=","*=","/=","~=", + "==","!=", + "<","<=", + ">",">=", + "+","-","*","/","~", + "unary-","unary!", + "trino", + "for","forindex","foreach","while","iter", + "conditional","if","elsif","else", + "multi_id","multi_scalar", + "def","multi_assign", + "continue","break","return" +}; class nasal_ast { @@ -98,39 +54,24 @@ private: std::string str; std::vector children; public: - nasal_ast(); - nasal_ast(int,int); + nasal_ast(){line=0;type=ast_null;} + nasal_ast(int l,int t){line=l;type=t;} nasal_ast(const nasal_ast&); - ~nasal_ast(); nasal_ast& operator=(const nasal_ast&); void print_ast(int); void clear(); - void set_line(int); - void set_type(int); - void set_str(std::string&); - void set_num(double); - void add_child(nasal_ast); - int get_line(); - int get_type(); - double get_num(); - std::string& get_str(); - std::vector& get_children(); + void add_child(nasal_ast ast){children.push_back(ast);} + void set_line(int l){line=l;} + void set_type(int t){type=t;} + void set_str(std::string& s){str=s;} + void set_num(double n){num=n;} + int get_line(){return line;} + int get_type(){return type;} + double get_num(){return num;} + std::string& get_str(){return str;} + std::vector& get_children(){return children;} }; -nasal_ast::nasal_ast() -{ - line=0; - type=ast_null; - return; -} - -nasal_ast::nasal_ast(int _line,int _type) -{ - line=_line; - type=_type; - return; -} - nasal_ast::nasal_ast(const nasal_ast& tmp) { line=tmp.line; @@ -141,12 +82,6 @@ nasal_ast::nasal_ast(const nasal_ast& tmp) return; } -nasal_ast::~nasal_ast() -{ - children.clear(); - return; -} - nasal_ast& nasal_ast::operator=(const nasal_ast& tmp) { line=tmp.line; @@ -167,67 +102,12 @@ void nasal_ast::clear() return; } -void nasal_ast::set_line(int l) -{ - line=l; - return; -} - -void nasal_ast::set_type(int t) -{ - type=t; - return; -} - -void nasal_ast::set_str(std::string& s) -{ - str=s; - return; -} - -void nasal_ast::set_num(double n) -{ - num=n; - return; -} - -void nasal_ast::add_child(nasal_ast ast) -{ - children.push_back(ast); - return; -} - -int nasal_ast::get_line() -{ - return line; -} - -int nasal_ast::get_type() -{ - return type; -} - -std::string& nasal_ast::get_str() -{ - return str; -} - -double nasal_ast::get_num() -{ - return num; -} - -std::vector& nasal_ast::get_children() -{ - return children; -} - void nasal_ast::print_ast(int depth) { std::string indentation=""; for(int i=0;i&,nasal_gc&); nasal_val* builtin_cmp(std::vector&,nasal_gc&); nasal_val* builtin_chr(std::vector&,nasal_gc&); -void builtin_err(std::string func_name,std::string info) +void builtin_err(const char* func_name,std::string info) { std::cout<<">> [vm] "<&,nasal_gc&); } builtin_func[]= { diff --git a/nasal_codegen.h b/nasal_codegen.h index 56a933b..fe0e074 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -216,13 +216,13 @@ private: void ret_gen(nasal_ast&); public: nasal_codegen(); - int get_error(); + int get_error(){return error;} void main_progress(nasal_ast&); void print_op(int); void print_byte_code(); - std::vector& get_str_table(); - std::vector& get_num_table(); - std::vector& get_exec_code(); + std::vector& get_str_table(){return str_res_table;} + std::vector& get_num_table(){return num_res_table;} + std::vector& get_exec_code(){return exec_code;} }; nasal_codegen::nasal_codegen() @@ -420,7 +420,7 @@ void nasal_codegen::func_gen(nasal_ast& ast) exec_code[local_label].num+=i.size(); local.pop_back(); - if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return) + if(!block.get_children().size() || block.get_children().back().get_type()!=ast_ret) { nil_gen(); gen(op_ret,0); @@ -708,10 +708,10 @@ void nasal_codegen::loop_gen(nasal_ast& ast) void nasal_codegen::load_continue_break(int continue_place,int break_place) { - for(int i=0;i& nasal_codegen::get_str_table() -{ - return str_res_table; -} - -std::vector& nasal_codegen::get_num_table() -{ - return num_res_table; -} - -std::vector& nasal_codegen::get_exec_code() -{ - return exec_code; -} - -int nasal_codegen::get_error() -{ - return error; -} - #endif \ No newline at end of file diff --git a/nasal_gc.h b/nasal_gc.h index 8217226..ce2f94f 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -242,11 +242,11 @@ std::string nasal_val::to_string() struct nasal_gc { -#define STACK_MAX_DEPTH (65536<<4) +#define STACK_MAX_DEPTH (65536<<2) nasal_val* zero_addr; // reserved address of nasal_val,type vm_num, 0 nasal_val* one_addr; // reserved address of nasal_val,type vm_num, 1 nasal_val* nil_addr; // reserved address of nasal_val,type vm_nil - nasal_val* val_stack[STACK_MAX_DEPTH]; + nasal_val* val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow nasal_val** stack_top; // stack top std::vector num_addrs; // reserved address for const vm_num std::vector str_addrs; // reserved address for const vm_str @@ -344,17 +344,15 @@ void nasal_gc::gc_init(std::vector& nums,std::vector& strs) num_addrs.resize(nums.size()); for(int i=0;iptr.num=nums[i]; - num_addrs[i]=tmp; + num_addrs[i]=new nasal_val(vm_num); + num_addrs[i]->ptr.num=nums[i]; } // init constant strings str_addrs.resize(strs.size()); for(int i=0;iptr.str=strs[i]; - str_addrs[i]=tmp; + str_addrs[i]=new nasal_val(vm_str); + *str_addrs[i]->ptr.str=strs[i]; } return; } diff --git a/nasal_import.h b/nasal_import.h index 0009ecf..52f651b 100644 --- a/nasal_import.h +++ b/nasal_import.h @@ -4,24 +4,24 @@ class nasal_import { private: - nasal_lexer import_lex; - nasal_parse import_par; - nasal_ast import_ast; - std::vector filename_table; int error; - void die(std::string,std::string); + nasal_lexer import_lex; + nasal_parse import_par; + nasal_ast import_ast; + std::vector filename_table; + void die(std::string&,const char*); bool check_import(nasal_ast&); - bool check_exist(std::string); + bool check_exist(std::string&); void linker(nasal_ast&,nasal_ast&); nasal_ast file_import(nasal_ast&); nasal_ast load(nasal_ast&); public: - int get_error(); + int get_error(){return error;} void link(nasal_ast&); - nasal_ast& get_root(); + nasal_ast& get_root(){return import_ast;} }; -void nasal_import::die(std::string filename,std::string error_stage) +void nasal_import::die(std::string& filename,const char* error_stage) { ++error; std::cout<<">> [import] in <\""<: error(s) occurred in "< res; std::vector token_list; - int get_tok_type(std::string); - void die(std::string,std::string,int,int); + int get_tok_type(std::string&); + void die(std::string,int); std::string id_gen(); std::string num_gen(); std::string str_gen(); public: - void openfile(std::string); + void openfile(std::string&); void scanner(); void print_token(); - int get_error(); - std::vector& get_token_list(); + int get_error(){return error;} + std::vector& get_token_list(){return token_list;} }; -void nasal_lexer::openfile(std::string filename) +void nasal_lexer::openfile(std::string& filename) { error=0; res.clear(); @@ -126,7 +126,6 @@ void nasal_lexer::openfile(std::string filename) ++error; std::cout<<">> [lexer] cannot open file \""<> [lexer] line "<> [lexer] line "<=res_size) { line_code+=token_str; - die(line_code,"incorrect number.",line,line_code.length()); + die("incorrect number.",line); return "0"; } while(ptr=res_size) { line_code+=token_str; - die(line_code,"incorrect number.",line,line_code.length()); + die("incorrect number.",line); return "0"; } if(ptr=res_size) { line_code+=token_str; - die(line_code,"incorrect number.",line,line_code.length()); + die("incorrect number.",line); return "0"; } while(ptr=res_size) - die(line_code,"get EOF when generating string.",line,line_code.length()); + die("get EOF when generating string.",line); if(str_begin=='`' && token_str.length()>1) - die(line_code,"\'`\' is used for string that includes one character.",line,line_code.length()); + die("\'`\' is used for string that includes one character.",line); return token_str; } @@ -309,6 +307,7 @@ void nasal_lexer::scanner() line=1; ptr=0; line_code=""; + res_size=res.size(); std::string token_str; while(ptr& nasal_lexer::get_token_list() -{ - return token_list; -} #endif \ No newline at end of file diff --git a/nasal_parse.h b/nasal_parse.h index 453579b..248e3ad 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -99,20 +99,11 @@ private: nasal_ast break_expr(); nasal_ast ret_expr(); public: - int get_error(); - void set_toklist(std::vector&); + int get_error(){return error;} + void set_toklist(std::vector& toks){tok_list=toks;} void main_process(); - nasal_ast& get_root(); + nasal_ast& get_root(){return root;} }; -int nasal_parse::get_error() -{ - return error; -} -void nasal_parse::set_toklist(std::vector& toks) -{ - tok_list=toks; - return; -} void nasal_parse::main_process() { reset(); @@ -147,10 +138,6 @@ void nasal_parse::main_process() <<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n"; return; } -nasal_ast& nasal_parse::get_root() -{ - return root; -} void nasal_parse::reset() { ptr=in_function=in_loop=error=0; @@ -237,7 +224,7 @@ bool nasal_parse::check_function_end(nasal_ast& node) if( node.get_children().empty() || ( - type!=ast_definition && + type!=ast_def && type!=ast_equal && type!=ast_addeq && type!=ast_subeq && @@ -695,7 +682,7 @@ nasal_ast nasal_parse::scalar() else if(tok_list[ptr].type==tok_var) { match(tok_var); - node.set_type(ast_definition); + node.set_type(ast_def); node.add_child(id_gen()); match(tok_id); match(tok_eq); @@ -795,7 +782,7 @@ nasal_ast nasal_parse::subvec() } nasal_ast nasal_parse::definition() { - nasal_ast node(tok_list[ptr].line,ast_definition); + nasal_ast node(tok_list[ptr].line,ast_def); if(tok_list[ptr].type==tok_var) { match(tok_var); @@ -1058,7 +1045,7 @@ nasal_ast nasal_parse::break_expr() } nasal_ast nasal_parse::ret_expr() { - nasal_ast node(tok_list[ptr].line,ast_return); + nasal_ast node(tok_list[ptr].line,ast_ret); match(tok_ret); int type=tok_list[ptr].type; if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func || diff --git a/nasal_vm.h b/nasal_vm.h index 4de1bb0..58d9807 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -82,7 +82,7 @@ private: void opr_mcallh(); void opr_ret(); public: - nasal_vm(); + nasal_vm():stack_top(gc.stack_top){}; void init( std::vector&, std::vector&, @@ -91,11 +91,6 @@ public: void run(); }; -nasal_vm::nasal_vm():stack_top(gc.stack_top) -{ - return; -} - void nasal_vm::init( std::vector& strs, std::vector& nums, @@ -123,7 +118,7 @@ void nasal_vm::clear() } void nasal_vm::die(std::string str) { - printf(">> [vm] 0x%.8x: %s\n",pc,str.data()); + printf(">> [vm] 0x%.8x: %s\n",pc,str.c_str()); loop_mark=false; return; } @@ -137,7 +132,7 @@ bool nasal_vm::condition(nasal_val* val_addr) std::string& str=*val_addr->ptr.str; double number=str2num(str.c_str()); if(std::isnan(number)) - return !str.empty(); + return str.empty(); return number; } return false; @@ -262,20 +257,19 @@ void nasal_vm::opr_unot() nasal_val* new_val=nullptr; int type=val->type; if(type==vm_nil) - new_val=gc.one_addr; + *stack_top=gc.one_addr; else if(type==vm_num) - new_val=val->ptr.num?gc.zero_addr:gc.one_addr; + *stack_top=val->ptr.num?gc.zero_addr:gc.one_addr; else if(type==vm_str) { double number=str2num(val->ptr.str->c_str()); if(std::isnan(number)) - new_val=val->ptr.str->empty()?gc.one_addr:gc.zero_addr; + *stack_top=val->ptr.str->empty()?gc.one_addr:gc.zero_addr; else - new_val=number?gc.zero_addr:gc.one_addr; + *stack_top=number?gc.zero_addr:gc.one_addr; } else die("unot: incorrect value type"); - *stack_top=new_val; return; } void nasal_vm::opr_usub() @@ -433,9 +427,7 @@ void nasal_vm::opr_less() { nasal_val* val2=*stack_top--; nasal_val* val1=*stack_top; - int a_type=val1->type; - int b_type=val2->type; - if(a_type==vm_str && b_type==vm_str) + if(val1->type==vm_str && val2->type==vm_str) *stack_top=(*val1->ptr.str<*val2->ptr.str)?gc.one_addr:gc.zero_addr; else *stack_top=(val1->to_number()to_number())?gc.one_addr:gc.zero_addr; @@ -445,9 +437,7 @@ void nasal_vm::opr_leq() { nasal_val* val2=*stack_top--; nasal_val* val1=*stack_top; - int a_type=val1->type; - int b_type=val2->type; - if(a_type==vm_str && b_type==vm_str) + if(val1->type==vm_str && val2->type==vm_str) *stack_top=(*val1->ptr.str<=*val2->ptr.str)?gc.one_addr:gc.zero_addr; else *stack_top=(val1->to_number()<=val2->to_number())?gc.one_addr:gc.zero_addr; @@ -457,9 +447,7 @@ void nasal_vm::opr_grt() { nasal_val* val2=*stack_top--; nasal_val* val1=*stack_top; - int a_type=val1->type; - int b_type=val2->type; - if(a_type==vm_str && b_type==vm_str) + if(val1->type==vm_str && val2->type==vm_str) *stack_top=(*val1->ptr.str>*val2->ptr.str)?gc.one_addr:gc.zero_addr; else *stack_top=(val1->to_number()>val2->to_number())?gc.one_addr:gc.zero_addr; @@ -469,9 +457,7 @@ void nasal_vm::opr_geq() { nasal_val* val2=*stack_top--; nasal_val* val1=*stack_top; - int a_type=val1->type; - int b_type=val2->type; - if(a_type==vm_str && b_type==vm_str) + if(val1->type==vm_str && val2->type==vm_str) *stack_top=(*val1->ptr.str>=*val2->ptr.str)?gc.one_addr:gc.zero_addr; else *stack_top=(val1->to_number()>=val2->to_number())?gc.one_addr:gc.zero_addr; @@ -502,12 +488,9 @@ void nasal_vm::opr_jf() } void nasal_vm::opr_counter() { - if((*stack_top)->type!=vm_vec) - { - die("cnt: must use vector in forindex/foreach"); - return; - } counter.push(-1); + if((*stack_top)->type!=vm_vec) + die("cnt: must use vector in forindex/foreach"); return; } void nasal_vm::opr_cntpop() @@ -556,15 +539,10 @@ void nasal_vm::opr_callv() int type=vec_addr->type; if(type==vm_vec) { - int num=val->to_number(); - nasal_val* res=vec_addr->ptr.vec->get_val(num); - if(res) - *stack_top=res; - else - { + nasal_val* res=vec_addr->ptr.vec->get_val(val->to_number()); + if(!res) die("callv: index out of range"); - return; - } + *stack_top=res; } else if(type==vm_hash) { @@ -612,10 +590,7 @@ void nasal_vm::opr_callvi() // cannot use operator[],because this may cause overflow nasal_val* res=val->ptr.vec->get_val(exec_code[pc].num); if(!res) - { die("callvi: index out of range"); - return; - } *(++stack_top)=res; return; } @@ -646,7 +621,7 @@ void nasal_vm::opr_callfv() nasal_val* func_addr=*(vec-1); if(func_addr->type!=vm_func) { - die("callfv: called a value that is not a function"); + die("callfv: must call a function"); return; } // push new local scope @@ -690,7 +665,7 @@ void nasal_vm::opr_callfh() nasal_val* func_addr=*(stack_top-1); if(func_addr->type!=vm_func) { - die("callfh: called a value that is not a function"); + die("callfh: must call a function"); return; } // push new local scope @@ -756,10 +731,9 @@ void nasal_vm::opr_slc() default:die("slc: error value type");break; } nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num); - if(res) - gc.slice_stack.back()->ptr.vec->elems.push_back(res); - else + if(!res) die("slc: index out of range"); + gc.slice_stack.back()->ptr.vec->elems.push_back(res); return; } void nasal_vm::opr_slc2() @@ -824,10 +798,7 @@ void nasal_vm::opr_mcallv() } nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num); if(!res) - { die("mcallv: index out of range"); - return; - } addr_stack.push(res); } else if(type==vm_hash) @@ -848,10 +819,7 @@ void nasal_vm::opr_mcallv() addr_stack.push(res); } else - { die("mcallv: cannot get memory space in a string"); - return; - } return; } void nasal_vm::opr_mcallh() @@ -957,6 +925,8 @@ void nasal_vm::run() for(pc=0;loop_mark&&!gc.val_stack[STACK_MAX_DEPTH-1];++pc) (this->*opr_table[exec_code[pc].op])(); float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC; + if(gc.val_stack[STACK_MAX_DEPTH-1]) + die("stack overflow"); std::cout<<">> [vm] process exited after "<