This commit is contained in:
Valk Richard Li 2020-12-12 19:58:43 +08:00
parent 71f501a323
commit d8ce203ab3
3 changed files with 96 additions and 23 deletions

View File

@ -17,7 +17,8 @@ void help()
std::cout<<">> [lex ] use lexer to turn code into tokens.\n";
std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n";
std::cout<<">> [run ] run abstract syntax tree.\n";
std::cout<<">> [exec ] generate byte code.\n";
std::cout<<">> [code ] show byte code.\n";
std::cout<<">> [exec ] execute program on bytecode vm.\n";
std::cout<<">> [logo ] print logo of nasal .\n";
std::cout<<">> [exit ] quit nasal interpreter.\n";
return;
@ -108,7 +109,7 @@ void runtime_start()
return;
}
void execute()
void show_bytecode()
{
lexer.openfile(inputfile);
lexer.scanner();
@ -132,6 +133,32 @@ void execute()
}
code_generator.main_progress(import.get_root());
code_generator.print_byte_code();
return;
}
void execute()
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
parse.set_toklist(lexer.get_token_list());
parse.main_process();
if(parse.get_error())
{
die("parse",inputfile);
return;
}
import.link(parse.get_root());
if(import.get_error())
{
die("import",inputfile);
return;
}
code_generator.main_progress(import.get_root());
bytevm.run(
code_generator.get_string_table(),
code_generator.get_number_table(),
@ -189,6 +216,8 @@ int main()
ast_print();
else if(command=="run")
runtime_start();
else if(command=="code")
show_bytecode();
else if(command=="exec")
execute();
else if(command=="logo")

View File

@ -7,16 +7,27 @@ private:
int error;
int ptr;
int global_scope_addr;
// garbage collector and memory manager
nasal_virtual_machine vm;
// byte codes store here
std::vector<opcode> exec_code;
// main calculation stack
std::stack<int> value_stack;
// local scope for function block
std::stack<int> local_scope_stack;
// slice stack for vec[val,val,val:val]
std::stack<int> slice_stack;
// ptr stack stores address for function to return
std::stack<int> call_stack;
// iterator stack for forindex/foreach
std::stack<int> counter_stack;
// string table
std::vector<std::string> string_table;
// number table
std::vector<double> number_table;
// opcode -> function address table
std::vector<void (nasal_bytecode_vm::*)()> opr_table;
// builtin function address table
std::map<std::string,int (*)(int x,nasal_virtual_machine& vm)> builtin_func_hashmap;
void die(std::string);
bool check_condition(int);
@ -182,7 +193,15 @@ void nasal_bytecode_vm::clear()
void nasal_bytecode_vm::die(std::string str)
{
++error;
std::cout<<">> [vm] "<<str<<'\n';
std::string numinfo="";
int num=ptr;
for(int i=0;i<8;++i)
{
int tmp=num&0x0f;
numinfo=(char)(tmp>9? 'a'+tmp-10:'0'+tmp)+numinfo;
num>>=4;
}
std::cout<<">> [vm] 0x"<<numinfo<<": "<<str<<'\n';
return;
}
bool nasal_bytecode_vm::check_condition(int value_addr)
@ -1004,6 +1023,7 @@ void nasal_bytecode_vm::opr_forindex()
{
vm.del_reference(value_stack.top());
value_stack.pop();
counter_stack.pop();
ptr=exec_code[ptr].index-1;
return;
}
@ -1020,6 +1040,7 @@ void nasal_bytecode_vm::opr_foreach()
{
vm.del_reference(value_stack.top());
value_stack.pop();
counter_stack.pop();
ptr=exec_code[ptr].index-1;
return;
}
@ -1033,10 +1054,14 @@ void nasal_bytecode_vm::opr_call()
int val_addr=-1;
if(local_scope_stack.top()>=0)
val_addr=vm.gc_get(local_scope_stack.top()).get_closure().get_value_address(string_table[exec_code[ptr].index]);
else
if(val_addr<0)
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]+"\"");
return;
}
vm.add_reference(val_addr);
value_stack.push(val_addr);
return;
}
@ -1098,6 +1123,11 @@ void nasal_bytecode_vm::opr_callv()
die("callv: cannot find member \""+vm.gc_get(val_addr).get_string()+"\" of this hash");
return;
}
if(vm.gc_get(res).get_type()==vm_function)
{
vm.gc_get(vm.gc_get(res).get_func().get_closure_addr()).get_closure().add_new_value("me",val_addr);
vm.add_reference(val_addr);
}
vm.add_reference(res);
value_stack.push(res);
}
@ -1133,8 +1163,16 @@ void nasal_bytecode_vm::opr_callh()
return;
}
int res=vm.gc_get(val_addr).get_hash().get_value_address(string_table[exec_code[ptr].index]);
if(res<0)
{
die("callh: hash member \""+string_table[exec_code[ptr].index]+"\" does not exist");
return;
}
vm.add_reference(res);
vm.del_reference(val_addr);
if(vm.gc_get(res).get_type()==vm_function)
vm.gc_get(vm.gc_get(res).get_func().get_closure_addr()).get_closure().add_new_value("me",val_addr);
else
vm.del_reference(val_addr);
value_stack.push(res);
return;
}
@ -1154,7 +1192,6 @@ void nasal_bytecode_vm::opr_callf()
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();
@ -1212,8 +1249,8 @@ void nasal_bytecode_vm::opr_callf()
die("callf: lack argument(s)");
return;
}
vm.add_reference(tmp);
ref_closure.add_new_value(ref_para[i],tmp);
vm.add_reference(tmp);
}
}
vm.del_reference(para_addr);
@ -1333,7 +1370,7 @@ void nasal_bytecode_vm::opr_mcall()
int mem_addr=-1;
if(local_scope_stack.top()>=0)
mem_addr=vm.gc_get(local_scope_stack.top()).get_closure().get_mem_address(string_table[exec_code[ptr].index]);
else
if(mem_addr<0)
mem_addr=vm.gc_get(global_scope_addr).get_closure().get_mem_address(string_table[exec_code[ptr].index]);
if(mem_addr<0)
die("mcall: cannot find symbol named \""+string_table[exec_code[ptr].index]+"\"");
@ -1390,8 +1427,6 @@ void nasal_bytecode_vm::opr_mcallv()
void nasal_bytecode_vm::opr_mcallh()
{
int mem_addr=-1;
int val_addr=value_stack.top();
value_stack.pop();
int hash_addr=vm.mem_get(value_stack.top());
value_stack.pop();
if(vm.gc_get(hash_addr).get_type()!=vm_hash)
@ -1399,7 +1434,7 @@ void nasal_bytecode_vm::opr_mcallh()
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());
mem_addr=vm.gc_get(hash_addr).get_hash().get_mem_address(string_table[exec_code[ptr].index]);
if(mem_addr<0)
{
die("mcallh: cannot get memory space in this hash");
@ -1435,18 +1470,23 @@ void nasal_bytecode_vm::run(std::vector<std::string>& strs,std::vector<double>&
tmp=exec[i];
exec_code.push_back(tmp);
}
error=0;
global_scope_addr=vm.gc_alloc(vm_closure);
size=exec_code.size();
time_t begin_time=std::time(NULL);
for(ptr=0;ptr<size;++ptr)
{
std::cout<<ptr<<'\n';
(this->*opr_table[exec_code[ptr].op])();
if(error)
break;
}
time_t end_time=std::time(NULL);
time_t total_run_time=end_time-begin_time;
if(total_run_time>=1)
std::cout<<">> [vm] process exited after "<<total_run_time<<"s.\n";
vm.del_reference(global_scope_addr);
clear();
return;
}

