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:
parent
6adb991c04
commit
a463af53b7
|
@ -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.
|
26
README.md
26
README.md
|
@ -2,13 +2,17 @@
|
|||
|
||||
[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!
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
@ -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'
|
||||
nasal_val* vector_value=local_scope[1];
|
||||
// main process
|
||||
// also check number of arguments and type here,if get a type error,use builtin_err and return nullptr
|
||||
nasal_vec& ref_vec=vector_value->get_vector();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
nasal_val* tmp=ref_vec[i];
|
||||
switch(tmp->get_type())
|
||||
// also check number of arguments and type here
|
||||
// if get a type error,use builtin_err and return nullptr
|
||||
for(auto i:vec_addr->ptr.vec->elems)
|
||||
switch(i->type)
|
||||
{
|
||||
case vm_nil: std::cout<<"nil"; break;
|
||||
case vm_num: std::cout<<tmp->get_number(); break;
|
||||
case vm_str: std::cout<<tmp->get_string(); break;
|
||||
case vm_vec: tmp->get_vector().print(); break;
|
||||
case vm_hash: tmp->get_hash().print(); break;
|
||||
case vm_num: std::cout<<i->ptr.num; break;
|
||||
case vm_str: std::cout<<*i->ptr.str; break;
|
||||
case vm_vec: i->ptr.vec->print(); break;
|
||||
case vm_hash: i->ptr.hash->print(); break;
|
||||
case vm_func: std::cout<<"func(...){...}"; break;
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// or use reserved reference gc.nil_addr/gc.one_addr/gc.zero_addr
|
||||
|
|
2
main.cpp
2
main.cpp
|
@ -103,6 +103,8 @@ int main()
|
|||
logo();
|
||||
std::cout<<">> Nasal interpreter ver 6.0 .\n";
|
||||
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\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";
|
||||
while(1)
|
||||
|
|
|
@ -119,21 +119,16 @@ nasal_val* builtin_print(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
|
|||
// local_scope[0] is reserved for 'me'
|
||||
nasal_val* vec_addr=local_scope[1];
|
||||
// main process
|
||||
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems;
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
nasal_val* tmp=ref_vec[i];
|
||||
switch(tmp->type)
|
||||
for(auto i:vec_addr->ptr.vec->elems)
|
||||
switch(i->type)
|
||||
{
|
||||
case vm_nil: std::cout<<"nil"; break;
|
||||
case vm_num: std::cout<<tmp->ptr.num; break;
|
||||
case vm_str: std::cout<<*tmp->ptr.str; break;
|
||||
case vm_vec: tmp->ptr.vec->print(); break;
|
||||
case vm_hash: tmp->ptr.hash->print(); break;
|
||||
case vm_num: std::cout<<i->ptr.num; break;
|
||||
case vm_str: std::cout<<*i->ptr.str; break;
|
||||
case vm_vec: i->ptr.vec->print(); break;
|
||||
case vm_hash: i->ptr.hash->print(); break;
|
||||
case vm_func: std::cout<<"func(...){...}"; break;
|
||||
}
|
||||
}
|
||||
// generate return value
|
||||
return gc.nil_addr;
|
||||
}
|
||||
|
@ -147,10 +142,8 @@ nasal_val* builtin_append(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
|
|||
return nullptr;
|
||||
}
|
||||
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems;
|
||||
std::vector<nasal_val*>& ref_elems=elem_addr->ptr.vec->elems;
|
||||
int size=ref_elems.size();
|
||||
for(int i=0;i<size;++i)
|
||||
ref_vec.push_back(ref_elems[i]);
|
||||
for(auto i:elem_addr->ptr.vec->elems)
|
||||
ref_vec.push_back(i);
|
||||
return gc.nil_addr;
|
||||
}
|
||||
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");
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems;
|
||||
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);
|
||||
vec_addr->ptr.vec->elems.resize(num,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;
|
||||
int delimeter_len=delimeter.length();
|
||||
int source_len=source.length();
|
||||
|
||||
nasal_val* ret_addr=gc.gc_alloc(vm_vec);
|
||||
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
|
||||
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);
|
||||
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=ref_hash.begin();iter!=ref_hash.end();++iter)
|
||||
for(auto iter:hash_addr->ptr.hash->elems)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
nasal_val* builtin_die(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
|
||||
|
|
143
nasal_codegen.h
143
nasal_codegen.h
|
@ -3,44 +3,44 @@
|
|||
|
||||
enum op_code
|
||||
{
|
||||
op_nop,
|
||||
op_intg,
|
||||
op_intl,
|
||||
op_loadg,
|
||||
op_loadl,
|
||||
op_pnum,
|
||||
op_pone,
|
||||
op_pzero,
|
||||
op_pnil,
|
||||
op_pstr,
|
||||
op_newv,
|
||||
op_newh,
|
||||
op_newf,
|
||||
op_vapp,
|
||||
op_happ,
|
||||
op_para,
|
||||
op_defpara,
|
||||
op_dynpara,
|
||||
op_unot,
|
||||
op_usub,
|
||||
op_add,
|
||||
op_sub,
|
||||
op_mul,
|
||||
op_div,
|
||||
op_lnk,
|
||||
op_addeq,
|
||||
op_subeq,
|
||||
op_muleq,
|
||||
op_diveq,
|
||||
op_lnkeq,
|
||||
op_meq,
|
||||
op_eq,
|
||||
op_neq,
|
||||
op_less,
|
||||
op_leq,
|
||||
op_grt,
|
||||
op_geq,
|
||||
op_pop,
|
||||
op_nop, // do nothing and end the vm main loop
|
||||
op_intg, // global scope size
|
||||
op_intl, // local scope size
|
||||
op_loadg, // load global symbol value
|
||||
op_loadl, // load local symbol value
|
||||
op_pnum, // push constant number to the stack
|
||||
op_pone, // push 1 to the stack
|
||||
op_pzero, // push 0 to the stack
|
||||
op_pnil, // push constant nil to the stack
|
||||
op_pstr, // push constant string to the stack
|
||||
op_newv, // push new vector to the stack
|
||||
op_newh, // push new hash to the stack
|
||||
op_newf, // push new function to the stack
|
||||
op_vapp, // vector append
|
||||
op_happ, // hash append
|
||||
op_para, // normal parameter
|
||||
op_defpara, // default parameter
|
||||
op_dynpara, // dynamic parameter
|
||||
op_unot, // !
|
||||
op_usub, // -
|
||||
op_add, // +
|
||||
op_sub, // -
|
||||
op_mul, // *
|
||||
op_div, // /
|
||||
op_lnk, // ~
|
||||
op_addeq, // +=
|
||||
op_subeq, // -=
|
||||
op_muleq, // *=
|
||||
op_diveq, // /=
|
||||
op_lnkeq, // ~=
|
||||
op_meq, // =
|
||||
op_eq, // ==
|
||||
op_neq, // !=
|
||||
op_less, // <
|
||||
op_leq, // <=
|
||||
op_grt, // >
|
||||
op_geq, // >=
|
||||
op_pop, // pop a value from stack
|
||||
op_jmp, // jump with no condition
|
||||
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
|
||||
|
@ -256,15 +256,15 @@ void nasal_codegen::add_sym(std::string name)
|
|||
{
|
||||
if(local.empty())
|
||||
{
|
||||
for(int i=0;i<global.size();++i)
|
||||
if(global[i]==name)
|
||||
for(auto sym:global)
|
||||
if(sym==name)
|
||||
return;
|
||||
global.push_back(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0;i<local.back().size();++i)
|
||||
if(local.back()[i]==name)
|
||||
for(auto sym:local.back())
|
||||
if(sym==name)
|
||||
return;
|
||||
local.back().push_back(name);
|
||||
}
|
||||
|
@ -275,12 +275,12 @@ int nasal_codegen::local_find(std::string& name)
|
|||
{
|
||||
int index=-1;
|
||||
int cnt=0;
|
||||
for(auto i=local.begin();i!=local.end();++i)
|
||||
for(auto i:local)
|
||||
{
|
||||
for(int j=0;j<i->size();++j)
|
||||
if((*i)[j]==name)
|
||||
for(int j=0;j<i.size();++j)
|
||||
if(i[j]==name)
|
||||
index=cnt+j;
|
||||
cnt+=i->size();
|
||||
cnt+=i.size();
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
@ -337,22 +337,20 @@ void nasal_codegen::str_gen(nasal_ast& ast)
|
|||
|
||||
void nasal_codegen::vec_gen(nasal_ast& ast)
|
||||
{
|
||||
int size=ast.get_children().size();
|
||||
gen(op_newv,0);
|
||||
for(int i=0;i<size;++i)
|
||||
calc_gen(ast.get_children()[i]);
|
||||
gen(op_vapp,size);
|
||||
for(auto node:ast.get_children())
|
||||
calc_gen(node);
|
||||
gen(op_vapp,ast.get_children().size());
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::hash_gen(nasal_ast& ast)
|
||||
{
|
||||
int size=ast.get_children().size();
|
||||
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]);
|
||||
std::string str=ast.get_children()[i].get_children()[0].get_str();
|
||||
calc_gen(node.get_children()[1]);
|
||||
std::string str=node.get_children()[0].get_str();
|
||||
regist_string(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
|
||||
if(local.size()==1)
|
||||
add_sym("me");
|
||||
|
||||
nasal_ast& ref_arg=ast.get_children()[0];
|
||||
int arg_size=ref_arg.get_children().size();
|
||||
for(int i=0;i<arg_size;++i)
|
||||
// generate parameter list
|
||||
for(auto tmp:ast.get_children()[0].get_children())
|
||||
{
|
||||
nasal_ast& tmp=ref_arg.get_children()[i];
|
||||
if(tmp.get_type()==ast_id)
|
||||
{
|
||||
std::string str=tmp.get_str();
|
||||
|
@ -463,7 +458,7 @@ void nasal_codegen::call_id(nasal_ast& ast)
|
|||
gen(op_callg,index);
|
||||
return;
|
||||
}
|
||||
die("cannot find symbol named \""+str+"\".",ast.get_line());
|
||||
die("undefined symbol \""+str+"\".",ast.get_line());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -484,10 +479,8 @@ void nasal_codegen::call_vec(nasal_ast& ast)
|
|||
return;
|
||||
}
|
||||
gen(op_slcbegin,0);
|
||||
int size=ast.get_children().size();
|
||||
for(int i=0;i<size;++i)
|
||||
for(auto tmp:ast.get_children())
|
||||
{
|
||||
nasal_ast& tmp=ast.get_children()[i];
|
||||
if(tmp.get_type()!=ast_subvec)
|
||||
{
|
||||
calc_gen(tmp);
|
||||
|
@ -549,7 +542,7 @@ void nasal_codegen::mcall_id(nasal_ast& ast)
|
|||
gen(op_mcallg,index);
|
||||
return;
|
||||
}
|
||||
die("cannot find symbol named \""+str+"\".",ast.get_line());
|
||||
die("undefined symbol \""+str+"\".",ast.get_line());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -955,10 +948,7 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
|
|||
|
||||
void nasal_codegen::block_gen(nasal_ast& ast)
|
||||
{
|
||||
int size=ast.get_children().size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
nasal_ast& tmp=ast.get_children()[i];
|
||||
for(auto tmp:ast.get_children())
|
||||
switch(tmp.get_type())
|
||||
{
|
||||
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_return:ret_gen(tmp);break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1085,10 +1074,10 @@ void nasal_codegen::main_progress(nasal_ast& ast)
|
|||
exec_code[0].num=global.size();
|
||||
num_res_table.resize(number_table.size());
|
||||
str_res_table.resize(string_table.size());
|
||||
for(auto i=number_table.begin();i!=number_table.end();++i)
|
||||
num_res_table[i->second]=i->first;
|
||||
for(auto i=string_table.begin();i!=string_table.end();++i)
|
||||
str_res_table[i->second]=i->first;
|
||||
for(auto i:number_table)
|
||||
num_res_table[i.second]=i.first;
|
||||
for(auto i:string_table)
|
||||
str_res_table[i.second]=i.first;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1124,10 +1113,10 @@ void nasal_codegen::print_op(int index)
|
|||
|
||||
void nasal_codegen::print_byte_code()
|
||||
{
|
||||
for(int i=0;i<num_res_table.size();++i)
|
||||
std::cout<<".number "<<num_res_table[i]<<'\n';
|
||||
for(int i=0;i<str_res_table.size();++i)
|
||||
std::cout<<".symbol "<<str_res_table[i]<<'\n';
|
||||
for(auto num:num_res_table)
|
||||
std::cout<<".number "<<num<<'\n';
|
||||
for(auto str:str_res_table)
|
||||
std::cout<<".symbol "<<str<<'\n';
|
||||
int size=exec_code.size();
|
||||
for(int i=0;i<size;++i)
|
||||
print_op(i);
|
||||
|
|
126
nasal_gc.h
126
nasal_gc.h
|
@ -96,23 +96,21 @@ nasal_val** nasal_vec::get_mem(int index)
|
|||
void nasal_vec::print()
|
||||
{
|
||||
int size=elems.size();
|
||||
std::cout<<"[";
|
||||
if(!size)
|
||||
std::cout<<"]";
|
||||
for(int i=0;i<size;++i)
|
||||
std::cout<<'[';
|
||||
for(auto i:elems)
|
||||
{
|
||||
nasal_val* tmp=elems[i];
|
||||
switch(tmp->type)
|
||||
switch(i->type)
|
||||
{
|
||||
case vm_nil: std::cout<<"nil"; break;
|
||||
case vm_num: std::cout<<tmp->ptr.num; break;
|
||||
case vm_str: std::cout<<*tmp->ptr.str; break;
|
||||
case vm_vec: tmp->ptr.vec->print(); break;
|
||||
case vm_hash: tmp->ptr.hash->print(); break;
|
||||
case vm_num: std::cout<<i->ptr.num; break;
|
||||
case vm_str: std::cout<<*i->ptr.str; break;
|
||||
case vm_vec: i->ptr.vec->print(); break;
|
||||
case vm_hash: i->ptr.hash->print(); break;
|
||||
case vm_func: std::cout<<"func(...){...}"; break;
|
||||
}
|
||||
std::cout<<",]"[i==size-1];
|
||||
std::cout<<',';
|
||||
}
|
||||
std::cout<<']';
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -126,19 +124,14 @@ nasal_val* nasal_hash::get_val(std::string& key)
|
|||
{
|
||||
nasal_val* val_addr=elems["parents"];
|
||||
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(tmp->type==vm_hash)
|
||||
ret_addr=tmp->ptr.hash->get_val(key);
|
||||
if(i->type==vm_hash)
|
||||
ret_addr=i->ptr.hash->get_val(key);
|
||||
if(ret_addr)
|
||||
return ret_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
nasal_val** nasal_hash::get_mem(std::string& key)
|
||||
|
@ -150,19 +143,14 @@ nasal_val** nasal_hash::get_mem(std::string& key)
|
|||
{
|
||||
nasal_val* val_addr=elems["parents"];
|
||||
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(tmp->type==vm_hash)
|
||||
mem_addr=tmp->ptr.hash->get_mem(key);
|
||||
if(i->type==vm_hash)
|
||||
mem_addr=i->ptr.hash->get_mem(key);
|
||||
if(mem_addr)
|
||||
return mem_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
bool nasal_hash::check_contain(std::string& key)
|
||||
|
@ -175,13 +163,10 @@ bool nasal_hash::check_contain(std::string& key)
|
|||
if(val_addr->type==vm_vec)
|
||||
{
|
||||
bool result=false;
|
||||
std::vector<nasal_val*>& vec_ref=val_addr->ptr.vec->elems;
|
||||
int size=vec_ref.size();
|
||||
for(int i=0;i<size;++i)
|
||||
for(auto i:val_addr->ptr.vec->elems)
|
||||
{
|
||||
nasal_val* tmp=vec_ref[i];
|
||||
if(tmp->type==vm_hash)
|
||||
result=tmp->ptr.hash->check_contain(key);
|
||||
if(i->type==vm_hash)
|
||||
result=i->ptr.hash->check_contain(key);
|
||||
if(result)
|
||||
return true;
|
||||
}
|
||||
|
@ -192,15 +177,10 @@ bool nasal_hash::check_contain(std::string& key)
|
|||
void nasal_hash::print()
|
||||
{
|
||||
std::cout<<'{';
|
||||
if(!elems.size())
|
||||
for(auto i:elems)
|
||||
{
|
||||
std::cout<<'}';
|
||||
return;
|
||||
}
|
||||
for(auto i=elems.begin();i!=elems.end();++i)
|
||||
{
|
||||
std::cout<<i->first<<':';
|
||||
nasal_val* tmp=i->second;
|
||||
std::cout<<i.first<<':';
|
||||
nasal_val* tmp=i.second;
|
||||
switch(tmp->type)
|
||||
{
|
||||
case vm_nil: std::cout<<"nil"; break;
|
||||
|
@ -322,13 +302,13 @@ struct nasal_gc
|
|||
void nasal_gc::mark()
|
||||
{
|
||||
std::queue<nasal_val*> bfs;
|
||||
for(auto i=global.begin();i!=global.end();++i)
|
||||
bfs.push(*i);
|
||||
for(auto i=local.begin();i!=local.end();++i)
|
||||
for(auto j=i->begin();j!=i->end();++j)
|
||||
bfs.push(*j);
|
||||
for(auto i=slice_stack.begin();i!=slice_stack.end();++i)
|
||||
bfs.push(*i);
|
||||
for(auto i:global)
|
||||
bfs.push(i);
|
||||
for(auto i:local)
|
||||
for(auto j:i)
|
||||
bfs.push(j);
|
||||
for(auto i:slice_stack)
|
||||
bfs.push(i);
|
||||
for(nasal_val** i=val_stack;i<=stack_top;++i)
|
||||
bfs.push(*i);
|
||||
while(!bfs.empty())
|
||||
|
@ -338,40 +318,31 @@ void nasal_gc::mark()
|
|||
if(!tmp || tmp->mark) continue;
|
||||
tmp->mark=true;
|
||||
if(tmp->type==vm_vec)
|
||||
{
|
||||
std::vector<nasal_val*>& vec=tmp->ptr.vec->elems;
|
||||
for(auto i=vec.begin();i!=vec.end();++i)
|
||||
bfs.push(*i);
|
||||
}
|
||||
for(auto i:tmp->ptr.vec->elems)
|
||||
bfs.push(i);
|
||||
else if(tmp->type==vm_hash)
|
||||
{
|
||||
std::unordered_map<std::string,nasal_val*>& hash=tmp->ptr.hash->elems;
|
||||
for(auto i=hash.begin();i!=hash.end();++i)
|
||||
bfs.push(i->second);
|
||||
}
|
||||
for(auto i:tmp->ptr.hash->elems)
|
||||
bfs.push(i.second);
|
||||
else if(tmp->type==vm_func)
|
||||
{
|
||||
std::vector<nasal_val*>& cls=tmp->ptr.func->closure;
|
||||
std::vector<nasal_val*>& def=tmp->ptr.func->default_para;
|
||||
for(auto i=cls.begin();i!=cls.end();++i)
|
||||
bfs.push(*i);
|
||||
for(auto i=def.begin();i!=def.end();++i)
|
||||
bfs.push(*i);
|
||||
for(auto i:tmp->ptr.func->closure)
|
||||
bfs.push(i);
|
||||
for(auto i:tmp->ptr.func->default_para)
|
||||
bfs.push(i);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
void nasal_gc::sweep()
|
||||
{
|
||||
int size=memory.size();
|
||||
for(int i=0;i<size;++i)
|
||||
for(auto i:memory)
|
||||
{
|
||||
if(!memory[i]->mark)
|
||||
if(!i->mark)
|
||||
{
|
||||
memory[i]->clear();
|
||||
free_list.push(memory[i]);
|
||||
i->clear();
|
||||
free_list.push(i);
|
||||
}
|
||||
memory[i]->mark=false;
|
||||
i->mark=false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -414,11 +385,8 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
|
|||
}
|
||||
void nasal_gc::gc_clear()
|
||||
{
|
||||
for(int i=0;i<memory.size();++i)
|
||||
{
|
||||
memory[i]->clear();
|
||||
delete memory[i];
|
||||
}
|
||||
for(auto i:memory)
|
||||
delete i;
|
||||
memory.clear();
|
||||
while(!free_list.empty())
|
||||
free_list.pop();
|
||||
|
@ -429,11 +397,11 @@ void nasal_gc::gc_clear()
|
|||
delete nil_addr;
|
||||
delete one_addr;
|
||||
delete zero_addr;
|
||||
for(int i=0;i<num_addrs.size();++i)
|
||||
delete num_addrs[i];
|
||||
for(auto i:num_addrs)
|
||||
delete i;
|
||||
num_addrs.clear();
|
||||
for(int i=0;i<str_addrs.size();++i)
|
||||
delete str_addrs[i];
|
||||
for(auto i:str_addrs)
|
||||
delete i;
|
||||
str_addrs.clear();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -120,24 +120,30 @@ void nasal_parse::main_process()
|
|||
root.set_type(ast_root);
|
||||
while(tok_list[ptr].type!=tok_eof)
|
||||
{
|
||||
int err_tok_size=error_token.size();
|
||||
root.add_child(expr());
|
||||
if(tok_list[ptr].type==tok_semi)
|
||||
match(tok_semi);
|
||||
else if(need_semi_check(root.get_children().back()) && tok_list[ptr].type!=tok_eof)
|
||||
{
|
||||
// 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)
|
||||
die(error_line,"expected \";\"");
|
||||
}
|
||||
}
|
||||
if(!error_token.size())
|
||||
return;
|
||||
int sameline=error_token[0].line;
|
||||
for(int i=0;i<error_token.size();++i)
|
||||
if(sameline!=error_token[i].line)
|
||||
{
|
||||
die(sameline,"error tokens in this line maybe recorded because of fatal syntax errors");
|
||||
sameline=error_token[i].line;
|
||||
}
|
||||
std::vector<int> err_lines;
|
||||
err_lines.push_back(error_token[0].line);
|
||||
for(auto tok:error_token)
|
||||
if(err_lines.back()!=tok.line)
|
||||
err_lines.push_back(tok.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;
|
||||
}
|
||||
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 in_panic_set=false;
|
||||
for(int i=0;panic_set[i];++i)
|
||||
if(tok_list[ptr].type==panic_set[i])
|
||||
{
|
||||
in_panic_set=true;
|
||||
die(error_line,"expected \',\' between scalars");
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
return in_panic_set;
|
||||
return false;
|
||||
}
|
||||
bool nasal_parse::check_multi_def()
|
||||
{
|
||||
|
@ -519,15 +523,17 @@ nasal_ast nasal_parse::exprs_gen()
|
|||
match(tok_lbrace);
|
||||
while(tok_list[ptr].type!=tok_rbrace && tok_list[ptr].type!=tok_eof)
|
||||
{
|
||||
int err_tok_size=error_token.size();
|
||||
node.add_child(expr());
|
||||
if(tok_list[ptr].type==tok_semi)
|
||||
match(tok_semi);
|
||||
else if(need_semi_check(node.get_children().back()) && tok_list[ptr].type!=tok_rbrace)
|
||||
{
|
||||
// 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)
|
||||
die(error_line,"expected \";\"");
|
||||
}
|
||||
}
|
||||
match(tok_rbrace,"expected \'}\' when generating expressions");
|
||||
}
|
||||
else
|
||||
|
|
|
@ -108,7 +108,6 @@ void nasal_vm::init(
|
|||
void nasal_vm::clear()
|
||||
{
|
||||
gc.gc_clear();
|
||||
|
||||
while(!addr_stack.empty())
|
||||
addr_stack.pop();
|
||||
while(!ret.empty())
|
||||
|
|
Loading…
Reference in New Issue