diff --git a/nasal_bytecode_vm.h b/nasal_bytecode_vm.h index b8d98e8..acf2755 100644 --- a/nasal_bytecode_vm.h +++ b/nasal_bytecode_vm.h @@ -74,6 +74,7 @@ private: void opr_jmptrue(); void opr_jmpfalse(); void opr_counter(); + void opr_cntpop(); void opr_forindex(); void opr_foreach(); void opr_call(); @@ -438,15 +439,6 @@ void nasal_bytecode_vm::opr_eq() { nasal_scalar* val_addr2=*value_stack_top--; nasal_scalar* val_addr1=*value_stack_top--; - if(val_addr1==val_addr2) - { - nasal_scalar* new_value_address=vm.gc_alloc(vm_number); - new_value_address->set_number(1); - *(++value_stack_top)=new_value_address; - vm.del_reference(val_addr1); - vm.del_reference(val_addr2); - return; - } int a_ref_type=val_addr1->get_type(); int b_ref_type=val_addr2->get_type(); if(a_ref_type==vm_nil && b_ref_type==vm_nil) @@ -481,7 +473,7 @@ void nasal_bytecode_vm::opr_eq() else { nasal_scalar* new_value_address=vm.gc_alloc(vm_number); - new_value_address->set_number(0); + new_value_address->set_number(val_addr1==val_addr2); *(++value_stack_top)=new_value_address; vm.del_reference(val_addr1); vm.del_reference(val_addr2); @@ -493,15 +485,6 @@ void nasal_bytecode_vm::opr_neq() { nasal_scalar* val_addr2=*value_stack_top--; nasal_scalar* val_addr1=*value_stack_top--; - if(val_addr1==val_addr2) - { - nasal_scalar* new_value_address=vm.gc_alloc(vm_number); - new_value_address->set_number(0); - *(++value_stack_top)=new_value_address; - vm.del_reference(val_addr1); - vm.del_reference(val_addr2); - return; - } int a_ref_type=val_addr1->get_type(); int b_ref_type=val_addr2->get_type(); if(a_ref_type==vm_nil && b_ref_type==vm_nil) @@ -536,7 +519,7 @@ void nasal_bytecode_vm::opr_neq() else { nasal_scalar* new_value_address=vm.gc_alloc(vm_number); - new_value_address->set_number(1); + new_value_address->set_number(val_addr1!=val_addr2); *(++value_stack_top)=new_value_address; vm.del_reference(val_addr1); vm.del_reference(val_addr2); @@ -674,14 +657,17 @@ void nasal_bytecode_vm::opr_counter() counter_stack.push(-1); return; } +void nasal_bytecode_vm::opr_cntpop() +{ + counter_stack.pop(); + return; +} void nasal_bytecode_vm::opr_forindex() { nasal_vector& ref=(*value_stack_top)->get_vector(); ++counter_stack.top(); if(counter_stack.top()>=ref.size()) { - vm.del_reference(*value_stack_top--); - counter_stack.pop(); ptr=exec_code[ptr].index-1; return; } @@ -696,8 +682,6 @@ void nasal_bytecode_vm::opr_foreach() ++counter_stack.top(); if(counter_stack.top()>=ref.size()) { - vm.del_reference(*value_stack_top--); - counter_stack.pop(); ptr=exec_code[ptr].index-1; return; } @@ -799,6 +783,7 @@ void nasal_bytecode_vm::opr_callvi() die("callvi: multi-definition/multi-assignment must use a vector"); return; } + // cannot use operator[],because this may cause overflow nasal_scalar* res=val_addr->get_vector().get_value_address(exec_code[ptr].index); if(!res) { @@ -1175,6 +1160,7 @@ void nasal_bytecode_vm::run(std::vector& strs,std::vector& &nasal_bytecode_vm::opr_jmptrue, &nasal_bytecode_vm::opr_jmpfalse, &nasal_bytecode_vm::opr_counter, + &nasal_bytecode_vm::opr_cntpop, &nasal_bytecode_vm::opr_forindex, &nasal_bytecode_vm::opr_foreach, &nasal_bytecode_vm::opr_call, diff --git a/nasal_codegen.h b/nasal_codegen.h index 46ddd6b..1ba4361 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -22,6 +22,7 @@ enum op_code op_jmptrue, op_jmpfalse, op_counter, // add counter for forindex/foreach + op_cntpop, // pop counter op_forindex, // index counter on the top of forindex_stack plus 1 op_foreach, // index counter on the top of forindex_stack plus 1 and get the value in vector op_call, // call identifier @@ -86,6 +87,7 @@ struct {op_jmptrue, "jt "}, {op_jmpfalse, "jf "}, {op_counter, "cnt "}, + {op_cntpop, "cntpop"}, {op_forindex, "findx "}, {op_foreach, "feach "}, {op_call, "call "}, @@ -115,6 +117,12 @@ struct opcode index=0; return; } + opcode(unsigned char _op,unsigned int _index) + { + op=_op; + index=_index; + return; + } opcode& operator=(const opcode& tmp) { op=tmp.op; @@ -123,9 +131,6 @@ struct opcode } }; -// unfinished -// now it can output ast but it is not byte code yet -// please wait... class nasal_codegen { private: @@ -134,8 +139,8 @@ private: std::vector number_result_table; std::vector string_result_table; std::vector exec_code; - std::vector continue_ptr; - std::vector break_ptr; + std::list > continue_ptr; + std::list > break_ptr; int error; void regist_number(double); void regist_string(std::string); @@ -206,17 +211,14 @@ void nasal_codegen::regist_string(std::string str) void nasal_codegen::pop_gen() { - opcode op; - op.op=op_pop; - op.index=0; + opcode op(op_pop,0); exec_code.push_back(op); return; } void nasal_codegen::nil_gen() { - opcode op; - op.op=op_pushnil; + opcode op(op_pushnil,0); exec_code.push_back(op); return; } @@ -243,9 +245,7 @@ void nasal_codegen::string_gen(nasal_ast& ast) { std::string str=ast.get_str(); regist_string(str); - opcode op; - op.op=op_pushstr; - op.index=string_table[str]; + opcode op(op_pushstr,string_table[str]); exec_code.push_back(op); return; } @@ -253,16 +253,12 @@ void nasal_codegen::string_gen(nasal_ast& ast) void nasal_codegen::vector_gen(nasal_ast& ast) { int size=ast.get_children().size(); - opcode op; - op.op=op_newvec; - op.index=0; + opcode op(op_newvec,0); exec_code.push_back(op); for(int i=0;i new_continue_ptr; + std::vector new_break_ptr; + continue_ptr.push_front(new_continue_ptr); + break_ptr.push_front(new_break_ptr); block_gen(ast.get_children()[1]); op.op=op_jmp; op.index=loop_ptr; @@ -746,6 +708,10 @@ void nasal_codegen::for_gen(nasal_ast& ast) int label_exit=exec_code.size(); exec_code.push_back(op); pop_gen(); + std::vector new_continue_ptr; + std::vector new_break_ptr; + continue_ptr.push_front(new_continue_ptr); + break_ptr.push_front(new_break_ptr); block_gen(ast.get_children()[3]); int continue_place=exec_code.size(); switch(ast.get_children()[2].get_type()) @@ -797,13 +763,22 @@ void nasal_codegen::forindex_gen(nasal_ast& ast) op.op=op_meq; op.index=0; exec_code.push_back(op); + pop_gen(); } + std::vector new_continue_ptr; + std::vector new_break_ptr; + continue_ptr.push_front(new_continue_ptr); + break_ptr.push_front(new_break_ptr); block_gen(ast.get_children()[2]); op.op=op_jmp; op.index=ptr; exec_code.push_back(op); exec_code[ptr].index=exec_code.size(); load_continue_break(exec_code.size()-1,exec_code.size()); + pop_gen(); + op.op=op_cntpop; + op.index=0; + exec_code.push_back(op); return; } void nasal_codegen::foreach_gen(nasal_ast& ast) @@ -835,12 +810,20 @@ void nasal_codegen::foreach_gen(nasal_ast& ast) exec_code.push_back(op); pop_gen(); } + std::vector new_continue_ptr; + std::vector new_break_ptr; + continue_ptr.push_front(new_continue_ptr); + break_ptr.push_front(new_break_ptr); block_gen(ast.get_children()[2]); op.op=op_jmp; op.index=ptr; exec_code.push_back(op); exec_code[ptr].index=exec_code.size(); load_continue_break(exec_code.size()-1,exec_code.size()); + pop_gen(); + op.op=op_cntpop; + op.index=0; + exec_code.push_back(op); return; } @@ -1081,13 +1064,13 @@ void nasal_codegen::block_gen(nasal_ast& ast) case ast_continue: op.op=op_jmp; op.index=0; - continue_ptr.push_back(exec_code.size()); + continue_ptr.front().push_back(exec_code.size()); exec_code.push_back(op); break; case ast_break: op.op=op_jmp; op.index=0; - break_ptr.push_back(exec_code.size()); + break_ptr.front().push_back(exec_code.size()); exec_code.push_back(op); break; case ast_while: