This commit is contained in:
Valk Richard Li 2020-12-12 01:58:40 +08:00
parent a5825e0e92
commit 71f501a323
5 changed files with 146 additions and 71 deletions

View File

@ -132,10 +132,11 @@ void execute()
}
code_generator.main_progress(import.get_root());
code_generator.print_byte_code();
bytevm.set_string_table(code_generator.get_string_table());
bytevm.set_number_table(code_generator.get_number_table());
bytevm.set_exec_code(code_generator.get_exec_code());
//bytevm.run();
bytevm.run(
code_generator.get_string_table(),
code_generator.get_number_table(),
code_generator.get_exec_code()
);
return;
}

View File

@ -80,10 +80,7 @@ public:
nasal_bytecode_vm();
~nasal_bytecode_vm();
void clear();
void set_string_table(std::vector<std::string>&);
void set_number_table(std::vector<double>&);
void set_exec_code(std::vector<opcode>&);
void run();
void run(std::vector<std::string>&,std::vector<double>&,std::vector<opcode>&);
};
nasal_bytecode_vm::nasal_bytecode_vm()
@ -172,10 +169,14 @@ void nasal_bytecode_vm::clear()
vm.clear();
global_scope_addr=-1;
while(!value_stack.empty())value_stack.pop();
while(local_scope_stack.top()!=-1)local_scope_stack.pop();
while(!local_scope_stack.empty())local_scope_stack.pop();
local_scope_stack.push(-1);
while(!slice_stack.empty())slice_stack.pop();
while(!call_stack.empty())call_stack.pop();
while(!counter_stack.empty())counter_stack.pop();
string_table.clear();
number_table.clear();
exec_code.clear();
return;
}
void nasal_bytecode_vm::die(std::string str)
@ -211,6 +212,9 @@ void nasal_bytecode_vm::opr_load()
{
int val_addr=value_stack.top();
value_stack.pop();
if(local_scope_stack.top()>=0)
vm.gc_get(local_scope_stack.top()).get_closure().add_new_value(string_table[exec_code[ptr].index],val_addr);
else
vm.gc_get(global_scope_addr).get_closure().add_new_value(string_table[exec_code[ptr].index],val_addr);
return;
}
@ -285,38 +289,27 @@ void nasal_bytecode_vm::opr_hashapp()
{
int val_addr=value_stack.top();
value_stack.pop();
int str_addr=value_stack.top();
value_stack.pop();
int hash_addr=value_stack.top();
vm.gc_get(hash_addr).get_hash().add_elem(vm.gc_get(str_addr).get_string(),val_addr);
vm.del_reference(str_addr);
vm.gc_get(hash_addr).get_hash().add_elem(string_table[exec_code[ptr].index],val_addr);
return;
}
void nasal_bytecode_vm::opr_para()
{
int str_addr=value_stack.top();
value_stack.pop();
std::string str=vm.gc_get(str_addr).get_string();
vm.del_reference(str_addr);
vm.gc_get(value_stack.top()).get_func().add_para(str,-1);
std::string str=string_table[exec_code[ptr].index];
vm.gc_get(value_stack.top()).get_func().add_para(str);
return;
}
void nasal_bytecode_vm::opr_defpara()
{
int str_addr=value_stack.top();
value_stack.pop();
std::string str=vm.gc_get(str_addr).get_string();
vm.del_reference(str_addr);
vm.gc_get(value_stack.top()).get_func().add_para(str,value_stack.top());
int val_addr=value_stack.top();
value_stack.pop();
std::string str=string_table[exec_code[ptr].index];
vm.gc_get(value_stack.top()).get_func().add_para(str,val_addr);
return;
}
void nasal_bytecode_vm::opr_dynpara()
{
int str_addr=value_stack.top();
value_stack.pop();
std::string str=vm.gc_get(str_addr).get_string();
vm.del_reference(str_addr);
std::string str=string_table[exec_code[ptr].index];
vm.gc_get(value_stack.top()).get_func().add_para(str,-1,true);
return;
}
@ -1039,9 +1032,9 @@ void nasal_bytecode_vm::opr_call()
{
int val_addr=-1;
if(local_scope_stack.top()>=0)
vm.gc_get(local_scope_stack.top()).get_closure().get_value_address(string_table[exec_code[ptr].index]);
val_addr=vm.gc_get(local_scope_stack.top()).get_closure().get_value_address(string_table[exec_code[ptr].index]);
else
vm.gc_get(global_scope_addr).get_closure().get_value_address(string_table[exec_code[ptr].index]);
val_addr=vm.gc_get(global_scope_addr).get_closure().get_value_address(string_table[exec_code[ptr].index]);
if(val_addr<0)
die("call: cannot find symbol named \""+string_table[exec_code[ptr].index]+"\"");
value_stack.push(val_addr);
@ -1157,10 +1150,73 @@ void nasal_bytecode_vm::opr_callf()
}
nasal_function& ref=vm.gc_get(func_addr).get_func();
int closure=ref.get_closure_addr();
vm.gc_get(closure).get_closure().add_scope();
nasal_closure& ref_closure=vm.gc_get(closure).get_closure();
ref_closure.add_scope();
local_scope_stack.push(closure);
vm.add_reference(closure);
// unfinished
if(vm.gc_get(para_addr).get_type()==vm_vector)
{
nasal_vector& ref_vec=vm.gc_get(para_addr).get_vector();
std::vector<std::string>& ref_para=ref.get_para();
std::vector<int>& ref_default=ref.get_default();
int i=0;
for(;i<ref_para.size();++i)
{
if(i>=ref_vec.size())
{
if(ref_default[i]<0)
{
die("callf: lack argument(s)");
return;
}
ref_closure.add_new_value(ref_para[i],ref_default[i]);
vm.add_reference(ref_default[i]);
}
else
{
int tmp=ref_vec.get_value_address(i);
ref_closure.add_new_value(ref_para[i],tmp);
vm.add_reference(tmp);
}
}
if(ref.get_dynamic_para().length())
{
int vec_addr=vm.gc_alloc(vm_vector);
for(;i<ref_vec.size();++i)
{
int tmp=ref_vec.get_value_address(i);
vm.gc_get(vec_addr).get_vector().add_elem(tmp);
vm.add_reference(tmp);
}
ref_closure.add_new_value(ref.get_dynamic_para(),vec_addr);
}
}
else
{
nasal_hash& ref_hash=vm.gc_get(para_addr).get_hash();
std::vector<std::string>& ref_para=ref.get_para();
std::vector<int>& ref_default=ref.get_default();
if(ref.get_dynamic_para().length())
{
die("callf: special call cannot use dynamic parameter");
return;
}
for(int i=0;i<ref_para.size();++i)
{
int tmp=ref_hash.get_special_para(ref_para[i]);
if(tmp<0)
tmp=ref_default[i];
if(tmp<0)
{
die("callf: lack argument(s)");
return;
}
vm.add_reference(tmp);
ref_closure.add_new_value(ref_para[i],tmp);
}
}
vm.del_reference(para_addr);
call_stack.push(ptr);
ptr=ref.get_entry()-1;
return;
@ -1182,7 +1238,7 @@ void nasal_bytecode_vm::opr_slicebegin()
int val_addr=vm.gc_alloc(vm_vector);
slice_stack.push(val_addr);
if(vm.gc_get(value_stack.top()).get_type()!=vm_vector)
die("must slice a vector");
die("slcbegin: must slice a vector");
return;
}
void nasal_bytecode_vm::opr_sliceend()
@ -1340,13 +1396,13 @@ void nasal_bytecode_vm::opr_mcallh()
value_stack.pop();
if(vm.gc_get(hash_addr).get_type()!=vm_hash)
{
die("must call a hash");
die("mcallh: must call a hash");
return;
}
mem_addr=vm.gc_get(hash_addr).get_hash().get_mem_address(vm.gc_get(val_addr).get_string());
if(mem_addr<0)
{
die("cannot get memory space in this hash");
die("mcallh: cannot get memory space in this hash");
return;
}
value_stack.push(mem_addr);
@ -1360,20 +1416,18 @@ void nasal_bytecode_vm::opr_return()
vm.del_reference(closure_addr);
ptr=call_stack.top();
call_stack.pop();
int tmp=value_stack.top();
value_stack.pop();
// delete function
vm.del_reference(value_stack.top());
value_stack.pop();
value_stack.push(tmp);
return;
}
void nasal_bytecode_vm::set_string_table(std::vector<std::string>& table)
{
string_table=table;
return;
}
void nasal_bytecode_vm::set_number_table(std::vector<double>& table)
{
number_table=table;
return;
}
void nasal_bytecode_vm::set_exec_code(std::vector<opcode>& exec)
void nasal_bytecode_vm::run(std::vector<std::string>& strs,std::vector<double>& nums,std::vector<opcode>& exec)
{
string_table=strs;
number_table=nums;
int size=exec.size();
for(int i=0;i<size;++i)
{
@ -1381,15 +1435,13 @@ void nasal_bytecode_vm::set_exec_code(std::vector<opcode>& exec)
tmp=exec[i];
exec_code.push_back(tmp);
}
return;
}
void nasal_bytecode_vm::run()
{
error=0;
global_scope_addr=vm.gc_alloc(vm_closure);
int size=exec_code.size();
size=exec_code.size();
for(ptr=0;ptr<size;++ptr)
{
std::cout<<ptr<<'\n';
(this->*opr_table[exec_code[ptr].op])();
if(error)
break;

View File

@ -277,10 +277,11 @@ void nasal_codegen::hash_gen(nasal_ast& ast)
exec_code.push_back(op);
for(int i=0;i<size;++i)
{
string_gen(ast.get_children()[i].get_children()[0]);
calculation_gen(ast.get_children()[i].get_children()[1]);
op.op=op_hashapp;
op.index=0;
std::string str=ast.get_children()[i].get_children()[0].get_str();
regist_string(str);
op.index=string_table[str];
exec_code.push_back(op);
}
return;
@ -1230,6 +1231,7 @@ void nasal_codegen::print_op(int index)
switch(exec_code[index].op)
{
case op_pushnum:std::cout<<'('<<number_result_table[exec_code[index].index]<<')';break;
case op_hashapp:
case op_call:
case op_builtincall:
case op_mcall:

View File

@ -51,6 +51,7 @@ public:
void add_elem(std::string,int);
void del_elem(std::string);
int size();
int get_special_para(std::string);
int get_value_address(std::string);
int get_mem_address(std::string);
bool check_contain(std::string);
@ -67,13 +68,18 @@ private:
int closure_addr;
nasal_ast argument_list;
nasal_ast function_expr;
std::map<std::string,int> para;
std::vector<std::string> para_name;
std::string dynamic_para_name;
std::vector<int> default_para_addr;
public:
nasal_function(nasal_virtual_machine&);
~nasal_function();
void set_entry(int);
int get_entry();
void add_para(std::string,int,bool);
std::vector<std::string>& get_para();
std::string get_dynamic_para();
std::vector<int>& get_default();
void set_closure_addr(int);
int get_closure_addr();
void set_arguments(nasal_ast&);
@ -272,6 +278,12 @@ int nasal_hash::size()
{
return elems.size();
}
int nasal_hash::get_special_para(std::string key)
{
if(elems.find(key)!=elems.end())
return vm.mem_get(elems[key]);
return -1;
}
int nasal_hash::get_value_address(std::string key)
{
int ret_value_addr=-1;
@ -388,6 +400,7 @@ void nasal_hash::print()
nasal_function::nasal_function(nasal_virtual_machine& nvm):vm(nvm)
{
closure_addr=-1;
dynamic_para_name="";
argument_list.clear();
function_expr.clear();
return;
@ -396,10 +409,9 @@ nasal_function::~nasal_function()
{
if(closure_addr>=0)
vm.del_reference(closure_addr);
for(std::map<std::string,int>::iterator i=para.begin();i!=para.end();++i)
if(i->second>=0)
vm.del_reference(i->second);
para.clear();
for(int i=0;i<default_para_addr.size();++i)
if(default_para_addr[i]>=0)
vm.del_reference(default_para_addr[i]);
argument_list.clear();
function_expr.clear();
return;
@ -413,14 +425,28 @@ int nasal_function::get_entry()
{
return entry;
}
void nasal_function::add_para(std::string key,int init_value_addr,bool is_dynamic=false)
void nasal_function::add_para(std::string name,int val_addr=-1,bool is_dynamic=false)
{
if(para.find(key)!=para.end())
vm.del_reference(para[key]);
para[key]=init_value_addr;
if(is_dynamic)
para[key]=vm.gc_alloc(vm_vector);
{
dynamic_para_name=name;
return;
}
para_name.push_back(name);
default_para_addr.push_back(val_addr);
return;
}
std::vector<std::string>& nasal_function::get_para()
{
return para_name;
}
std::string nasal_function::get_dynamic_para()
{
return dynamic_para_name;
}
std::vector<int>& nasal_function::get_default()
{
return default_para_addr;
}
void nasal_function::set_closure_addr(int value_address)
{

View File

@ -53,7 +53,7 @@ private:
int call_scalar(nasal_ast&,int);
int call_vector(nasal_ast&,int,int);
int call_hash(nasal_ast&,int,int);
int call_function(nasal_ast&,std::string,int,int,int);
int call_function(nasal_ast&,int,int,int);
int call_builtin_function(std::string,int);
// get scalars' memory place in complex data structure like vector/hash/function/closure(scope)
int call_scalar_mem(nasal_ast&,int);
@ -505,7 +505,7 @@ int nasal_runtime::call_scalar(nasal_ast& node,int local_scope_addr)
val_name=call_expr.get_str();
break;
case ast_call_func:
tmp_value_addr=call_function(call_expr,val_name,value_address,last_call_hash_addr,local_scope_addr);
tmp_value_addr=call_function(call_expr,value_address,last_call_hash_addr,local_scope_addr);
last_call_hash_addr=-1;
val_name="";
break;
@ -734,7 +734,7 @@ int nasal_runtime::call_hash(nasal_ast& node,int base_value_addr,int local_scope
nasal_vm.add_reference(ret_value_addr);
return ret_value_addr;
}
int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_value_addr,int last_call_hash_addr,int local_scope_addr)
int nasal_runtime::call_function(nasal_ast& node,int base_value_addr,int last_call_hash_addr,int local_scope_addr)
{
int ret_value_addr=-1;
int value_type=nasal_vm.gc_get(base_value_addr).get_type();
@ -753,12 +753,6 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_
nasal_vm.add_reference(last_call_hash_addr);
run_closure.add_new_value("me",last_call_hash_addr);
}
else if(func_name.length())
{
// when hash.me does not exist,set self
nasal_vm.add_reference(base_value_addr);
run_closure.add_new_value(func_name,base_value_addr);
}
nasal_ast& argument_format=reference_of_func.get_arguments();
if(!node.get_children().size())
{