bug fixed

a gc bug which causes  fatal error.
add member value collect to make sure that nasal_val is not collected repeatedly.
use builtin_alloc in builtin function to avoid incorrect collection of value in use(gc_alloc).
change free_list to free_list[vm_type_size] to avoid too many calls of new/delete(but seems useless?)
but the most important thing is fixing this bug.
This commit is contained in:
Valk Richard Li 2021-05-31 19:10:59 +08:00
parent aae9395d66
commit a68bf85f04
11 changed files with 234 additions and 195 deletions

View File

@ -139,6 +139,14 @@ In this update i changed global and local scope from unordered_map to vector.
So the bytecode generator changed a lot.
## Version 6.5
2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error.
Add builtin_alloc to avoid mark-sweep when running a built-in function,which will mark useful items as useless garbage to collect.
Better use setsize and assignment to get a big array,append is very slow in this situation.
```javascript
for(var i=0;i<4000000;i+=1);
```
@ -429,3 +437,34 @@ var print=func(elements...)
In version 5.0,if you don't warp built-in function in a normal nasal function,this built-in function may cause a fault when searching arguments,which will cause SIGSEGV segmentation error(maybe).
Use import("") to get the nasal file including your built-in functions,then you could use it.
version 6.5 update:
Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more then one time.
When running a builtin function,alloc will run more than one time,this may cause mark-sweep in gc_alloc.
The value got before will be collected,but stil in use in this builtin function,this is a fatal error.
So use builtin_alloc in builtin functions like this:
```C++
nasal_val* builtin_getkeys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
{
nasal_val* hash_addr=local_scope[1];
if(hash_addr->type!=vm_hash)
{
builtin_err("keys","\"hash\" must be hash");
return nullptr;
}
nasal_val* ret_addr=gc.builtin_alloc(vm_vec);
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
for(auto iter:hash_addr->ptr.hash->elems)
{
nasal_val* str_addr=gc.builtin_alloc(vm_str);
*str_addr->ptr.str=iter.first;
ref_vec.push_back(str_addr);
}
return ret_addr;
}
```

View File

@ -99,12 +99,14 @@ int main()
// use chcp 65001 to use unicode io
system("chcp 65001");
system("cls");
#else
system("clear");
#endif
logo();
std::cout<<">> Nasal interpreter ver 6.0 .\n";
std::cout<<">> Nasal interpreter ver 6.5 efficient gc test .\n";
std::cout<<">> Thanks to https://github.com/andyross/nasal\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)

View File

@ -3,6 +3,7 @@
#pragma GCC optimize(2)
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
@ -94,7 +95,7 @@ inline double dec_to_double(std::string& str,int len)
}
return ret*std::pow(10,negative*num_pow);
}
double trans_string_to_number(std::string str)
double str2num(std::string str)
{
bool is_negative=false;
int len=str.length();
@ -118,7 +119,7 @@ double trans_string_to_number(std::string str)
trans_number_to_string:
convert number to string
*/
std::string trans_number_to_string(double number)
std::string num2str(double number)
{
std::string res;
std::stringstream ss;

View File

@ -113,7 +113,7 @@ public:
int get_line();
int get_type();
double get_num();
std::string get_str();
std::string& get_str();
std::vector<nasal_ast>& get_children();
};
@ -207,7 +207,7 @@ int nasal_ast::get_type()
return type;
}
std::string nasal_ast::get_str()
std::string& nasal_ast::get_str()
{
return str;
}
@ -233,9 +233,8 @@ void nasal_ast::print_ast(int depth)
else if(type==ast_num)
std::cout<<":"<<num;
std::cout<<'\n';
int child_size=children.size();
for(int i=0;i<child_size;++i)
children[i].print_ast(depth+1);
for(auto& i:children)
i.print_ast(depth+1);
return;
}

View File

