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:
parent
aae9395d66
commit
a68bf85f04
39
README.md
39
README.md
|
@ -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;
|
||||
}
|
||||
```
|
6
main.cpp
6
main.cpp
|
@ -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)
|
||||
|
|
5
nasal.h
5
nasal.h
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
157
nasal_gc.h
157
nasal_gc.h
|
@ -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
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
22
nasal_vm.h
22
nasal_vm.h
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue