From fce34c12b32a3e45481f34af993c829ce0b18eac Mon Sep 17 00:00:00 2001 From: Valk Richard Li <48872266+ValKmjolnir@users.noreply.github.com> Date: Sun, 29 Nov 2020 00:54:54 +0800 Subject: [PATCH] update --- main.cpp | 31 +++++ nasal_codegen.h | 319 +++++++++++++++++++++++++++++++++++++++++++++++- nasal_gc.h | 4 +- nasal_parse.h | 18 +++ nasal_runtime.h | 66 ++-------- 5 files changed, 377 insertions(+), 61 deletions(-) diff --git a/main.cpp b/main.cpp index 0ce9866..acd5da3 100644 --- a/main.cpp +++ b/main.cpp @@ -16,6 +16,7 @@ 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<<">> [logo ] print logo of nasal .\n"; std::cout<<">> [exit ] quit nasal interpreter.\n"; return; @@ -78,6 +79,7 @@ void ast_print() parse.get_root().print_ast(0); return; } + void runtime_start() { lexer.openfile(inputfile); @@ -105,6 +107,33 @@ void runtime_start() 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()); + code_generator.print_byte_code(); + return; +} + int main() { std::string command; @@ -154,6 +183,8 @@ int main() ast_print(); else if(command=="run") runtime_start(); + else if(command=="exec") + execute(); else if(command=="logo") logo(); else if(command=="exit") diff --git a/nasal_codegen.h b/nasal_codegen.h index 4ef4d1f..7dc4272 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -10,7 +10,7 @@ enum op_code op_pushstr, op_newvec,op_newhash,op_newfunc, op_vecappend,op_hashappend, - op_para,op_defaultpara,op_dynamicpara, + op_para,op_defaultpara,op_dynamicpara,op_funcbegin, op_unot,op_usub, op_add,op_sub,op_mul,op_div,op_lnk, op_eq,op_neq,op_less,op_leq,op_grt,op_geq, @@ -23,6 +23,60 @@ enum op_code op_end }; +struct +{ + int type; + const char* name; +}code_table[]= +{ + {op_nop, "nop "}, + {op_load, "load "}, + {op_pushnum, "pnum "}, + {op_pushone, "pone "}, + {op_pushzero, "pzero "}, + {op_pushnil, "pnil "}, + {op_pushstr, "pstr "}, + {op_newvec, "newv "}, + {op_newhash, "newh "}, + {op_newfunc, "newf "}, + {op_vecappend, "vapp "}, + {op_hashappend, "happ "}, + {op_para, "para "}, + {op_defaultpara, "deflt "}, + {op_dynamicpara, "dyn "}, + {op_funcbegin, "fbegin"}, + {op_unot, "not "}, + {op_usub, "usub "}, + {op_add, "add "}, + {op_sub, "sub "}, + {op_mul, "mult "}, + {op_div, "div "}, + {op_lnk, "link "}, + {op_eq, "eq "}, + {op_neq, "neq "}, + {op_less, "l "}, + {op_leq, "leq "}, + {op_grt, "g "}, + {op_geq, "geq "}, + {op_pop, "pop "}, + {op_jmp, "jmp "}, + {op_jmptrue, "jt "}, + {op_jmpfalse, "jf "}, + {op_gccall, "calli "}, + {op_gccallvec, "callv "}, + {op_gccallhash, "callh "}, + {op_gccallfunc, "callf "}, + {op_builtincall, "callb "}, + {op_slice, "slice "}, + {op_slice2, "slice2"}, + {op_memcall, "mcalli"}, + {op_memcallvec, "mcallv"}, + {op_memcallhash, "mcallh"}, + {op_return, "ret "}, + {op_end, "end "}, + {-1, NULL}, +}; + struct opcode { unsigned char op; @@ -46,14 +100,19 @@ private: void vector_gen(nasal_ast&); void hash_gen(nasal_ast&); void function_gen(nasal_ast&); + void call_gen(nasal_ast&); + void call_id(nasal_ast&); void definition_gen(nasal_ast&); void multi_assignment_gen(nasal_ast&); void conditional_gen(nasal_ast&); void loop_gen(nasal_ast&); void calculation_gen(nasal_ast&); + void block_gen(nasal_ast&); + void return_gen(nasal_ast&); public: nasal_codegen(); void main_progress(nasal_ast&); + void print_byte_code(); }; nasal_codegen::nasal_codegen() @@ -115,9 +174,10 @@ void nasal_codegen::vector_gen(nasal_ast& ast) for(int i=0;iright_range) { - std::cout<<">> [runtime] nasal_vector::get_value_address: index out of range.\n"; + std::cout<<">> [runtime] nasal_vector::get_value_address: index out of range: "<right_range) { - std::cout<<">> [runtime] nasal_vector::get_mem_address: index out of range.\n"; + std::cout<<">> [runtime] nasal_vector::get_mem_address: index out of range: "<1) + die(tmp_node.get_line(),"cannot get the memory in temporary sliced vector"); + else if(tmp_node.get_children()[0].get_type()==ast_subvec) + die(tmp_node.get_children()[0].get_line(),"cannot get the memory in temporary sliced vector"); + } + } + } // assignment nasal_ast tmp; tmp.set_line(tok_list[ptr].line); diff --git a/nasal_runtime.h b/nasal_runtime.h index 17046e4..5c483d4 100644 --- a/nasal_runtime.h +++ b/nasal_runtime.h @@ -569,12 +569,12 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco if(node.get_children()[i].get_type()==ast_subvec) { nasal_ast& subvec_node=node.get_children()[i]; - int begin_value_addr=calculation(subvec_node.get_children()[0],local_scope_addr); - int end_value_addr=calculation(subvec_node.get_children()[1],local_scope_addr); - int begin_value_type=nasal_vm.gc_get(begin_value_addr).get_type(); - int end_value_type=nasal_vm.gc_get(end_value_addr).get_type(); + int begin_value_addr=calculation(subvec_node.get_children()[0],local_scope_addr); + int end_value_addr=calculation(subvec_node.get_children()[1],local_scope_addr); + int begin_value_type=nasal_vm.gc_get(begin_value_addr).get_type(); + int end_value_type=nasal_vm.gc_get(end_value_addr).get_type(); bool begin_is_nil=true,end_is_nil=true; - int begin_index=0,end_index=0; + int begin_index=0,end_index=0; if(begin_value_type!=vm_nil && begin_value_type!=vm_number && begin_value_type!=vm_string) { die(subvec_node.get_children()[0].get_line(),"begin index must be nil/number/string"); @@ -589,11 +589,6 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco { std::string str=nasal_vm.gc_get(begin_value_addr).get_string(); double number=trans_string_to_number(str); - if(std::isnan(number)) - { - die(subvec_node.get_children()[0].get_line(),"begin index is not a numerable string"); - return -1; - } begin_index=(int)number; begin_is_nil=false; } @@ -607,11 +602,6 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco { std::string str=nasal_vm.gc_get(end_value_addr).get_string(); double number=trans_string_to_number(str); - if(std::isnan(number)) - { - die(subvec_node.get_children()[1].get_line(),"end index is not a numerable string"); - return -1; - } begin_index=(int)number; end_is_nil=false; } @@ -639,6 +629,12 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco die(subvec_node.get_children()[0].get_line(),"begin index is greater than end index"); return -1; } + int vsize=reference_value.size(); + if(begin_index<-vsize || begin_index>vsize-1 || end_index<-vsize || end_index>vsize-1) + { + die(node.get_children()[i].get_line(),"begin index or end index is out of range"); + return -1; + } for(int i=begin_index;i<=end_index;++i) called_value_addrs.push_back(reference_value.get_value_address(i)); nasal_vm.del_reference(begin_value_addr); @@ -658,11 +654,6 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco { std::string str=nasal_vm.gc_get(index_value_addr).get_string(); double number=trans_string_to_number(str); - if(std::isnan(number)) - { - die(node.get_children()[i].get_line(),"index is not a numerable string"); - return -1; - } index_num=(int)number; } else @@ -740,11 +731,6 @@ int nasal_runtime::call_vector(nasal_ast& node,int base_value_addr,int local_sco { std::string str=nasal_vm.gc_get(index_value_addr).get_string(); double number=trans_string_to_number(str); - if(std::isnan(number)) - { - die(tmp.get_line(),"index is not a numerable string"); - return -1; - } index_num=(int)number; } else @@ -1007,10 +993,6 @@ int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr) { case ast_call_vec: tmp_mem_addr=call_vector_mem(call_expr,mem_address,local_scope_addr);break; case ast_call_hash: tmp_mem_addr=call_hash_mem(call_expr,mem_address,local_scope_addr);break; - case ast_call_func: - die(call_expr.get_line(),"cannot change function returned value"); - return -1; - break; } mem_address=tmp_mem_addr; if(mem_address<0) @@ -1031,21 +1013,10 @@ int nasal_runtime::call_vector_mem(nasal_ast& node,int base_mem_addr,int local_s die(node.get_line(),"incorrect value type,must be vector/hash"); return -1; } - int call_size=node.get_children().size(); - if(call_size>1) - { - die(node.get_line(),"only one index/key is allowed to get memory space of vector/hash"); - return -1; - } if(base_value_type==vm_vector) { nasal_vector& reference_value=nasal_vm.gc_get(base_value_addr).get_vector(); nasal_ast& tmp=node.get_children()[0]; - if(tmp.get_type()==ast_subvec) - { - die(tmp.get_line(),"temporary sliced vector"); - return -1; - } int index_value_addr=calculation(tmp,local_scope_addr); int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); if(index_value_type!=vm_number && index_value_type!=vm_string) @@ -1058,11 +1029,6 @@ int nasal_runtime::call_vector_mem(nasal_ast& node,int base_mem_addr,int local_s { std::string str=nasal_vm.gc_get(index_value_addr).get_string(); double number=trans_string_to_number(str); - if(std::isnan(number)) - { - die(tmp.get_line(),"index is not a numerable string"); - return -1; - } index_num=(int)number; } else @@ -1072,17 +1038,7 @@ int nasal_runtime::call_vector_mem(nasal_ast& node,int base_mem_addr,int local_s } else { - if(call_size>1) - { - die(node.get_line(),"use only one key to call a hash"); - return -1; - } nasal_ast& tmp=node.get_children()[0]; - if(tmp.get_type()==ast_subvec) - { - die(tmp.get_line(),"cannot slice hash"); - return -1; - } int str_addr=calculation(tmp,local_scope_addr); if(str_addr<0 || nasal_vm.gc_get(str_addr).get_type()!=vm_string) {