@ -271,7 +271,7 @@ 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);
nasal_val* ret_addr=gc.builtin_alloc(vm_vec);
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
std::string tmp="";
@ -279,7 +279,7 @@ nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
{
for(int i=0;i<source_len;++i)
{
nasal_val* str_addr=gc.gc_alloc(vm_str);
nasal_val* str_addr=gc.builtin_alloc(vm_str);
*str_addr->ptr.str=source[i];
ref_vec.push_back(str_addr);
}
@ -301,7 +301,7 @@ nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
{
if(tmp.length())
{
nasal_val* str_addr=gc.gc_alloc(vm_str);
nasal_val* str_addr=gc.builtin_alloc(vm_str);
*str_addr->ptr.str=tmp;
ref_vec.push_back(str_addr);
tmp="";
@ -313,7 +313,7 @@ nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
if(tmp.length())
{
nasal_val* str_addr=gc.gc_alloc(vm_str);
nasal_val* str_addr=gc.builtin_alloc(vm_str);
*str_addr->ptr.str=tmp;
ref_vec.push_back(str_addr);
tmp="";
@ -585,7 +585,7 @@ nasal_val* builtin_sqrt(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_val* builtin_atan2(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
{
nasal_val* x_val_addr=local_scope[1];
nasal_val* y_val_addr=local_scope[1];
nasal_val* y_val_addr=local_scope[2];
if(x_val_addr->type!=vm_num)
{
builtin_err("atan2","\"x\" must be number");
@ -628,7 +628,7 @@ nasal_val* builtin_contains(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=hash_addr->ptr.hash->check_contain(*key_addr->ptr.str);
ret_addr->ptr.num=hash_addr->ptr.hash->elems.count(*key_addr->ptr.str);
return ret_addr;
}
nasal_val* builtin_delete(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
@ -657,11 +657,11 @@ nasal_val* builtin_getkeys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
builtin_err("keys","\"hash\" must be hash");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_vec);
nasal_val* ret_addr=gc.builtin_alloc(vm_vec);
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
for(auto iter:hash_addr->ptr.hash->elems)
{
nasal_val* str_addr=gc.gc_alloc(vm_str);
nasal_val* str_addr=gc.builtin_alloc(vm_str);
*str_addr->ptr.str=iter.first;
ref_vec.push_back(str_addr);
}

View File

@ -140,9 +140,9 @@ struct
struct opcode
{
unsigned char op;
unsigned int num;
opcode(unsigned char _op=op_nop,unsigned int _num=0)
uint8_t op;
uint32_t num;
opcode(uint8_t _op=op_nop,uint32_t _num=0)
{
op=_op;
num=_num;
@ -175,7 +175,7 @@ private:
void die(std::string,int);
void regist_number(double);
void regist_string(std::string&);
void add_sym(std::string);
void add_sym(std::string&);
int local_find(std::string&);
int global_find(std::string&);
void gen(unsigned char,unsigned int);
@ -254,18 +254,18 @@ void nasal_codegen::regist_string(std::string& str)
return;
}
void nasal_codegen::add_sym(std::string name)
void nasal_codegen::add_sym(std::string& name)
{
if(local.empty())
{
for(auto sym:global)
for(auto& sym:global)
if(sym==name)
return;
global.push_back(name);
}
else
{
for(auto sym:local.back())
for(auto& sym:local.back())
if(sym==name)
return;
local.back().push_back(name);
@ -277,7 +277,7 @@ int nasal_codegen::local_find(std::string& name)
{
int index=-1;
int cnt=0;
for(auto i:local)
for(auto& i:local)
{
for(int j=0;j<i.size();++j)
if(i[j]==name)
@ -331,7 +331,7 @@ void nasal_codegen::num_gen(nasal_ast& ast)
void nasal_codegen::str_gen(nasal_ast& ast)
{
std::string str=ast.get_str();
std::string& str=ast.get_str();
regist_string(str);
gen(op_pstr,string_table[str]);
return;
@ -340,7 +340,7 @@ void nasal_codegen::str_gen(nasal_ast& ast)
void nasal_codegen::vec_gen(nasal_ast& ast)
{
gen(op_newv,0);
for(auto node:ast.get_children())
for(auto& node:ast.get_children())
calc_gen(node);
gen(op_vapp,ast.get_children().size());
return;
@ -349,10 +349,10 @@ void nasal_codegen::vec_gen(nasal_ast& ast)
void nasal_codegen::hash_gen(nasal_ast& ast)
{
gen(op_newh,0);
for(auto node:ast.get_children())
for(auto& node:ast.get_children())
{
calc_gen(node.get_children()[1]);
std::string str=node.get_children()[0].get_str();
std::string& str=node.get_children()[0].get_str();
regist_string(str);
gen(op_happ,string_table[str]);
}
@ -374,17 +374,20 @@ void nasal_codegen::func_gen(nasal_ast& ast)
// after calling a hash, this keyword is set to this hash
// this symbol's index will be 0
if(local.size()==1)
add_sym("me");
{
std::string me="me";
add_sym(me);
}
gen(op_offset,0);
for(auto i:local)
for(auto& i:local)
exec_code.back().num+=i.size();
// generate parameter list
for(auto tmp:ast.get_children()[0].get_children())
for(auto& tmp:ast.get_children()[0].get_children())
{
if(tmp.get_type()==ast_id)
{
std::string str=tmp.get_str();
std::string& str=tmp.get_str();
regist_string(str);
add_sym(str);
gen(op_para,string_table[str]);
@ -392,14 +395,14 @@ void nasal_codegen::func_gen(nasal_ast& ast)
else if(tmp.get_type()==ast_default_arg)
{
calc_gen(tmp.get_children()[1]);
std::string str=tmp.get_children()[0].get_str();
std::string& str=tmp.get_children()[0].get_str();
regist_string(str);
add_sym(str);
gen(op_defpara,string_table[str]);
}
else if(tmp.get_type()==ast_dynamic_id)
{
std::string str=tmp.get_str();
std::string& str=tmp.get_str();
regist_string(str);
add_sym(str);
gen(op_dynpara,string_table[str]);
@ -411,8 +414,8 @@ void nasal_codegen::func_gen(nasal_ast& ast)
nasal_ast& block=ast.get_children()[1];
block_gen(block);
for(auto i=local.begin();i!=local.end();++i)
exec_code[local_label].num+=i->size();
for(auto& i:local)
exec_code[local_label].num+=i.size();
local.pop_back();
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return)
@ -445,7 +448,7 @@ void nasal_codegen::call_gen(nasal_ast& ast)
void nasal_codegen::call_id(nasal_ast& ast)
{
std::string str=ast.get_str();
std::string& str=ast.get_str();
for(int i=0;builtin_func[i].func;++i)
if(builtin_func[i].name==str)
{
@ -470,7 +473,7 @@ void nasal_codegen::call_id(nasal_ast& ast)
void nasal_codegen::call_hash(nasal_ast& ast)
{
std::string str=ast.get_str();
std::string& str=ast.get_str();
regist_string(str);
gen(op_callh,string_table[str]);
return;
@ -485,7 +488,7 @@ void nasal_codegen::call_vec(nasal_ast& ast)
return;
}
gen(op_slcbegin,0);
for(auto tmp:ast.get_children())
for(auto& tmp:ast.get_children())
{
if(tmp.get_type()!=ast_subvec)
{
@ -535,7 +538,7 @@ void nasal_codegen::mcall(nasal_ast& ast)
void nasal_codegen::mcall_id(nasal_ast& ast)
{
std::string str=ast.get_str();
std::string& str=ast.get_str();
int index=local_find(str);
if(index>=0)
{
@ -561,7 +564,7 @@ void nasal_codegen::mcall_vec(nasal_ast& ast)
void nasal_codegen::mcall_hash(nasal_ast& ast)
{
std::string str=ast.get_str();
std::string& str=ast.get_str();
regist_string(str);
gen(op_mcallh,string_table[str]);
return;
@ -569,7 +572,7 @@ void nasal_codegen::mcall_hash(nasal_ast& ast)
void nasal_codegen::single_def(nasal_ast& ast)
{
std::string str=ast.get_children()[0].get_str();
std::string& str=ast.get_children()[0].get_str();
add_sym(str);
calc_gen(ast.get_children()[1]);
if(local.empty())
@ -585,7 +588,7 @@ void nasal_codegen::multi_def(nasal_ast& ast)
{
for(int i=0;i<size;++i)
{
std::string str=ast.get_children()[0].get_children()[i].get_str();
std::string& str=ast.get_children()[0].get_children()[i].get_str();
add_sym(str);
calc_gen(ast.get_children()[1].get_children()[i]);
if(local.empty())
@ -600,7 +603,7 @@ void nasal_codegen::multi_def(nasal_ast& ast)
for(int i=0;i<size;++i)
{
gen(op_callvi,i);
std::string str=ast.get_children()[0].get_children()[i].get_str();
std::string& str=ast.get_children()[0].get_children()[i].get_str();
add_sym(str);
if(local.empty())
gen(op_loadg,global_find(str));
@ -794,7 +797,7 @@ void nasal_codegen::forindex_gen(nasal_ast& ast)
gen(op_findex,0);
if(ast.get_children()[0].get_type()==ast_new_iter)
{
std::string str=ast.get_children()[0].get_children()[0].get_str();
std::string& str=ast.get_children()[0].get_children()[0].get_str();
add_sym(str);
if(local.empty())
gen(op_loadg,global_find(str));
@ -824,7 +827,7 @@ void nasal_codegen::foreach_gen(nasal_ast& ast)
gen(op_feach,0);
if(ast.get_children()[0].get_type()==ast_new_iter)
{
std::string str=ast.get_children()[0].get_children()[0].get_str();
std::string& str=ast.get_children()[0].get_children()[0].get_str();
add_sym(str);
if(local.empty())
gen(op_loadg,global_find(str));
@ -954,7 +957,7 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
void nasal_codegen::block_gen(nasal_ast& ast)
{
for(auto tmp:ast.get_children())
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;
@ -1080,9 +1083,9 @@ 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)
for(auto& i:number_table)
num_res_table[i.second]=i.first;
for(auto i:string_table)
for(auto& i:string_table)
str_res_table[i.second]=i.first;
return;
}
@ -1119,9 +1122,9 @@ void nasal_codegen::print_op(int index)
void nasal_codegen::print_byte_code()
{
for(auto num:num_res_table)
for(auto& num:num_res_table)
std::cout<<".number "<<num<<'\n';
for(auto str:str_res_table)
for(auto& str:str_res_table)
std::cout<<".symbol "<<str<<'\n';
int size=exec_code.size();
for(int i=0;i<size;++i)

View File

@ -8,7 +8,18 @@ enum nasal_type
vm_str,
vm_func,
vm_vec,
vm_hash
vm_hash,
vm_type_size
};
const int increment[vm_type_size]=
{
8, // vm_nil,in fact it is not in use
65536,// vm_num
512, // vm_str
16, // vm_func
128, // vm_vec
16 // vm_hash
};
struct nasal_vec;
@ -30,7 +41,6 @@ struct nasal_hash
{
std::unordered_map<std::string,nasal_val*> elems;
bool check_contain(std::string&);
void print();
nasal_val* get_val(std::string&);
nasal_val** get_mem(std::string&);
@ -38,20 +48,22 @@ struct nasal_hash
struct nasal_func
{
int dynpara;// dynamic parameter name index in hash
int offset;
int entry;
int32_t dynpara;// dynamic parameter name index in hash
uint32_t offset;
uint32_t entry;
std::vector<nasal_val*> default_para;
std::unordered_map<std::string,int> key_table;// parameter name hash
std::vector<nasal_val*> closure;
nasal_func();
void clear();
};
struct nasal_val
{
bool collected;
bool mark;
int type;
uint16_t type;
union
{
double num;
@ -64,8 +76,6 @@ struct nasal_val
nasal_val();
nasal_val(int);
~nasal_val();
void clear();
void set_type(int);
double to_number();
std::string to_string();
};
@ -95,7 +105,6 @@ nasal_val** nasal_vec::get_mem(int index)
}
void nasal_vec::print()
{
int size=elems.size();
std::cout<<'[';
for(auto i:elems)
{
@ -153,31 +162,10 @@ nasal_val** nasal_hash::get_mem(std::string& key)
}
return nullptr;
}
bool nasal_hash::check_contain(std::string& key)
{
if(elems.count(key))
return true;
if(elems.count("parents"))
{
nasal_val* val_addr=elems["parents"];
if(val_addr->type==vm_vec)
{
bool result=false;
for(auto i:val_addr->ptr.vec->elems)
{
if(i->type==vm_hash)
result=i->ptr.hash->check_contain(key);
if(result)
return true;
}
}
}
return false;
}
void nasal_hash::print()
{
std::cout<<'{';
for(auto i:elems)
for(auto& i:elems)
{
std::cout<<i.first<<':';
nasal_val* tmp=i.second;
@ -202,16 +190,26 @@ nasal_func::nasal_func()
dynpara=-1;
return;
}
void nasal_func::clear()
{
dynpara=-1;
default_para.clear();
key_table.clear();
closure.clear();
return;
}
/*functions of nasal_val*/
nasal_val::nasal_val()
{
collected=true;
mark=false;
type=vm_nil;
return;
}
nasal_val::nasal_val(int val_type)
{
collected=true;
mark=false;
type=val_type;
switch(type)
@ -236,35 +234,10 @@ nasal_val::~nasal_val()
type=vm_nil;
return;
}
void nasal_val::clear()
{
switch(type)
{
case vm_str: delete ptr.str; break;
case vm_vec: delete ptr.vec; break;
case vm_hash: delete ptr.hash; break;
case vm_func: delete ptr.func; break;
}
type=vm_nil;
return;
}
void nasal_val::set_type(int val_type)
{
type=val_type;
switch(type)
{
case vm_num: ptr.num=0; break;
case vm_str: ptr.str=new std::string; break;
case vm_vec: ptr.vec=new nasal_vec; break;
case vm_hash: ptr.hash=new nasal_hash; break;
case vm_func: ptr.func=new nasal_func; break;
}
return;
}
double nasal_val::to_number()
{
if(type==vm_str)
return trans_string_to_number(*ptr.str);
return str2num(*ptr.str);
return ptr.num;
}
std::string nasal_val::to_string()
@ -272,7 +245,7 @@ std::string nasal_val::to_string()
if(type==vm_str)
return *ptr.str;
else if(type==vm_num)
return trans_number_to_string(ptr.num);
return num2str(ptr.num);
return "";
}
@ -288,7 +261,7 @@ struct nasal_gc
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
std::vector<nasal_val*> slice_stack; // slice stack for vec[val,val,val:val]
std::vector<nasal_val*> memory; // gc memory
std::queue <nasal_val*> free_list; // gc free list
std::queue <nasal_val*> free_list[vm_type_size]; // gc free list
std::vector<nasal_val*> global;
std::list<std::vector<nasal_val*> > local;
void mark();
@ -296,6 +269,7 @@ struct nasal_gc
void gc_init(std::vector<double>&,std::vector<std::string>&);
void gc_clear();
nasal_val* gc_alloc(int);
nasal_val* builtin_alloc(int);
};
/* gc functions */
@ -304,7 +278,7 @@ void nasal_gc::mark()
std::queue<nasal_val*> bfs;
for(auto i:global)
bfs.push(i);
for(auto i:local)
for(auto& i:local)
for(auto j:i)
bfs.push(j);
for(auto i:slice_stack)
@ -321,7 +295,7 @@ void nasal_gc::mark()
for(auto i:tmp->ptr.vec->elems)
bfs.push(i);
else if(tmp->type==vm_hash)
for(auto i:tmp->ptr.hash->elems)
for(auto& i:tmp->ptr.hash->elems)
bfs.push(i.second);
else if(tmp->type==vm_func)
{
@ -337,10 +311,19 @@ void nasal_gc::sweep()
{
for(auto i:memory)
{
if(!i->mark)
if(!i->collected && !i->mark)
{
i->clear();
free_list.push(i);
switch(i->type)
{
case vm_nil: break;
case vm_num: i->ptr.num=0; break;
case vm_str: i->ptr.str->clear(); break;
case vm_vec: i->ptr.vec->elems.clear(); break;
case vm_hash:i->ptr.hash->elems.clear();break;
case vm_func:i->ptr.func->clear(); break;
}
free_list[i->type].push(i);
i->collected=true;
}
i->mark=false;
}
@ -348,11 +331,12 @@ void nasal_gc::sweep()
}
void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
{
for(int i=0;i<65536;++i)
for(int i=vm_num;i<vm_type_size;++i)
for(int j=0;j<increment[i];++j)
{
nasal_val* tmp=new nasal_val;
nasal_val* tmp=new nasal_val(i);
memory.push_back(tmp);
free_list.push(tmp);
free_list[i].push(tmp);
}
stack_top=val_stack; // set stack_top to val_stack
@ -388,8 +372,9 @@ void nasal_gc::gc_clear()
for(auto i:memory)
delete i;
memory.clear();
while(!free_list.empty())
free_list.pop();
for(int i=0;i<vm_type_size;++i)
while(!free_list[i].empty())
free_list[i].pop();
global.clear();
local.clear();
slice_stack.clear();
@ -407,21 +392,39 @@ void nasal_gc::gc_clear()
}
nasal_val* nasal_gc::gc_alloc(int type)
{
if(free_list.empty())
if(free_list[type].empty())
{
mark();
sweep();
}
if(free_list.empty())
for(int i=0;i<65536;++i)
if(free_list[type].empty())
for(int i=0;i<increment[type];++i)
{
nasal_val* tmp=new nasal_val;
nasal_val* tmp=new nasal_val(type);
memory.push_back(tmp);
free_list.push(tmp);
free_list[type].push(tmp);
}
nasal_val* ret=free_list.front();
free_list.pop();
ret->set_type(type);
nasal_val* ret=free_list[type].front();
ret->collected=false;
free_list[type].pop();
return ret;
}
nasal_val* nasal_gc::builtin_alloc(int type)
{
// when running a builtin function,alloc will run more than one time
// this may cause mark-sweep in gc_alloc
// and the value got before will be collected,this is a fatal error
// so use builtin_alloc in builtin functions if this function uses alloc more then one time
if(free_list[type].empty())
for(int i=0;i<increment[type];++i)
{
nasal_val* tmp=new nasal_val(type);
memory.push_back(tmp);
free_list[type].push(tmp);
}
nasal_val* ret=free_list[type].front();
ret->collected=false;
free_list[type].pop();
return ret;
}
#endif

View File

@ -24,7 +24,7 @@ public:
void nasal_import::die(std::string filename,std::string error_stage)
{
++error;
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<"."<<std::endl;
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<".\n";
return;
}
@ -32,7 +32,6 @@ bool nasal_import::check_import(nasal_ast& node)
{
/*
only this kind of node can be recognized as 'import':
call
id:import
call_func
@ -55,9 +54,8 @@ bool nasal_import::check_import(nasal_ast& node)
bool nasal_import::check_exist(std::string filename)
{
// avoid importing the same file
int size=filename_table.size();
for(int i=0;i<size;++i)
if(filename==filename_table[i])
for(auto& fname:filename_table)
if(filename==fname)
return true;
filename_table.push_back(filename);
return false;
@ -66,10 +64,8 @@ bool nasal_import::check_exist(std::string filename)
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
{
// add children of add_root to the back of root
std::vector<nasal_ast>& ref_vec=add_root.get_children();
int size=ref_vec.size();
for(int i=0;i<size;++i)
root.add_child(ref_vec[i]);
for(auto& i:add_root.get_children())
root.add_child(i);
return;
}
@ -110,18 +106,13 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
nasal_ast nasal_import::load(nasal_ast& root)
{
nasal_ast new_root(0,ast_root);
std::vector<nasal_ast>& ref_vec=root.get_children();
int size=ref_vec.size();
for(int i=0;i<size;++i)
for(auto& i:root.get_children())
if(check_import(i))
{
if(check_import(ref_vec[i]))
{
nasal_ast tmp=file_import(ref_vec[i]);
nasal_ast tmp=file_import(i);
// add tmp to the back of new_root
linker(new_root,tmp);
}
}
// add root to the back of new_root
linker(new_root,root);
// oops,i think it is not efficient if the root is too ... large?

View File

@ -103,11 +103,11 @@ private:
std::string line_code;
std::vector<char> res;
std::vector<token> token_list;
int get_token_type(std::string);
int get_tok_type(std::string);
void die(std::string,std::string,int,int);
std::string identifier_gen();
std::string number_gen();
std::string string_gen();
std::string id_gen();
std::string num_gen();
std::string str_gen();
public:
void openfile(std::string);
void scanner();
@ -140,7 +140,7 @@ void nasal_lexer::openfile(std::string filename)
return;
}
int nasal_lexer::get_token_type(std::string tk_str)
int nasal_lexer::get_tok_type(std::string tk_str)
{
for(int i=0;token_table[i].str;++i)
if(tk_str==token_table[i].str)
@ -158,7 +158,7 @@ void nasal_lexer::die(std::string code,std::string error_info,int line=-1,int co
return;
}
std::string nasal_lexer::identifier_gen()
std::string nasal_lexer::id_gen()
{
std::string token_str="";
while(ptr<res_size && (IS_IDENTIFIER(res[ptr])||IS_DIGIT(res[ptr])))
@ -168,7 +168,7 @@ std::string nasal_lexer::identifier_gen()
// after running this process, ptr will point to the next token's beginning character
}
std::string nasal_lexer::number_gen()
std::string nasal_lexer::num_gen()
{
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
std::string token_str="";
@ -258,7 +258,7 @@ std::string nasal_lexer::number_gen()
return token_str;
}
std::string nasal_lexer::string_gen()
std::string nasal_lexer::str_gen()
{
std::string token_str="";
char str_begin=res[ptr];
@ -325,21 +325,21 @@ void nasal_lexer::scanner()
if(ptr>=res_size) break;
if(IS_IDENTIFIER(res[ptr]))
{
token_str=identifier_gen();
token new_token(line,get_token_type(token_str),token_str);
token_str=id_gen();
token new_token(line,get_tok_type(token_str),token_str);
if(!new_token.type)
new_token.type=tok_id;
token_list.push_back(new_token);
}
else if(IS_DIGIT(res[ptr]))
{
token_str=number_gen();
token_str=num_gen();
token new_token(line,tok_num,token_str);
token_list.push_back(new_token);
}
else if(IS_STRING(res[ptr]))
{
token_str=string_gen();
token_str=str_gen();
token new_token(line,tok_str,token_str);
token_list.push_back(new_token);
}
@ -348,7 +348,7 @@ void nasal_lexer::scanner()
token_str="";
token_str+=res[ptr];
line_code+=res[ptr];
token new_token(line,get_token_type(token_str),token_str);
token new_token(line,get_tok_type(token_str),token_str);
if(!new_token.type)
die(line_code,"incorrect operator.",line,line_code.length());
token_list.push_back(new_token);
@ -367,7 +367,7 @@ void nasal_lexer::scanner()
++ptr;
}
line_code+=token_str;
token new_token(line,get_token_type(token_str),token_str);
token new_token(line,get_tok_type(token_str),token_str);
token_list.push_back(new_token);
}
else if(IS_CALC_OPERATOR(res[ptr]))
@ -377,7 +377,7 @@ void nasal_lexer::scanner()
if(ptr<res_size && res[ptr]=='=')
token_str+=res[ptr++];
line_code+=token_str;
token new_token(line,get_token_type(token_str),token_str);
token new_token(line,get_tok_type(token_str),token_str);
token_list.push_back(new_token);
}
else if(IS_NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1

View File

@ -135,14 +135,15 @@ void nasal_parse::main_process()
return;
std::vector<int> err_lines;
err_lines.push_back(error_token[0].line);
for(auto tok:error_token)
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)
for(auto& line:err_lines)
std::cout<<' '<<line;
std::cout<<" maybe recorded because of fatal syntax errors."
std::cout
<<" maybe recorded because of fatal syntax errors."
<<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n";
return;
}
@ -314,7 +315,7 @@ nasal_ast nasal_parse::nil_gen()
nasal_ast nasal_parse::num_gen()
{
nasal_ast node(tok_list[ptr].line,ast_num);
node.set_num(trans_string_to_number(tok_list[ptr].str));
node.set_num(str2num(tok_list[ptr].str));
return node;
}
nasal_ast nasal_parse::str_gen()

View File

@ -133,7 +133,7 @@ bool nasal_vm::condition(nasal_val* val_addr)
else if(type==vm_str)
{
std::string& str=*val_addr->ptr.str;
double number=trans_string_to_number(str);
double number=str2num(str);
if(std::isnan(number))
return str.length();
return number;
@ -212,7 +212,7 @@ void nasal_vm::opr_newf()
nasal_val* val=gc.gc_alloc(vm_func);
val->ptr.func->entry=exec_code[pc].num;
if(!gc.local.empty())
val->ptr.func->closure=gc.local.back();
val->ptr.func->closure=gc.local.back();// local contains 'me'
else
val->ptr.func->closure.push_back(gc.nil_addr);// me
*(++stack_top)=val;
@ -263,7 +263,7 @@ void nasal_vm::opr_unot()
new_val=val->ptr.num?gc.zero_addr:gc.one_addr;
else if(type==vm_str)
{
double number=trans_string_to_number(*val->ptr.str);
double number=str2num(*val->ptr.str);
if(std::isnan(number))
new_val=val->ptr.str->length()?gc.zero_addr:gc.one_addr;
else
@ -688,15 +688,15 @@ void nasal_vm::opr_callf()
die("callf: special call cannot use dynamic argument");
return;
}
for(auto i=ref_keys.begin();i!=ref_keys.end();++i)
for(auto& i:ref_keys)
{
if(ref_hash.count(i->first))
ref_closure[i->second+ref_func.offset]=ref_hash[i->first];
else if(ref_default[i->second])
ref_closure[i->second+ref_func.offset]=ref_default[i->second];
if(ref_hash.count(i.first))
ref_closure[i.second+ref_func.offset]=ref_hash[i.first];
else if(ref_default[i.second])
ref_closure[i.second+ref_func.offset]=ref_default[i.second];
else
{
die("callf: lack argument(s): \""+i->first+"\"");
die("callf: lack argument(s): \""+i.first+"\"");
return;
}
}
@ -733,7 +733,7 @@ void nasal_vm::opr_slc()
switch(val->type)
{
case vm_num:num=val->ptr.num;break;
case vm_str:num=trans_string_to_number(*val->ptr.str);break;
case vm_str:num=str2num(*val->ptr.str);break;
default:die("slc: error value type");break;
}
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
@ -800,7 +800,7 @@ void nasal_vm::opr_mcallv()
switch(val->type)
{
case vm_num:num=(int)val->ptr.num;break;
case vm_str:num=(int)trans_string_to_number(*val->ptr.str);break;
case vm_str:num=(int)str2num(*val->ptr.str);break;
default:die("mcallv: error value type");break;
}
nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num);