View File

@ -161,7 +161,7 @@ private:
void multi_assignment_gen(nasal_ast&);
void conditional_gen(nasal_ast&);
void loop_gen(nasal_ast&);
void load_continue_break();
void load_continue_break(int,int);
void while_gen(nasal_ast&);
void for_gen(nasal_ast&);
void forindex_gen(nasal_ast&);
@ -465,10 +465,11 @@ void nasal_codegen::call_func(nasal_ast& ast)
for(int i=0;i<size;++i)
{
nasal_ast& tmp=ast.get_children()[i];
string_gen(tmp.get_children()[0]);
calculation_gen(tmp.get_children()[1]);
std::string str=tmp.get_children()[0].get_str();
regist_string(str);
op.op=op_hashapp;
op.index=0;
op.index=string_table[str];
exec_code.push_back(op);
}
op.op=op_callf;
@ -683,13 +684,13 @@ void nasal_codegen::loop_gen(nasal_ast& ast)
return;
}
void nasal_codegen::load_continue_break()
void nasal_codegen::load_continue_break(int continue_place,int break_place)
{
for(int i=0;i<continue_ptr.size();++i)
exec_code[continue_ptr[i]].index=exec_code.size()-2;
exec_code[continue_ptr[i]].index=continue_place;
continue_ptr.clear();
for(int i=0;i<break_ptr.size();++i)
exec_code[break_ptr[i]].index=exec_code.size();
exec_code[break_ptr[i]].index=break_place;
break_ptr.clear();
return;
}
@ -709,7 +710,7 @@ void nasal_codegen::while_gen(nasal_ast& ast)
exec_code.push_back(op);
exec_code[condition_ptr].index=exec_code.size();
pop_gen();
load_continue_break();
load_continue_break(exec_code.size()-2,exec_code.size());
return;
}
@ -744,6 +745,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
exec_code.push_back(op);
pop_gen();
block_gen(ast.get_children()[3]);
int continue_place=exec_code.size();
switch(ast.get_children()[2].get_type())
{
case ast_null:break;
@ -763,7 +765,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
exec_code.push_back(op);
exec_code[label_exit].index=exec_code.size();
pop_gen();
load_continue_break();
load_continue_break(continue_place,exec_code.size());
return;
}
void nasal_codegen::forindex_gen(nasal_ast& ast)
@ -799,7 +801,7 @@ void nasal_codegen::forindex_gen(nasal_ast& ast)
op.index=ptr;
exec_code.push_back(op);
exec_code[ptr].index=exec_code.size();
load_continue_break();
load_continue_break(exec_code.size()-1,exec_code.size());
return;
}
void nasal_codegen::foreach_gen(nasal_ast& ast)
@ -835,7 +837,7 @@ void nasal_codegen::foreach_gen(nasal_ast& ast)
op.index=ptr;
exec_code.push_back(op);
exec_code[ptr].index=exec_code.size();
load_continue_break();
load_continue_break(exec_code.size()-1,exec_code.size());
return;
}
@ -1125,6 +1127,8 @@ void nasal_codegen::return_gen(nasal_ast& ast)
{
if(ast.get_children().size())
calculation_gen(ast.get_children()[0]);
else
nil_gen();
opcode op;
op.op=op_return;
exec_code.push_back(op);