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.
|
30
README.md
30
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/).
|
[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
|
||||||
|
|
6
main.cpp
6
main.cpp
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
143
nasal_codegen.h
143
nasal_codegen.h
|
@ -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);
|
||||||
|
|
126
nasal_gc.h
126
nasal_gc.h
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
Loading…
Reference in New Issue