add license & other changes

parser recognizes syntax errors more accurately.
change some for loop to standard c++11 for(auto iter:obj)
add MIT license
change info in README.md
This commit is contained in:
Valk Richard Li 2021-05-04 17:39:24 +08:00
parent 6adb991c04
commit a463af53b7
8 changed files with 188 additions and 219 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 ValKmjolnir
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -2,13 +2,17 @@
[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 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!
Also,i am a member of [FGPRC](https://www.fgprc.org/), welcome to join us! 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. 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.
@ -379,22 +383,18 @@ nasal_val* builtin_print(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
// because local_scope[0] is reserved for value 'me' // because local_scope[0] is reserved for value 'me'
nasal_val* vector_value=local_scope[1]; nasal_val* vector_value=local_scope[1];
// main process // main process
// also check number of arguments and type here,if get a type error,use builtin_err and return nullptr // also check number of arguments and type here
nasal_vec& ref_vec=vector_value->get_vector(); // if get a type error,use builtin_err and return nullptr
int size=ref_vec.size(); for(auto i:vec_addr->ptr.vec->elems)
for(int i=0;i<size;++i) switch(i->type)
{
nasal_val* tmp=ref_vec[i];
switch(tmp->get_type())
{ {
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<tmp->get_number(); break; case vm_num: std::cout<<i->ptr.num; break;
case vm_str: std::cout<<tmp->get_string(); break; case vm_str: std::cout<<*i->ptr.str; break;
case vm_vec: tmp->get_vector().print(); break; case vm_vec: i->ptr.vec->print(); break;
case vm_hash: tmp->get_hash().print(); break; case vm_hash: i->ptr.hash->print(); break;
case vm_func: std::cout<<"func(...){...}"; break; case vm_func: std::cout<<"func(...){...}"; break;
} }
}
// if a nasal value is not in use,use gc::del_reference to delete it // if a nasal value is not in use,use gc::del_reference to delete it
// generate return value,use gc::gc_alloc(type) to make a new value // generate return value,use gc::gc_alloc(type) to make a new value
// or use reserved reference gc.nil_addr/gc.one_addr/gc.zero_addr // or use reserved reference gc.nil_addr/gc.one_addr/gc.zero_addr

View File

@ -102,8 +102,10 @@ int main()
#endif #endif
logo(); logo();
std::cout<<">> Nasal interpreter ver 6.0 .\n"; std::cout<<">> Nasal interpreter ver 6.0 .\n";
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n"; std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n";
std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n"; std::cout<<">> Code: https://gitee.com/valkmjolnir/Nasal-Interpreter\n";
std::cout<<">> Thanks: https://github.com/andyross/nasal\n";
std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n";
std::cout<<">> Input \"help\" to get help .\n"; std::cout<<">> Input \"help\" to get help .\n";
while(1) while(1)
{ {

View File

@ -119,21 +119,16 @@ nasal_val* builtin_print(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
// local_scope[0] is reserved for 'me' // local_scope[0] is reserved for 'me'
nasal_val* vec_addr=local_scope[1]; nasal_val* vec_addr=local_scope[1];
// main process // main process
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems; for(auto i:vec_addr->ptr.vec->elems)
int size=ref_vec.size(); switch(i->type)
for(int i=0;i<size;++i)
{
nasal_val* tmp=ref_vec[i];
switch(tmp->type)
{ {
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<tmp->ptr.num; break; case vm_num: std::cout<<i->ptr.num; break;
case vm_str: std::cout<<*tmp->ptr.str; break; case vm_str: std::cout<<*i->ptr.str; break;
case vm_vec: tmp->ptr.vec->print(); break; case vm_vec: i->ptr.vec->print(); break;
case vm_hash: tmp->ptr.hash->print(); break; case vm_hash: i->ptr.hash->print(); break;
case vm_func: std::cout<<"func(...){...}"; break; case vm_func: std::cout<<"func(...){...}"; break;
} }
}
// generate return value // generate return value
return gc.nil_addr; return gc.nil_addr;
} }
@ -147,10 +142,8 @@ nasal_val* builtin_append(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return nullptr; return nullptr;
} }
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems; std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems;
std::vector<nasal_val*>& ref_elems=elem_addr->ptr.vec->elems; for(auto i:elem_addr->ptr.vec->elems)
int size=ref_elems.size(); ref_vec.push_back(i);
for(int i=0;i<size;++i)
ref_vec.push_back(ref_elems[i]);
return gc.nil_addr; return gc.nil_addr;
} }
nasal_val* builtin_setsize(std::vector<nasal_val*>& local_scope,nasal_gc& gc) nasal_val* builtin_setsize(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
@ -173,14 +166,7 @@ nasal_val* builtin_setsize(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
builtin_err("setsize","\"size\" must be greater than -1"); builtin_err("setsize","\"size\" must be greater than -1");
return nullptr; return nullptr;
} }
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems; vec_addr->ptr.vec->elems.resize(num,gc.nil_addr);
int vec_size=ref_vec.size();
if(num<vec_size)
for(int i=num;i<vec_size;++i)
ref_vec.pop_back();
else if(num>vec_size)
for(int i=vec_size;i<num;++i)
ref_vec.push_back(gc.nil_addr);
return gc.nil_addr; return gc.nil_addr;
} }
@ -285,7 +271,6 @@ nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
std::string source=*string_val_addr->ptr.str; std::string source=*string_val_addr->ptr.str;
int delimeter_len=delimeter.length(); int delimeter_len=delimeter.length();
int source_len=source.length(); int source_len=source.length();
nasal_val* ret_addr=gc.gc_alloc(vm_vec); nasal_val* ret_addr=gc.gc_alloc(vm_vec);
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems; std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
std::string tmp=""; std::string tmp="";
@ -674,11 +659,10 @@ nasal_val* builtin_getkeys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
} }
nasal_val* ret_addr=gc.gc_alloc(vm_vec); nasal_val* ret_addr=gc.gc_alloc(vm_vec);
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems; std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
std::unordered_map<std::string,nasal_val*>& ref_hash=hash_addr->ptr.hash->elems; for(auto iter:hash_addr->ptr.hash->elems)
for(auto iter=ref_hash.begin();iter!=ref_hash.end();++iter)
{ {
nasal_val* str_addr=gc.gc_alloc(vm_str); nasal_val* str_addr=gc.gc_alloc(vm_str);
*str_addr->ptr.str=iter->first; *str_addr->ptr.str=iter.first;
ref_vec.push_back(str_addr); ref_vec.push_back(str_addr);
} }
return ret_addr; return ret_addr;
@ -687,7 +671,7 @@ nasal_val* builtin_import(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
{ {
// this function is used in preprocessing. // this function is used in preprocessing.
// this function will return nothing when running. // this function will return nothing when running.
builtin_err("import","cannot use import when running"); builtin_err("import","must use this function in global scope");
return nullptr; return nullptr;
} }
nasal_val* builtin_die(std::vector<nasal_val*>& local_scope,nasal_gc& gc) nasal_val* builtin_die(std::vector<nasal_val*>& local_scope,nasal_gc& gc)

View File

@ -3,44 +3,44 @@
enum op_code enum op_code
{ {
op_nop, op_nop, // do nothing and end the vm main loop
op_intg, op_intg, // global scope size
op_intl, op_intl, // local scope size
op_loadg, op_loadg, // load global symbol value
op_loadl, op_loadl, // load local symbol value
op_pnum, op_pnum, // push constant number to the stack
op_pone, op_pone, // push 1 to the stack
op_pzero, op_pzero, // push 0 to the stack
op_pnil, op_pnil, // push constant nil to the stack
op_pstr, op_pstr, // push constant string to the stack
op_newv, op_newv, // push new vector to the stack
op_newh, op_newh, // push new hash to the stack
op_newf, op_newf, // push new function to the stack
op_vapp, op_vapp, // vector append
op_happ, op_happ, // hash append
op_para, op_para, // normal parameter
op_defpara, op_defpara, // default parameter
op_dynpara, op_dynpara, // dynamic parameter
op_unot, op_unot, // !
op_usub, op_usub, // -
op_add, op_add, // +
op_sub, op_sub, // -
op_mul, op_mul, // *
op_div, op_div, // /
op_lnk, op_lnk, // ~
op_addeq, op_addeq, // +=
op_subeq, op_subeq, // -=
op_muleq, op_muleq, // *=
op_diveq, op_diveq, // /=
op_lnkeq, op_lnkeq, // ~=
op_meq, op_meq, // =
op_eq, op_eq, // ==
op_neq, op_neq, // !=
op_less, op_less, // <
op_leq, op_leq, // <=
op_grt, op_grt, // >
op_geq, op_geq, // >=
op_pop, op_pop, // pop a value from stack
op_jmp, // jump with no condition op_jmp, // jump with no condition
op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP
op_jf, // used in conditional/loop,jmp when condition is false and POP STACK op_jf, // used in conditional/loop,jmp when condition is false and POP STACK
@ -256,15 +256,15 @@ void nasal_codegen::add_sym(std::string name)
{ {
if(local.empty()) if(local.empty())
{ {
for(int i=0;i<global.size();++i) for(auto sym:global)
if(global[i]==name) if(sym==name)
return; return;
global.push_back(name); global.push_back(name);
} }
else else
{ {
for(int i=0;i<local.back().size();++i) for(auto sym:local.back())
if(local.back()[i]==name) if(sym==name)
return; return;
local.back().push_back(name); local.back().push_back(name);
} }
@ -275,12 +275,12 @@ int nasal_codegen::local_find(std::string& name)
{ {
int index=-1; int index=-1;
int cnt=0; int cnt=0;
for(auto i=local.begin();i!=local.end();++i) for(auto i:local)
{ {
for(int j=0;j<i->size();++j) for(int j=0;j<i.size();++j)
if((*i)[j]==name) if(i[j]==name)
index=cnt+j; index=cnt+j;
cnt+=i->size(); cnt+=i.size();
} }
return index; return index;
} }
@ -337,22 +337,20 @@ void nasal_codegen::str_gen(nasal_ast& ast)
void nasal_codegen::vec_gen(nasal_ast& ast) void nasal_codegen::vec_gen(nasal_ast& ast)
{ {
int size=ast.get_children().size();
gen(op_newv,0); gen(op_newv,0);
for(int i=0;i<size;++i) for(auto node:ast.get_children())
calc_gen(ast.get_children()[i]); calc_gen(node);
gen(op_vapp,size); gen(op_vapp,ast.get_children().size());
return; return;
} }
void nasal_codegen::hash_gen(nasal_ast& ast) void nasal_codegen::hash_gen(nasal_ast& ast)
{ {
int size=ast.get_children().size();
gen(op_newh,0); gen(op_newh,0);
for(int i=0;i<size;++i) for(auto node:ast.get_children())
{ {
calc_gen(ast.get_children()[i].get_children()[1]); calc_gen(node.get_children()[1]);
std::string str=ast.get_children()[i].get_children()[0].get_str(); std::string str=node.get_children()[0].get_str();
regist_string(str); regist_string(str);
gen(op_happ,string_table[str]); gen(op_happ,string_table[str]);
} }
@ -375,12 +373,9 @@ void nasal_codegen::func_gen(nasal_ast& ast)
// this symbol's index will be 0 // this symbol's index will be 0
if(local.size()==1) if(local.size()==1)
add_sym("me"); add_sym("me");
// generate parameter list
nasal_ast& ref_arg=ast.get_children()[0]; for(auto tmp:ast.get_children()[0].get_children())
int arg_size=ref_arg.get_children().size();
for(int i=0;i<arg_size;++i)
{ {
nasal_ast& tmp=ref_arg.get_children()[i];
if(tmp.get_type()==ast_id) if(tmp.get_type()==ast_id)
{ {
std::string str=tmp.get_str(); std::string str=tmp.get_str();
@ -463,7 +458,7 @@ void nasal_codegen::call_id(nasal_ast& ast)
gen(op_callg,index); gen(op_callg,index);
return; return;
} }
die("cannot find symbol named \""+str+"\".",ast.get_line()); die("undefined symbol \""+str+"\".",ast.get_line());
return; return;
} }
@ -484,10 +479,8 @@ void nasal_codegen::call_vec(nasal_ast& ast)
return; return;
} }
gen(op_slcbegin,0); gen(op_slcbegin,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];
if(tmp.get_type()!=ast_subvec) if(tmp.get_type()!=ast_subvec)
{ {
calc_gen(tmp); calc_gen(tmp);
@ -549,7 +542,7 @@ void nasal_codegen::mcall_id(nasal_ast& ast)
gen(op_mcallg,index); gen(op_mcallg,index);
return; return;
} }
die("cannot find symbol named \""+str+"\".",ast.get_line()); die("undefined symbol \""+str+"\".",ast.get_line());
return; return;
} }
@ -955,10 +948,7 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
void nasal_codegen::block_gen(nasal_ast& ast) void nasal_codegen::block_gen(nasal_ast& ast)
{ {
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;
@ -1005,7 +995,6 @@ void nasal_codegen::block_gen(nasal_ast& ast)
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_return:ret_gen(tmp);break;
} }
}
return; return;
} }
@ -1085,10 +1074,10 @@ void nasal_codegen::main_progress(nasal_ast& ast)
exec_code[0].num=global.size(); exec_code[0].num=global.size();
num_res_table.resize(number_table.size()); num_res_table.resize(number_table.size());
str_res_table.resize(string_table.size()); str_res_table.resize(string_table.size());
for(auto i=number_table.begin();i!=number_table.end();++i) for(auto i:number_table)
num_res_table[i->second]=i->first; num_res_table[i.second]=i.first;
for(auto i=string_table.begin();i!=string_table.end();++i) for(auto i:string_table)
str_res_table[i->second]=i->first; str_res_table[i.second]=i.first;
return; return;
} }
@ -1124,10 +1113,10 @@ void nasal_codegen::print_op(int index)
void nasal_codegen::print_byte_code() void nasal_codegen::print_byte_code()
{ {
for(int i=0;i<num_res_table.size();++i) for(auto num:num_res_table)
std::cout<<".number "<<num_res_table[i]<<'\n'; std::cout<<".number "<<num<<'\n';
for(int i=0;i<str_res_table.size();++i) for(auto str:str_res_table)
std::cout<<".symbol "<<str_res_table[i]<<'\n'; std::cout<<".symbol "<<str<<'\n';
int size=exec_code.size(); int size=exec_code.size();
for(int i=0;i<size;++i) for(int i=0;i<size;++i)
print_op(i); print_op(i);

View File

@ -96,23 +96,21 @@ nasal_val** nasal_vec::get_mem(int index)
void nasal_vec::print() void nasal_vec::print()
{ {
int size=elems.size(); int size=elems.size();
std::cout<<"["; std::cout<<'[';
if(!size) for(auto i:elems)
std::cout<<"]";
for(int i=0;i<size;++i)
{ {
nasal_val* tmp=elems[i]; switch(i->type)
switch(tmp->type)
{ {
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<tmp->ptr.num; break; case vm_num: std::cout<<i->ptr.num; break;
case vm_str: std::cout<<*tmp->ptr.str; break; case vm_str: std::cout<<*i->ptr.str; break;
case vm_vec: tmp->ptr.vec->print(); break; case vm_vec: i->ptr.vec->print(); break;
case vm_hash: tmp->ptr.hash->print(); break; case vm_hash: i->ptr.hash->print(); break;
case vm_func: std::cout<<"func(...){...}"; break; case vm_func: std::cout<<"func(...){...}"; break;
} }
std::cout<<",]"[i==size-1]; std::cout<<',';
} }
std::cout<<']';
return; return;
} }
@ -126,18 +124,13 @@ nasal_val* nasal_hash::get_val(std::string& key)
{ {
nasal_val* val_addr=elems["parents"]; nasal_val* val_addr=elems["parents"];
if(val_addr->type==vm_vec) if(val_addr->type==vm_vec)
{ for(auto i:val_addr->ptr.vec->elems)
std::vector<nasal_val*>& vec_ref=val_addr->ptr.vec->elems;
int size=vec_ref.size();
for(int i=0;i<size;++i)
{ {
nasal_val* tmp=vec_ref[i]; if(i->type==vm_hash)
if(tmp->type==vm_hash) ret_addr=i->ptr.hash->get_val(key);
ret_addr=tmp->ptr.hash->get_val(key);
if(ret_addr) if(ret_addr)
return ret_addr; return ret_addr;
} }
}
} }
return nullptr; return nullptr;
} }
@ -150,18 +143,13 @@ nasal_val** nasal_hash::get_mem(std::string& key)
{ {
nasal_val* val_addr=elems["parents"]; nasal_val* val_addr=elems["parents"];
if(val_addr->type==vm_vec) if(val_addr->type==vm_vec)
{ for(auto i:val_addr->ptr.vec->elems)
std::vector<nasal_val*>& vec_ref=val_addr->ptr.vec->elems;
int size=vec_ref.size();
for(int i=0;i<size;++i)
{ {
nasal_val* tmp=vec_ref[i]; if(i->type==vm_hash)
if(tmp->type==vm_hash) mem_addr=i->ptr.hash->get_mem(key);
mem_addr=tmp->ptr.hash->get_mem(key);
if(mem_addr) if(mem_addr)
return mem_addr; return mem_addr;
} }
}
} }
return nullptr; return nullptr;
} }
@ -175,13 +163,10 @@ bool nasal_hash::check_contain(std::string& key)
if(val_addr->type==vm_vec) if(val_addr->type==vm_vec)
{ {
bool result=false; bool result=false;
std::vector<nasal_val*>& vec_ref=val_addr->ptr.vec->elems; for(auto i:val_addr->ptr.vec->elems)
int size=vec_ref.size();
for(int i=0;i<size;++i)
{ {
nasal_val* tmp=vec_ref[i]; if(i->type==vm_hash)
if(tmp->type==vm_hash) result=i->ptr.hash->check_contain(key);
result=tmp->ptr.hash->check_contain(key);
if(result) if(result)
return true; return true;
} }
@ -192,15 +177,10 @@ bool nasal_hash::check_contain(std::string& key)
void nasal_hash::print() void nasal_hash::print()
{ {
std::cout<<'{'; std::cout<<'{';
if(!elems.size()) for(auto i:elems)
{ {
std::cout<<'}'; std::cout<<i.first<<':';
return; nasal_val* tmp=i.second;
}
for(auto i=elems.begin();i!=elems.end();++i)
{
std::cout<<i->first<<':';
nasal_val* tmp=i->second;
switch(tmp->type) switch(tmp->type)
{ {
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
@ -322,13 +302,13 @@ struct nasal_gc
void nasal_gc::mark() void nasal_gc::mark()
{ {
std::queue<nasal_val*> bfs; std::queue<nasal_val*> bfs;
for(auto i=global.begin();i!=global.end();++i) for(auto i:global)
bfs.push(*i); bfs.push(i);
for(auto i=local.begin();i!=local.end();++i) for(auto i:local)
for(auto j=i->begin();j!=i->end();++j) for(auto j:i)
bfs.push(*j); bfs.push(j);
for(auto i=slice_stack.begin();i!=slice_stack.end();++i) for(auto i:slice_stack)
bfs.push(*i); bfs.push(i);
for(nasal_val** i=val_stack;i<=stack_top;++i) for(nasal_val** i=val_stack;i<=stack_top;++i)
bfs.push(*i); bfs.push(*i);
while(!bfs.empty()) while(!bfs.empty())
@ -338,40 +318,31 @@ void nasal_gc::mark()
if(!tmp || tmp->mark) continue; if(!tmp || tmp->mark) continue;
tmp->mark=true; tmp->mark=true;
if(tmp->type==vm_vec) if(tmp->type==vm_vec)
{ for(auto i:tmp->ptr.vec->elems)
std::vector<nasal_val*>& vec=tmp->ptr.vec->elems; bfs.push(i);
for(auto i=vec.begin();i!=vec.end();++i)
bfs.push(*i);
}
else if(tmp->type==vm_hash) else if(tmp->type==vm_hash)
{ for(auto i:tmp->ptr.hash->elems)
std::unordered_map<std::string,nasal_val*>& hash=tmp->ptr.hash->elems; bfs.push(i.second);
for(auto i=hash.begin();i!=hash.end();++i)
bfs.push(i->second);
}
else if(tmp->type==vm_func) else if(tmp->type==vm_func)
{ {
std::vector<nasal_val*>& cls=tmp->ptr.func->closure; for(auto i:tmp->ptr.func->closure)
std::vector<nasal_val*>& def=tmp->ptr.func->default_para; bfs.push(i);
for(auto i=cls.begin();i!=cls.end();++i) for(auto i:tmp->ptr.func->default_para)
bfs.push(*i); bfs.push(i);
for(auto i=def.begin();i!=def.end();++i)
bfs.push(*i);
} }
} }
return; return;
} }
void nasal_gc::sweep() void nasal_gc::sweep()
{ {
int size=memory.size(); for(auto i:memory)
for(int i=0;i<size;++i)
{ {
if(!memory[i]->mark) if(!i->mark)
{ {
memory[i]->clear(); i->clear();
free_list.push(memory[i]); free_list.push(i);
} }
memory[i]->mark=false; i->mark=false;
} }
return; return;
} }
@ -414,11 +385,8 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
} }
void nasal_gc::gc_clear() void nasal_gc::gc_clear()
{ {
for(int i=0;i<memory.size();++i) for(auto i:memory)
{ delete i;
memory[i]->clear();
delete memory[i];
}
memory.clear(); memory.clear();
while(!free_list.empty()) while(!free_list.empty())
free_list.pop(); free_list.pop();
@ -429,11 +397,11 @@ void nasal_gc::gc_clear()
delete nil_addr; delete nil_addr;
delete one_addr; delete one_addr;
delete zero_addr; delete zero_addr;
for(int i=0;i<num_addrs.size();++i) for(auto i:num_addrs)
delete num_addrs[i]; delete i;
num_addrs.clear(); num_addrs.clear();
for(int i=0;i<str_addrs.size();++i) for(auto i:str_addrs)
delete str_addrs[i]; delete i;
str_addrs.clear(); str_addrs.clear();
return; return;
} }

View File

@ -120,24 +120,30 @@ void nasal_parse::main_process()
root.set_type(ast_root); root.set_type(ast_root);
while(tok_list[ptr].type!=tok_eof) while(tok_list[ptr].type!=tok_eof)
{ {
int err_tok_size=error_token.size();
root.add_child(expr()); root.add_child(expr());
if(tok_list[ptr].type==tok_semi) if(tok_list[ptr].type==tok_semi)
match(tok_semi); match(tok_semi);
// if detect error token, avoid checking semicolon
else if(error_token.size()>err_tok_size)
continue;
// the last expression can be recognized without semi
else if(need_semi_check(root.get_children().back()) && tok_list[ptr].type!=tok_eof) else if(need_semi_check(root.get_children().back()) && tok_list[ptr].type!=tok_eof)
{
// the last expression can be recognized without semi
die(error_line,"expected \";\""); die(error_line,"expected \";\"");
}
} }
if(!error_token.size()) if(!error_token.size())
return; return;
int sameline=error_token[0].line; std::vector<int> err_lines;
for(int i=0;i<error_token.size();++i) err_lines.push_back(error_token[0].line);
if(sameline!=error_token[i].line) for(auto tok:error_token)
{ if(err_lines.back()!=tok.line)
die(sameline,"error tokens in this line maybe recorded because of fatal syntax errors"); err_lines.push_back(tok.line);
sameline=error_token[i].line; ++error;
} std::cout<<">> [parse] error tokens in line";
for(auto line:err_lines)
std::cout<<' '<<line;
std::cout<<" maybe recorded because of fatal syntax errors."
<<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n";
return; return;
} }
nasal_ast& nasal_parse::get_root() nasal_ast& nasal_parse::get_root()
@ -189,15 +195,13 @@ void nasal_parse::match(int type,std::string err_info)
} }
bool nasal_parse::check_comma(int* panic_set) bool nasal_parse::check_comma(int* panic_set)
{ {
bool in_panic_set=false;
for(int i=0;panic_set[i];++i) for(int i=0;panic_set[i];++i)
if(tok_list[ptr].type==panic_set[i]) if(tok_list[ptr].type==panic_set[i])
{ {
in_panic_set=true;
die(error_line,"expected \',\' between scalars"); die(error_line,"expected \',\' between scalars");
break; return true;
} }
return in_panic_set; return false;
} }
bool nasal_parse::check_multi_def() bool nasal_parse::check_multi_def()
{ {
@ -519,14 +523,16 @@ nasal_ast nasal_parse::exprs_gen()
match(tok_lbrace); match(tok_lbrace);
while(tok_list[ptr].type!=tok_rbrace && tok_list[ptr].type!=tok_eof) while(tok_list[ptr].type!=tok_rbrace && tok_list[ptr].type!=tok_eof)
{ {
int err_tok_size=error_token.size();
node.add_child(expr()); node.add_child(expr());
if(tok_list[ptr].type==tok_semi) if(tok_list[ptr].type==tok_semi)
match(tok_semi); match(tok_semi);
// if detect error token, avoid checking semicolon
else if(error_token.size()>err_tok_size)
continue;
// the last expression can be recognized without semi
else if(need_semi_check(node.get_children().back()) && tok_list[ptr].type!=tok_rbrace) else if(need_semi_check(node.get_children().back()) && tok_list[ptr].type!=tok_rbrace)
{
// the last expression can be recognized without semi
die(error_line,"expected \";\""); die(error_line,"expected \";\"");
}
} }
match(tok_rbrace,"expected \'}\' when generating expressions"); match(tok_rbrace,"expected \'}\' when generating expressions");
} }

View File

@ -108,7 +108,6 @@ void nasal_vm::init(
void nasal_vm::clear() void nasal_vm::clear()
{ {
gc.gc_clear(); gc.gc_clear();
while(!addr_stack.empty()) while(!addr_stack.empty())
addr_stack.pop(); addr_stack.pop();
while(!ret.empty()) while(!ret.empty())