update
This commit is contained in:
parent
71f501a323
commit
d8ce203ab3
33
main.cpp
33
main.cpp
|
@ -17,7 +17,8 @@ void help()
|
||||||
std::cout<<">> [lex ] use lexer to turn code into tokens.\n";
|
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<<">> [ast ] do parsing and check the abstract syntax tree.\n";
|
||||||
std::cout<<">> [run ] run 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<<">> [logo ] print logo of nasal .\n";
|
||||||
std::cout<<">> [exit ] quit nasal interpreter.\n";
|
std::cout<<">> [exit ] quit nasal interpreter.\n";
|
||||||
return;
|
return;
|
||||||
|
@ -108,7 +109,7 @@ void runtime_start()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute()
|
void show_bytecode()
|
||||||
{
|
{
|
||||||
lexer.openfile(inputfile);
|
lexer.openfile(inputfile);
|
||||||
lexer.scanner();
|
lexer.scanner();
|
||||||
|
@ -132,6 +133,32 @@ void execute()
|
||||||
}
|
}
|
||||||
code_generator.main_progress(import.get_root());
|
code_generator.main_progress(import.get_root());
|
||||||
code_generator.print_byte_code();
|
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(
|
bytevm.run(
|
||||||
code_generator.get_string_table(),
|
code_generator.get_string_table(),
|
||||||
code_generator.get_number_table(),
|
code_generator.get_number_table(),
|
||||||
|
@ -189,6 +216,8 @@ int main()
|
||||||
ast_print();
|
ast_print();
|
||||||
else if(command=="run")
|
else if(command=="run")
|
||||||
runtime_start();
|
runtime_start();
|
||||||
|
else if(command=="code")
|
||||||
|
show_bytecode();
|
||||||
else if(command=="exec")
|
else if(command=="exec")
|
||||||
execute();
|
execute();
|
||||||
else if(command=="logo")
|
else if(command=="logo")
|
||||||
|
|
|
@ -7,16 +7,27 @@ private:
|
||||||
int error;
|
int error;
|
||||||
int ptr;
|
int ptr;
|
||||||
int global_scope_addr;
|
int global_scope_addr;
|
||||||
|
// garbage collector and memory manager
|
||||||
nasal_virtual_machine vm;
|
nasal_virtual_machine vm;
|
||||||
|
// byte codes store here
|
||||||
std::vector<opcode> exec_code;
|
std::vector<opcode> exec_code;
|
||||||
|
// main calculation stack
|
||||||
std::stack<int> value_stack;
|
std::stack<int> value_stack;
|
||||||
|
// local scope for function block
|
||||||
std::stack<int> local_scope_stack;
|
std::stack<int> local_scope_stack;
|
||||||
|
// slice stack for vec[val,val,val:val]
|
||||||
std::stack<int> slice_stack;
|
std::stack<int> slice_stack;
|
||||||
|
// ptr stack stores address for function to return
|
||||||
std::stack<int> call_stack;
|
std::stack<int> call_stack;
|
||||||
|
// iterator stack for forindex/foreach
|
||||||
std::stack<int> counter_stack;
|
std::stack<int> counter_stack;
|
||||||
|
// string table
|
||||||
std::vector<std::string> string_table;
|
std::vector<std::string> string_table;
|
||||||
|
// number table
|
||||||
std::vector<double> number_table;
|
std::vector<double> number_table;
|
||||||
|
// opcode -> function address table
|
||||||
std::vector<void (nasal_bytecode_vm::*)()> opr_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;
|
std::map<std::string,int (*)(int x,nasal_virtual_machine& vm)> builtin_func_hashmap;
|
||||||
void die(std::string);
|
void die(std::string);
|
||||||
bool check_condition(int);
|
bool check_condition(int);
|
||||||
|
@ -182,7 +193,15 @@ void nasal_bytecode_vm::clear()
|
||||||
void nasal_bytecode_vm::die(std::string str)
|
void nasal_bytecode_vm::die(std::string str)
|
||||||
{
|
{
|
||||||
++error;
|
++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;
|
return;
|
||||||
}
|
}
|
||||||
bool nasal_bytecode_vm::check_condition(int value_addr)
|
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());
|
vm.del_reference(value_stack.top());
|
||||||
value_stack.pop();
|
value_stack.pop();
|
||||||
|
counter_stack.pop();
|
||||||
ptr=exec_code[ptr].index-1;
|
ptr=exec_code[ptr].index-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1020,6 +1040,7 @@ void nasal_bytecode_vm::opr_foreach()
|
||||||
{
|
{
|
||||||
vm.del_reference(value_stack.top());
|
vm.del_reference(value_stack.top());
|
||||||
value_stack.pop();
|
value_stack.pop();
|
||||||
|
counter_stack.pop();
|
||||||
ptr=exec_code[ptr].index-1;
|
ptr=exec_code[ptr].index-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1033,10 +1054,14 @@ void nasal_bytecode_vm::opr_call()
|
||||||
int val_addr=-1;
|
int val_addr=-1;
|
||||||
if(local_scope_stack.top()>=0)
|
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]);
|
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]);
|
val_addr=vm.gc_get(global_scope_addr).get_closure().get_value_address(string_table[exec_code[ptr].index]);
|
||||||
if(val_addr<0)
|
if(val_addr<0)
|
||||||
|
{
|
||||||
die("call: cannot find symbol named \""+string_table[exec_code[ptr].index]+"\"");
|
die("call: cannot find symbol named \""+string_table[exec_code[ptr].index]+"\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vm.add_reference(val_addr);
|
||||||
value_stack.push(val_addr);
|
value_stack.push(val_addr);
|
||||||
return;
|
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");
|
die("callv: cannot find member \""+vm.gc_get(val_addr).get_string()+"\" of this hash");
|
||||||
return;
|
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);
|
vm.add_reference(res);
|
||||||
value_stack.push(res);
|
value_stack.push(res);
|
||||||
}
|
}
|
||||||
|
@ -1133,8 +1163,16 @@ void nasal_bytecode_vm::opr_callh()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int res=vm.gc_get(val_addr).get_hash().get_value_address(string_table[exec_code[ptr].index]);
|
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.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);
|
value_stack.push(res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1154,7 +1192,6 @@ void nasal_bytecode_vm::opr_callf()
|
||||||
ref_closure.add_scope();
|
ref_closure.add_scope();
|
||||||
local_scope_stack.push(closure);
|
local_scope_stack.push(closure);
|
||||||
vm.add_reference(closure);
|
vm.add_reference(closure);
|
||||||
// unfinished
|
|
||||||
if(vm.gc_get(para_addr).get_type()==vm_vector)
|
if(vm.gc_get(para_addr).get_type()==vm_vector)
|
||||||
{
|
{
|
||||||
nasal_vector& ref_vec=vm.gc_get(para_addr).get_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)");
|
die("callf: lack argument(s)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vm.add_reference(tmp);
|
|
||||||
ref_closure.add_new_value(ref_para[i],tmp);
|
ref_closure.add_new_value(ref_para[i],tmp);
|
||||||
|
vm.add_reference(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm.del_reference(para_addr);
|
vm.del_reference(para_addr);
|
||||||
|
@ -1333,7 +1370,7 @@ void nasal_bytecode_vm::opr_mcall()
|
||||||
int mem_addr=-1;
|
int mem_addr=-1;
|
||||||
if(local_scope_stack.top()>=0)
|
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]);
|
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]);
|
mem_addr=vm.gc_get(global_scope_addr).get_closure().get_mem_address(string_table[exec_code[ptr].index]);
|
||||||
if(mem_addr<0)
|
if(mem_addr<0)
|
||||||
die("mcall: cannot find symbol named \""+string_table[exec_code[ptr].index]+"\"");
|
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()
|
void nasal_bytecode_vm::opr_mcallh()
|
||||||
{
|
{
|
||||||
int mem_addr=-1;
|
int mem_addr=-1;
|
||||||
int val_addr=value_stack.top();
|
|
||||||
value_stack.pop();
|
|
||||||
int hash_addr=vm.mem_get(value_stack.top());
|
int hash_addr=vm.mem_get(value_stack.top());
|
||||||
value_stack.pop();
|
value_stack.pop();
|
||||||
if(vm.gc_get(hash_addr).get_type()!=vm_hash)
|
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");
|
die("mcallh: must call a hash");
|
||||||
return;
|
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)
|
if(mem_addr<0)
|
||||||
{
|
{
|
||||||
die("mcallh: cannot get memory space in this hash");
|
die("mcallh: cannot get memory space in this hash");
|
||||||
|
@ -1439,14 +1474,19 @@ void nasal_bytecode_vm::run(std::vector<std::string>& strs,std::vector<double>&
|
||||||
error=0;
|
error=0;
|
||||||
global_scope_addr=vm.gc_alloc(vm_closure);
|
global_scope_addr=vm.gc_alloc(vm_closure);
|
||||||
size=exec_code.size();
|
size=exec_code.size();
|
||||||
|
time_t begin_time=std::time(NULL);
|
||||||
for(ptr=0;ptr<size;++ptr)
|
for(ptr=0;ptr<size;++ptr)
|
||||||
{
|
{
|
||||||
std::cout<<ptr<<'\n';
|
|
||||||
(this->*opr_table[exec_code[ptr].op])();
|
(this->*opr_table[exec_code[ptr].op])();
|
||||||
if(error)
|
if(error)
|
||||||
break;
|
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);
|
vm.del_reference(global_scope_addr);
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ private:
|
||||||
void multi_assignment_gen(nasal_ast&);
|
void multi_assignment_gen(nasal_ast&);
|
||||||
void conditional_gen(nasal_ast&);
|
void conditional_gen(nasal_ast&);
|
||||||
void loop_gen(nasal_ast&);
|
void loop_gen(nasal_ast&);
|
||||||
void load_continue_break();
|
void load_continue_break(int,int);
|
||||||
void while_gen(nasal_ast&);
|
void while_gen(nasal_ast&);
|
||||||
void for_gen(nasal_ast&);
|
void for_gen(nasal_ast&);
|
||||||
void forindex_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)
|
for(int i=0;i<size;++i)
|
||||||
{
|
{
|
||||||
nasal_ast& tmp=ast.get_children()[i];
|
nasal_ast& tmp=ast.get_children()[i];
|
||||||
string_gen(tmp.get_children()[0]);
|
|
||||||
calculation_gen(tmp.get_children()[1]);
|
calculation_gen(tmp.get_children()[1]);
|
||||||
|
std::string str=tmp.get_children()[0].get_str();
|
||||||
|
regist_string(str);
|
||||||
op.op=op_hashapp;
|
op.op=op_hashapp;
|
||||||
op.index=0;
|
op.index=string_table[str];
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
}
|
}
|
||||||
op.op=op_callf;
|
op.op=op_callf;
|
||||||
|
@ -683,13 +684,13 @@ void nasal_codegen::loop_gen(nasal_ast& ast)
|
||||||
return;
|
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)
|
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();
|
continue_ptr.clear();
|
||||||
for(int i=0;i<break_ptr.size();++i)
|
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();
|
break_ptr.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +710,7 @@ void nasal_codegen::while_gen(nasal_ast& ast)
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
exec_code[condition_ptr].index=exec_code.size();
|
exec_code[condition_ptr].index=exec_code.size();
|
||||||
pop_gen();
|
pop_gen();
|
||||||
load_continue_break();
|
load_continue_break(exec_code.size()-2,exec_code.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,6 +745,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
pop_gen();
|
pop_gen();
|
||||||
block_gen(ast.get_children()[3]);
|
block_gen(ast.get_children()[3]);
|
||||||
|
int continue_place=exec_code.size();
|
||||||
switch(ast.get_children()[2].get_type())
|
switch(ast.get_children()[2].get_type())
|
||||||
{
|
{
|
||||||
case ast_null:break;
|
case ast_null:break;
|
||||||
|
@ -763,7 +765,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
exec_code[label_exit].index=exec_code.size();
|
exec_code[label_exit].index=exec_code.size();
|
||||||
pop_gen();
|
pop_gen();
|
||||||
load_continue_break();
|
load_continue_break(continue_place,exec_code.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_codegen::forindex_gen(nasal_ast& ast)
|
void nasal_codegen::forindex_gen(nasal_ast& ast)
|
||||||
|
@ -799,7 +801,7 @@ void nasal_codegen::forindex_gen(nasal_ast& ast)
|
||||||
op.index=ptr;
|
op.index=ptr;
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
exec_code[ptr].index=exec_code.size();
|
exec_code[ptr].index=exec_code.size();
|
||||||
load_continue_break();
|
load_continue_break(exec_code.size()-1,exec_code.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_codegen::foreach_gen(nasal_ast& ast)
|
void nasal_codegen::foreach_gen(nasal_ast& ast)
|
||||||
|
@ -835,7 +837,7 @@ void nasal_codegen::foreach_gen(nasal_ast& ast)
|
||||||
op.index=ptr;
|
op.index=ptr;
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
exec_code[ptr].index=exec_code.size();
|
exec_code[ptr].index=exec_code.size();
|
||||||
load_continue_break();
|
load_continue_break(exec_code.size()-1,exec_code.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,6 +1127,8 @@ void nasal_codegen::return_gen(nasal_ast& ast)
|
||||||
{
|
{
|
||||||
if(ast.get_children().size())
|
if(ast.get_children().size())
|
||||||
calculation_gen(ast.get_children()[0]);
|
calculation_gen(ast.get_children()[0]);
|
||||||
|
else
|
||||||
|
nil_gen();
|
||||||
opcode op;
|
opcode op;
|
||||||
op.op=op_return;
|
op.op=op_return;
|
||||||
exec_code.push_back(op);
|
exec_code.push_back(op);
|
||||||
|
|
Loading…
Reference in New Issue