front end optimization&stack overflow prompt

change parameter type to avoid unnecessary copies of string.
change stack depth from 65536<<4 to 16+(65536<<2).
now you could know stack overflow when it happens
This commit is contained in:
Valk Richard Li 2021-06-07 23:53:43 +08:00
parent 9f2c31149a
commit 3deea632f8
10 changed files with 172 additions and 396 deletions

View File

@ -1,8 +1,10 @@
# Nasal Script Language # Nasal Script Language
## Introduction
[Nasal](http://wiki.flightgear.org/Nasal_scripting_language) is a script language that used in [FlightGear](https://www.flightgear.org/). [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(<https://github.com/andyross/nasal>). 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! 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). (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(<https://github.com/andyross>).
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. 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). 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. 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 > g++ -std=c++11 -O2 main.cpp -o main.exe
# Parser ## Parser
LL(k) 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. 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. 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. 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. 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. 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. 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... 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. 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. 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. 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 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. 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. 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. 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 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. 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 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. 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 ```javascript
1+2; 1+2;
@ -311,7 +313,7 @@ a/=1;
a~='string'; a~='string';
``` ```
## definition ### definition
```javascript ```javascript
var a=1; var a=1;
@ -321,14 +323,14 @@ var (a,b,c)=(0,1,2);
(var a,b,c)=(0,1,2); (var a,b,c)=(0,1,2);
``` ```
## multi-assignment ### multi-assignment
```javascript ```javascript
(a,b[0],c.d)=[0,1,2]; (a,b[0],c.d)=[0,1,2];
(a,b[1],c.e)=(0,1,2); (a,b[1],c.e)=(0,1,2);
``` ```
## conditional expression ### conditional expression
```javascript ```javascript
if(1) if(1)
@ -349,7 +351,7 @@ else
} }
``` ```
## loop ### loop
```javascript ```javascript
while(condition) while(condition)
@ -365,7 +367,7 @@ foreach(var i;elem)
print(i); 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(). 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]; "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). 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); a(x:0,y:1,z:2);
``` ```
## lambda ### lambda
Also functions have this kind of use: 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); func(x){return 1/(1+math.exp(-x));}(0.5);
``` ```
## closure ### closure
Use closure to OOP. 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. Must import lib.nas or has these functions' definitions inside your code.
@ -522,11 +524,3 @@ nasal_val* builtin_getkeys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return ret_addr; return ret_addr;
} }
``` ```
# 写在最后
我要怎么才能告诉gitee的逆天管理员gitee上的ValKmjolnir和github的ValKmjolnir是一个人
他居然告诉我我从github同步的仓库是他人项目
我证明我是我自己?:sweat_smile:

View File

@ -28,7 +28,7 @@ void logo()
return; return;
} }
void die(std::string stage,std::string filename) void die(const char* stage,std::string& filename)
{ {
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n"; std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
return; return;

View File

@ -4,8 +4,7 @@
enum ast_node enum ast_node
{ {
ast_null=0, ast_null=0,
ast_root, ast_root,ast_block,
ast_block,
ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec, 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_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec,
ast_args,ast_default_arg,ast_dynamic_id, 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_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
ast_conditional,ast_if,ast_elsif,ast_else, ast_conditional,ast_if,ast_elsif,ast_else,
ast_multi_id,ast_multi_scalar, ast_multi_id,ast_multi_scalar,
ast_definition,ast_multi_assign, ast_def,ast_multi_assign,
ast_continue,ast_break,ast_return ast_continue,ast_break,ast_ret
}; };
std::string ast_name(int type) const char* ast_name[]=
{ {
switch(type) "null",
{ "root","block",
case ast_null: return "null"; "nil","num","str","id","func","hash","vec",
case ast_root: return "root"; "hashmember","call","callh","callv","callf","subvec",
case ast_block: return "block"; "args","deflt_arg","dyn_id",
case ast_nil: return "nil"; "and","or",
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"; "unary-","unary!",
case ast_hashmember: return "hashmember"; "trino",
case ast_call: return "call"; "for","forindex","foreach","while","iter",
case ast_callh: return "callh"; "conditional","if","elsif","else",
case ast_callv: return "callv"; "multi_id","multi_scalar",
case ast_callf: return "callf"; "def","multi_assign",
case ast_subvec: return "subvec"; "continue","break","return"
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";
}
class nasal_ast class nasal_ast
{ {
@ -98,39 +54,24 @@ private:
std::string str; std::string str;
std::vector<nasal_ast> children; std::vector<nasal_ast> children;
public: public:
nasal_ast(); nasal_ast(){line=0;type=ast_null;}
nasal_ast(int,int); nasal_ast(int l,int t){line=l;type=t;}
nasal_ast(const nasal_ast&); nasal_ast(const nasal_ast&);
~nasal_ast();
nasal_ast& operator=(const nasal_ast&); nasal_ast& operator=(const nasal_ast&);
void print_ast(int); void print_ast(int);
void clear(); void clear();
void set_line(int); void add_child(nasal_ast ast){children.push_back(ast);}
void set_type(int); void set_line(int l){line=l;}
void set_str(std::string&); void set_type(int t){type=t;}
void set_num(double); void set_str(std::string& s){str=s;}
void add_child(nasal_ast); void set_num(double n){num=n;}
int get_line(); int get_line(){return line;}
int get_type(); int get_type(){return type;}
double get_num(); double get_num(){return num;}
std::string& get_str(); std::string& get_str(){return str;}
std::vector<nasal_ast>& get_children(); std::vector<nasal_ast>& 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) nasal_ast::nasal_ast(const nasal_ast& tmp)
{ {
line=tmp.line; line=tmp.line;
@ -141,12 +82,6 @@ nasal_ast::nasal_ast(const nasal_ast& tmp)
return; return;
} }
nasal_ast::~nasal_ast()
{
children.clear();
return;
}
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp) nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
{ {
line=tmp.line; line=tmp.line;
@ -167,67 +102,12 @@ void nasal_ast::clear()
return; 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>& nasal_ast::get_children()
{
return children;
}
void nasal_ast::print_ast(int depth) void nasal_ast::print_ast(int depth)
{ {
std::string indentation=""; std::string indentation="";
for(int i=0;i<depth;++i) for(int i=0;i<depth;++i)
indentation+="| "; indentation+="| ";
std::cout<<indentation<<ast_name(type); std::cout<<indentation<<ast_name[type];
if(type==ast_str || type==ast_id || type==ast_dynamic_id || type==ast_callh) if(type==ast_str || type==ast_id || type==ast_dynamic_id || type==ast_callh)
std::cout<<":"<<str; std::cout<<":"<<str;
else if(type==ast_num) else if(type==ast_num)

View File

@ -55,7 +55,7 @@ nasal_val* builtin_right(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_cmp(std::vector<nasal_val*>&,nasal_gc&); nasal_val* builtin_cmp(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_chr(std::vector<nasal_val*>&,nasal_gc&); nasal_val* builtin_chr(std::vector<nasal_val*>&,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] "<<func_name<<": "<<info<<".\n"; std::cout<<">> [vm] "<<func_name<<": "<<info<<".\n";
return; return;
@ -65,7 +65,7 @@ void builtin_err(std::string func_name,std::string info)
// this table must end with {"",NULL} // this table must end with {"",NULL}
struct FUNC_TABLE struct FUNC_TABLE
{ {
std::string name; const char* name;
nasal_val* (*func)(std::vector<nasal_val*>&,nasal_gc&); nasal_val* (*func)(std::vector<nasal_val*>&,nasal_gc&);
} builtin_func[]= } builtin_func[]=
{ {

View File

@ -216,13 +216,13 @@ private:
void ret_gen(nasal_ast&); void ret_gen(nasal_ast&);
public: public:
nasal_codegen(); nasal_codegen();
int get_error(); int get_error(){return error;}
void main_progress(nasal_ast&); void main_progress(nasal_ast&);
void print_op(int); void print_op(int);
void print_byte_code(); void print_byte_code();
std::vector<std::string>& get_str_table(); std::vector<std::string>& get_str_table(){return str_res_table;}
std::vector<double>& get_num_table(); std::vector<double>& get_num_table(){return num_res_table;}
std::vector<opcode>& get_exec_code(); std::vector<opcode>& get_exec_code(){return exec_code;}
}; };
nasal_codegen::nasal_codegen() nasal_codegen::nasal_codegen()
@ -420,7 +420,7 @@ void nasal_codegen::func_gen(nasal_ast& ast)
exec_code[local_label].num+=i.size(); exec_code[local_label].num+=i.size();
local.pop_back(); 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(); nil_gen();
gen(op_ret,0); 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) void nasal_codegen::load_continue_break(int continue_place,int break_place)
{ {
for(int i=0;i<continue_ptr.front().size();++i) for(auto i:continue_ptr.front())
exec_code[continue_ptr.front()[i]].num=continue_place; exec_code[i].num=continue_place;
for(int i=0;i<break_ptr.front().size();++i) for(auto i:break_ptr.front())
exec_code[break_ptr.front()[i]].num=break_place; exec_code[i].num=break_place;
continue_ptr.pop_front(); continue_ptr.pop_front();
break_ptr.pop_front(); break_ptr.pop_front();
return; return;
@ -737,7 +737,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
switch(ast.get_children()[0].get_type()) switch(ast.get_children()[0].get_type())
{ {
case ast_null:break; case ast_null:break;
case ast_definition:def_gen(ast.get_children()[0]);break; case ast_def:def_gen(ast.get_children()[0]);break;
case ast_multi_assign:multi_assign_gen(ast.get_children()[0]);break; case ast_multi_assign:multi_assign_gen(ast.get_children()[0]);break;
case ast_nil: case ast_nil:
case ast_num: case ast_num:
@ -780,7 +780,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
switch(ast.get_children()[2].get_type()) switch(ast.get_children()[2].get_type())
{ {
case ast_null:break; case ast_null:break;
case ast_definition:def_gen(ast.get_children()[2]);break; case ast_def:def_gen(ast.get_children()[2]);break;
case ast_multi_assign:multi_assign_gen(ast.get_children()[2]);break; case ast_multi_assign:multi_assign_gen(ast.get_children()[2]);break;
case ast_nil:case ast_num:case ast_str:case ast_func:break; case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_vec:case ast_hash: case ast_vec:case ast_hash:
@ -955,7 +955,7 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
calc_gen(ast.get_children()[0]); calc_gen(ast.get_children()[0]);
gen(op_unot,0); gen(op_unot,0);
break; break;
case ast_definition: case ast_def:
single_def(ast); single_def(ast);
call_id(ast.get_children()[0]); call_id(ast.get_children()[0]);
break; break;
@ -969,7 +969,7 @@ void nasal_codegen::block_gen(nasal_ast& ast)
switch(tmp.get_type()) switch(tmp.get_type())
{ {
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break; case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_definition:def_gen(tmp);break; case ast_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break; case ast_multi_assign:multi_assign_gen(tmp);break;
case ast_conditional:conditional_gen(tmp);break; case ast_conditional:conditional_gen(tmp);break;
case ast_continue: case ast_continue:
@ -1010,7 +1010,7 @@ void nasal_codegen::block_gen(nasal_ast& ast)
case ast_or: case ast_or:
case ast_and: case ast_and:
case ast_trino:calc_gen(tmp);pop_gen();break; case ast_trino:calc_gen(tmp);pop_gen();break;
case ast_return:ret_gen(tmp);break; case ast_ret:ret_gen(tmp);break;
} }
return; return;
} }
@ -1045,14 +1045,12 @@ void nasal_codegen::main_progress(nasal_ast& ast)
global.clear(); global.clear();
local.clear(); local.clear();
gen(op_intg,0); gen(op_intg,0);
int size=ast.get_children().size(); for(auto& tmp:ast.get_children())
for(int i=0;i<size;++i)
{ {
nasal_ast& tmp=ast.get_children()[i];
switch(tmp.get_type()) switch(tmp.get_type())
{ {
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break; case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_definition:def_gen(tmp);break; case ast_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break; case ast_multi_assign:multi_assign_gen(tmp);break;
case ast_conditional:conditional_gen(tmp);break; case ast_conditional:conditional_gen(tmp);break;
case ast_while: case ast_while:
@ -1100,31 +1098,22 @@ void nasal_codegen::main_progress(nasal_ast& ast)
void nasal_codegen::print_op(int index) void nasal_codegen::print_op(int index)
{ {
// print opcode ptr // print opcode index,opcode name,opcode immediate number
printf("0x%.8x: ",index); printf("0x%.8x: %s 0x%.8x",index,code_table[exec_code[index].op].name,exec_code[index].num);
// print opcode name
for(int i=0;code_table[i].name;++i)
if(exec_code[index].op==code_table[i].type)
{
std::cout<<code_table[i].name<<" ";
break;
}
// print opcode index
printf("0x%.8x ",exec_code[index].num);
// print detail info // print detail info
switch(exec_code[index].op) switch(exec_code[index].op)
{ {
case op_pnum:std::cout<<'('<<num_res_table[exec_code[index].num]<<')';break; case op_pnum:printf(" (%lf)\n",num_res_table[exec_code[index].num]);break;
case op_callb:std::cout<<'('<<builtin_func[exec_code[index].num].name<<')';break; case op_callb:printf(" (%s)\n",builtin_func[exec_code[index].num].name);break;
case op_happ: case op_happ:
case op_pstr: case op_pstr:
case op_callh: case op_callh:
case op_mcallh: case op_mcallh:
case op_para: case op_para:
case op_defpara: case op_defpara:
case op_dynpara:std::cout<<'('<<str_res_table[exec_code[index].num]<<')';break; case op_dynpara:printf(" (%s)\n",str_res_table[exec_code[index].num].c_str());break;
default:printf("\n");break;
} }
std::cout<<'\n';
return; return;
} }
@ -1134,30 +1123,9 @@ void nasal_codegen::print_byte_code()
std::cout<<".number "<<num<<'\n'; std::cout<<".number "<<num<<'\n';
for(auto& str:str_res_table) for(auto& str:str_res_table)
std::cout<<".symbol "<<str<<'\n'; std::cout<<".symbol "<<str<<'\n';
int size=exec_code.size(); for(int i=0;i<exec_code.size();++i)
for(int i=0;i<size;++i)
print_op(i); print_op(i);
return; return;
} }
std::vector<std::string>& nasal_codegen::get_str_table()
{
return str_res_table;
}
std::vector<double>& nasal_codegen::get_num_table()
{
return num_res_table;
}
std::vector<opcode>& nasal_codegen::get_exec_code()
{
return exec_code;
}
int nasal_codegen::get_error()
{
return error;
}
#endif #endif

View File

@ -242,11 +242,11 @@ std::string nasal_val::to_string()
struct nasal_gc 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* 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* 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* 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 nasal_val** stack_top; // stack top
std::vector<nasal_val*> num_addrs; // reserved address for const vm_num std::vector<nasal_val*> num_addrs; // reserved address for const vm_num
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
@ -344,17 +344,15 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
num_addrs.resize(nums.size()); num_addrs.resize(nums.size());
for(int i=0;i<nums.size();++i) for(int i=0;i<nums.size();++i)
{ {
nasal_val* tmp=new nasal_val(vm_num); num_addrs[i]=new nasal_val(vm_num);
tmp->ptr.num=nums[i]; num_addrs[i]->ptr.num=nums[i];
num_addrs[i]=tmp;
} }
// init constant strings // init constant strings
str_addrs.resize(strs.size()); str_addrs.resize(strs.size());
for(int i=0;i<strs.size();++i) for(int i=0;i<strs.size();++i)
{ {
nasal_val* tmp=new nasal_val(vm_str); str_addrs[i]=new nasal_val(vm_str);
*tmp->ptr.str=strs[i]; *str_addrs[i]->ptr.str=strs[i];
str_addrs[i]=tmp;
} }
return; return;
} }

View File

@ -4,24 +4,24 @@
class nasal_import class nasal_import
{ {
private: private:
nasal_lexer import_lex;
nasal_parse import_par;
nasal_ast import_ast;
std::vector<std::string> filename_table;
int error; int error;
void die(std::string,std::string); nasal_lexer import_lex;
nasal_parse import_par;
nasal_ast import_ast;
std::vector<std::string> filename_table;
void die(std::string&,const char*);
bool check_import(nasal_ast&); bool check_import(nasal_ast&);
bool check_exist(std::string); bool check_exist(std::string&);
void linker(nasal_ast&,nasal_ast&); void linker(nasal_ast&,nasal_ast&);
nasal_ast file_import(nasal_ast&); nasal_ast file_import(nasal_ast&);
nasal_ast load(nasal_ast&); nasal_ast load(nasal_ast&);
public: public:
int get_error(); int get_error(){return error;}
void link(nasal_ast&); 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; ++error;
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<".\n"; std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<".\n";
@ -51,7 +51,7 @@ only this kind of node can be recognized as 'import':
return true; return true;
} }
bool nasal_import::check_exist(std::string filename) bool nasal_import::check_exist(std::string& filename)
{ {
// avoid importing the same file // avoid importing the same file
for(auto& fname:filename_table) for(auto& fname:filename_table)
@ -75,7 +75,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
nasal_ast tmp(0,ast_root); nasal_ast tmp(0,ast_root);
// get filename and set node to ast_null // get filename and set node to ast_null
std::string filename=node.get_children()[1].get_children()[0].get_str(); std::string& filename=node.get_children()[1].get_children()[0].get_str();
node.clear(); node.clear();
// avoid infinite loading loop // avoid infinite loading loop
@ -131,14 +131,4 @@ void nasal_import::link(nasal_ast& root)
return; return;
} }
nasal_ast& nasal_import::get_root()
{
return import_ast;
}
int nasal_import::get_error()
{
return error;
}
#endif #endif

View File

@ -103,20 +103,20 @@ private:
std::string line_code; std::string line_code;
std::vector<char> res; std::vector<char> res;
std::vector<token> token_list; std::vector<token> token_list;
int get_tok_type(std::string); int get_tok_type(std::string&);
void die(std::string,std::string,int,int); void die(std::string,int);
std::string id_gen(); std::string id_gen();
std::string num_gen(); std::string num_gen();
std::string str_gen(); std::string str_gen();
public: public:
void openfile(std::string); void openfile(std::string&);
void scanner(); void scanner();
void print_token(); void print_token();
int get_error(); int get_error(){return error;}
std::vector<token>& get_token_list(); std::vector<token>& get_token_list(){return token_list;}
}; };
void nasal_lexer::openfile(std::string filename) void nasal_lexer::openfile(std::string& filename)
{ {
error=0; error=0;
res.clear(); res.clear();
@ -126,7 +126,6 @@ void nasal_lexer::openfile(std::string filename)
++error; ++error;
std::cout<<">> [lexer] cannot open file \""<<filename<<"\".\n"; std::cout<<">> [lexer] cannot open file \""<<filename<<"\".\n";
fin.close(); fin.close();
res_size=0;
return; return;
} }
while(!fin.eof()) while(!fin.eof())
@ -137,11 +136,10 @@ void nasal_lexer::openfile(std::string filename)
res.push_back(c); res.push_back(c);
} }
fin.close(); fin.close();
res_size=res.size();
return; return;
} }
int nasal_lexer::get_tok_type(std::string tk_str) int nasal_lexer::get_tok_type(std::string& tk_str)
{ {
for(int i=0;token_table[i].str;++i) for(int i=0;token_table[i].str;++i)
if(tk_str==token_table[i].str) if(tk_str==token_table[i].str)
@ -149,12 +147,12 @@ int nasal_lexer::get_tok_type(std::string tk_str)
return tok_null; return tok_null;
} }
void nasal_lexer::die(std::string code,std::string error_info,int line=-1,int column=-1) void nasal_lexer::die(std::string error_info,int line)
{ {
++error; ++error;
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": \n"<<code<<"\n"; std::cout<<">> [lexer] line "<<line<<" column "<<line_code.length()<<": \n"<<line_code<<"\n";
for(int i=0;i<column-1;++i) for(auto i:line_code)
std::cout<<(code[i]=='\t'?'\t':' '); std::cout<<(i=='\t'?'\t':' ');
std::cout<<"^ "<<error_info<<'\n'; std::cout<<"^ "<<error_info<<'\n';
return; return;
} }
@ -183,7 +181,7 @@ std::string nasal_lexer::num_gen()
line_code+=token_str; line_code+=token_str;
if(token_str=="0x") if(token_str=="0x")
{ {
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
return token_str; return token_str;
@ -198,7 +196,7 @@ std::string nasal_lexer::num_gen()
line_code+=token_str; line_code+=token_str;
if(token_str=="0o") if(token_str=="0o")
{ {
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
return token_str; return token_str;
@ -214,7 +212,7 @@ std::string nasal_lexer::num_gen()
if(ptr>=res_size) if(ptr>=res_size)
{ {
line_code+=token_str; line_code+=token_str;
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
while(ptr<res_size && IS_DIGIT(res[ptr])) while(ptr<res_size && IS_DIGIT(res[ptr]))
@ -223,7 +221,7 @@ std::string nasal_lexer::num_gen()
if(token_str.back()=='.') if(token_str.back()=='.')
{ {
line_code+=token_str; line_code+=token_str;
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
} }
@ -234,7 +232,7 @@ std::string nasal_lexer::num_gen()
if(ptr>=res_size) if(ptr>=res_size)
{ {
line_code+=token_str; line_code+=token_str;
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+')) if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
@ -242,7 +240,7 @@ std::string nasal_lexer::num_gen()
if(ptr>=res_size) if(ptr>=res_size)
{ {
line_code+=token_str; line_code+=token_str;
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
while(ptr<res_size && IS_DIGIT(res[ptr])) while(ptr<res_size && IS_DIGIT(res[ptr]))
@ -251,7 +249,7 @@ std::string nasal_lexer::num_gen()
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+') if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
{ {
line_code+=token_str; line_code+=token_str;
die(line_code,"incorrect number.",line,line_code.length()); die("incorrect number.",line);
return "0"; return "0";
} }
} }
@ -277,15 +275,15 @@ std::string nasal_lexer::str_gen()
line_code+=res[++ptr]; line_code+=res[++ptr];
switch(res[ptr]) switch(res[ptr])
{ {
case 'a':token_str.push_back('\a');break; case 'a': token_str.push_back('\a');break;
case 'b':token_str.push_back('\b');break; case 'b': token_str.push_back('\b');break;
case 'f':token_str.push_back('\f');break; case 'f': token_str.push_back('\f');break;
case 'n':token_str.push_back('\n');break; case 'n': token_str.push_back('\n');break;
case 'r':token_str.push_back('\r');break; case 'r': token_str.push_back('\r');break;
case 't':token_str.push_back('\t');break; case 't': token_str.push_back('\t');break;
case 'v':token_str.push_back('\v');break; case 'v': token_str.push_back('\v');break;
case '?':token_str.push_back('\?');break; case '?': token_str.push_back('\?');break;
case '0':token_str.push_back('\0');break; case '0': token_str.push_back('\0');break;
case '\\':token_str.push_back('\\');break; case '\\':token_str.push_back('\\');break;
case '\'':token_str.push_back('\'');break; case '\'':token_str.push_back('\'');break;
case '\"':token_str.push_back('\"');break; case '\"':token_str.push_back('\"');break;
@ -297,9 +295,9 @@ std::string nasal_lexer::str_gen()
} }
// check if this string ends with a " or ' // check if this string ends with a " or '
if(ptr++>=res_size) if(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) 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; return token_str;
} }
@ -309,6 +307,7 @@ void nasal_lexer::scanner()
line=1; line=1;
ptr=0; ptr=0;
line_code=""; line_code="";
res_size=res.size();
std::string token_str; std::string token_str;
while(ptr<res_size) while(ptr<res_size)
@ -351,7 +350,7 @@ void nasal_lexer::scanner()
line_code+=res[ptr]; line_code+=res[ptr];
token new_token(line,get_tok_type(token_str),token_str); token new_token(line,get_tok_type(token_str),token_str);
if(!new_token.type) if(!new_token.type)
die(line_code,"incorrect operator.",line,line_code.length()); die("incorrect operator.",line);
token_list.push_back(new_token); token_list.push_back(new_token);
++ptr; ++ptr;
} }
@ -386,7 +385,7 @@ void nasal_lexer::scanner()
else else
{ {
line_code+=res[ptr++]; line_code+=res[ptr++];
die(line_code,"unknown character.",line,line_code.length()); die("unknown character.",line);
} }
} }
token tk(line,tok_eof,""); token tk(line,tok_eof,"");
@ -397,19 +396,9 @@ void nasal_lexer::scanner()
void nasal_lexer::print_token() void nasal_lexer::print_token()
{ {
int size=token_list.size(); for(auto tok:token_list)
for(int i=0;i<size;++i) std::cout<<"("<<tok.line<<" | "<<tok.str<<")\n";
std::cout<<"("<<token_list[i].line<<" | "<<token_list[i].str<<")\n";
return; return;
} }
int nasal_lexer::get_error()
{
return error;
}
std::vector<token>& nasal_lexer::get_token_list()
{
return token_list;
}
#endif #endif

View File

@ -99,20 +99,11 @@ private:
nasal_ast break_expr(); nasal_ast break_expr();
nasal_ast ret_expr(); nasal_ast ret_expr();
public: public:
int get_error(); int get_error(){return error;}
void set_toklist(std::vector<token>&); void set_toklist(std::vector<token>& toks){tok_list=toks;}
void main_process(); 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<token>& toks)
{
tok_list=toks;
return;
}
void nasal_parse::main_process() void nasal_parse::main_process()
{ {
reset(); reset();
@ -147,10 +138,6 @@ void nasal_parse::main_process()
<<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n"; <<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n";
return; return;
} }
nasal_ast& nasal_parse::get_root()
{
return root;
}
void nasal_parse::reset() void nasal_parse::reset()
{ {
ptr=in_function=in_loop=error=0; ptr=in_function=in_loop=error=0;
@ -237,7 +224,7 @@ bool nasal_parse::check_function_end(nasal_ast& node)
if( if(
node.get_children().empty() || node.get_children().empty() ||
( (
type!=ast_definition && type!=ast_def &&
type!=ast_equal && type!=ast_equal &&
type!=ast_addeq && type!=ast_addeq &&
type!=ast_subeq && type!=ast_subeq &&
@ -695,7 +682,7 @@ nasal_ast nasal_parse::scalar()
else if(tok_list[ptr].type==tok_var) else if(tok_list[ptr].type==tok_var)
{ {
match(tok_var); match(tok_var);
node.set_type(ast_definition); node.set_type(ast_def);
node.add_child(id_gen()); node.add_child(id_gen());
match(tok_id); match(tok_id);
match(tok_eq); match(tok_eq);
@ -795,7 +782,7 @@ nasal_ast nasal_parse::subvec()
} }
nasal_ast nasal_parse::definition() 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) if(tok_list[ptr].type==tok_var)
{ {
match(tok_var); match(tok_var);
@ -1058,7 +1045,7 @@ nasal_ast nasal_parse::break_expr()
} }
nasal_ast nasal_parse::ret_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); match(tok_ret);
int type=tok_list[ptr].type; int type=tok_list[ptr].type;
if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func || if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func ||

View File

@ -82,7 +82,7 @@ private:
void opr_mcallh(); void opr_mcallh();
void opr_ret(); void opr_ret();
public: public:
nasal_vm(); nasal_vm():stack_top(gc.stack_top){};
void init( void init(
std::vector<std::string>&, std::vector<std::string>&,
std::vector<double>&, std::vector<double>&,
@ -91,11 +91,6 @@ public:
void run(); void run();
}; };
nasal_vm::nasal_vm():stack_top(gc.stack_top)
{
return;
}
void nasal_vm::init( void nasal_vm::init(
std::vector<std::string>& strs, std::vector<std::string>& strs,
std::vector<double>& nums, std::vector<double>& nums,
@ -123,7 +118,7 @@ void nasal_vm::clear()
} }
void nasal_vm::die(std::string str) 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; loop_mark=false;
return; return;
} }
@ -137,7 +132,7 @@ bool nasal_vm::condition(nasal_val* val_addr)
std::string& str=*val_addr->ptr.str; std::string& str=*val_addr->ptr.str;
double number=str2num(str.c_str()); double number=str2num(str.c_str());
if(std::isnan(number)) if(std::isnan(number))
return !str.empty(); return str.empty();
return number; return number;
} }
return false; return false;
@ -262,20 +257,19 @@ void nasal_vm::opr_unot()
nasal_val* new_val=nullptr; nasal_val* new_val=nullptr;
int type=val->type; int type=val->type;
if(type==vm_nil) if(type==vm_nil)
new_val=gc.one_addr; *stack_top=gc.one_addr;
else if(type==vm_num) 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) else if(type==vm_str)
{ {
double number=str2num(val->ptr.str->c_str()); double number=str2num(val->ptr.str->c_str());
if(std::isnan(number)) 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 else
new_val=number?gc.zero_addr:gc.one_addr; *stack_top=number?gc.zero_addr:gc.one_addr;
} }
else else
die("unot: incorrect value type"); die("unot: incorrect value type");
*stack_top=new_val;
return; return;
} }
void nasal_vm::opr_usub() void nasal_vm::opr_usub()
@ -433,9 +427,7 @@ void nasal_vm::opr_less()
{ {
nasal_val* val2=*stack_top--; nasal_val* val2=*stack_top--;
nasal_val* val1=*stack_top; nasal_val* val1=*stack_top;
int a_type=val1->type; if(val1->type==vm_str && val2->type==vm_str)
int b_type=val2->type;
if(a_type==vm_str && b_type==vm_str)
*stack_top=(*val1->ptr.str<*val2->ptr.str)?gc.one_addr:gc.zero_addr; *stack_top=(*val1->ptr.str<*val2->ptr.str)?gc.one_addr:gc.zero_addr;
else else
*stack_top=(val1->to_number()<val2->to_number())?gc.one_addr:gc.zero_addr; *stack_top=(val1->to_number()<val2->to_number())?gc.one_addr:gc.zero_addr;
@ -445,9 +437,7 @@ void nasal_vm::opr_leq()
{ {
nasal_val* val2=*stack_top--; nasal_val* val2=*stack_top--;
nasal_val* val1=*stack_top; nasal_val* val1=*stack_top;
int a_type=val1->type; if(val1->type==vm_str && val2->type==vm_str)
int b_type=val2->type;
if(a_type==vm_str && b_type==vm_str)
*stack_top=(*val1->ptr.str<=*val2->ptr.str)?gc.one_addr:gc.zero_addr; *stack_top=(*val1->ptr.str<=*val2->ptr.str)?gc.one_addr:gc.zero_addr;
else else
*stack_top=(val1->to_number()<=val2->to_number())?gc.one_addr:gc.zero_addr; *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* val2=*stack_top--;
nasal_val* val1=*stack_top; nasal_val* val1=*stack_top;
int a_type=val1->type; if(val1->type==vm_str && val2->type==vm_str)
int b_type=val2->type;
if(a_type==vm_str && b_type==vm_str)
*stack_top=(*val1->ptr.str>*val2->ptr.str)?gc.one_addr:gc.zero_addr; *stack_top=(*val1->ptr.str>*val2->ptr.str)?gc.one_addr:gc.zero_addr;
else else
*stack_top=(val1->to_number()>val2->to_number())?gc.one_addr:gc.zero_addr; *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* val2=*stack_top--;
nasal_val* val1=*stack_top; nasal_val* val1=*stack_top;
int a_type=val1->type; if(val1->type==vm_str && val2->type==vm_str)
int b_type=val2->type;
if(a_type==vm_str && b_type==vm_str)
*stack_top=(*val1->ptr.str>=*val2->ptr.str)?gc.one_addr:gc.zero_addr; *stack_top=(*val1->ptr.str>=*val2->ptr.str)?gc.one_addr:gc.zero_addr;
else else
*stack_top=(val1->to_number()>=val2->to_number())?gc.one_addr:gc.zero_addr; *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() void nasal_vm::opr_counter()
{ {
if((*stack_top)->type!=vm_vec)
{
die("cnt: must use vector in forindex/foreach");
return;
}
counter.push(-1); counter.push(-1);
if((*stack_top)->type!=vm_vec)
die("cnt: must use vector in forindex/foreach");
return; return;
} }
void nasal_vm::opr_cntpop() void nasal_vm::opr_cntpop()
@ -556,15 +539,10 @@ void nasal_vm::opr_callv()
int type=vec_addr->type; int type=vec_addr->type;
if(type==vm_vec) if(type==vm_vec)
{ {
int num=val->to_number(); nasal_val* res=vec_addr->ptr.vec->get_val(val->to_number());
nasal_val* res=vec_addr->ptr.vec->get_val(num); if(!res)
if(res)
*stack_top=res;
else
{
die("callv: index out of range"); die("callv: index out of range");
return; *stack_top=res;
}
} }
else if(type==vm_hash) else if(type==vm_hash)
{ {
@ -612,10 +590,7 @@ void nasal_vm::opr_callvi()
// cannot use operator[],because this may cause overflow // cannot use operator[],because this may cause overflow
nasal_val* res=val->ptr.vec->get_val(exec_code[pc].num); nasal_val* res=val->ptr.vec->get_val(exec_code[pc].num);
if(!res) if(!res)
{
die("callvi: index out of range"); die("callvi: index out of range");
return;
}
*(++stack_top)=res; *(++stack_top)=res;
return; return;
} }
@ -646,7 +621,7 @@ void nasal_vm::opr_callfv()
nasal_val* func_addr=*(vec-1); nasal_val* func_addr=*(vec-1);
if(func_addr->type!=vm_func) if(func_addr->type!=vm_func)
{ {
die("callfv: called a value that is not a function"); die("callfv: must call a function");
return; return;
} }
// push new local scope // push new local scope
@ -690,7 +665,7 @@ void nasal_vm::opr_callfh()
nasal_val* func_addr=*(stack_top-1); nasal_val* func_addr=*(stack_top-1);
if(func_addr->type!=vm_func) if(func_addr->type!=vm_func)
{ {
die("callfh: called a value that is not a function"); die("callfh: must call a function");
return; return;
} }
// push new local scope // push new local scope
@ -756,10 +731,9 @@ void nasal_vm::opr_slc()
default:die("slc: error value type");break; default:die("slc: error value type");break;
} }
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num); nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
if(res) if(!res)
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
else
die("slc: index out of range"); die("slc: index out of range");
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
return; return;
} }
void nasal_vm::opr_slc2() void nasal_vm::opr_slc2()
@ -824,10 +798,7 @@ void nasal_vm::opr_mcallv()
} }
nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num); nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num);
if(!res) if(!res)
{
die("mcallv: index out of range"); die("mcallv: index out of range");
return;
}
addr_stack.push(res); addr_stack.push(res);
} }
else if(type==vm_hash) else if(type==vm_hash)
@ -848,10 +819,7 @@ void nasal_vm::opr_mcallv()
addr_stack.push(res); addr_stack.push(res);
} }
else else
{
die("mcallv: cannot get memory space in a string"); die("mcallv: cannot get memory space in a string");
return;
}
return; return;
} }
void nasal_vm::opr_mcallh() 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) for(pc=0;loop_mark&&!gc.val_stack[STACK_MAX_DEPTH-1];++pc)
(this->*opr_table[exec_code[pc].op])(); (this->*opr_table[exec_code[pc].op])();
float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC; 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 "<<total_time<<"s.\n"; std::cout<<">> [vm] process exited after "<<total_time<<"s.\n";
return; return;
} }