diff --git a/main.cpp b/main.cpp index 2ce3eba..170dfb0 100644 --- a/main.cpp +++ b/main.cpp @@ -10,15 +10,15 @@ nasal_vm vm; void help() { std::cout - <<">> [\"file\"] input a file name. \n" - <<">> [help ] show help. \n" - <<">> [clear ] clear the screen. \n" - <<">> [lex ] use lexer to turn code into tokens. \n" - <<">> [ast ] do parsing and check the abstract syntax tree.\n" - <<">> [code ] show byte code. \n" - <<">> [exec ] execute program on bytecode vm. \n" - <<">> [logo ] print logo of nasal . \n" - <<">> [exit ] quit nasal interpreter. \n"; + <<">> [\"file\"] input file name. \n" + <<">> [help ] show help. \n" + <<">> [clear ] clear the screen. \n" + <<">> [lex ] view tokens. \n" + <<">> [ast ] view abstract syntax tree. \n" + <<">> [code ] view byte code. \n" + <<">> [exec ] execute program on bytecode vm. \n" + <<">> [logo ] print logo of nasal . \n" + <<">> [exit ] quit nasal interpreter. \n"; return; } @@ -39,16 +39,6 @@ void die(std::string stage,std::string filename) return; } -void clear() -{ - // this will clear the data in lexer/parser/import modules - // to reduce memory footprint - lexer.get_token_list().clear(); - parse.get_root().clear(); - import.get_root().clear(); - return; -} - void execute(std::string& command) { lexer.openfile(file); @@ -61,7 +51,6 @@ void execute(std::string& command) if(command=="lex") { lexer.print_token(); - clear(); return; } parse.set_toklist(lexer.get_token_list()); @@ -74,7 +63,6 @@ void execute(std::string& command) if(command=="ast") { parse.get_root().print_ast(0); - clear(); return; } import.link(parse.get_root()); @@ -84,7 +72,11 @@ void execute(std::string& command) return; } codegen.main_progress(import.get_root()); - clear(); + if(codegen.get_error()) + { + die("codegen",file); + return; + } if(command=="code") { codegen.print_byte_code(); diff --git a/nasal_codegen.h b/nasal_codegen.h index 0404243..e1a31ae 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -4,7 +4,6 @@ enum op_code { op_nop, - op_load,// load value in value_stack to identifier op_loadg, op_loadl, op_pnum, @@ -43,13 +42,12 @@ enum op_code op_jmp, // jump with no condition op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP op_jf, // used in conditional/loop,jmp when condition is false and POP STACK - op_counter, // add counter for forindex/foreach + op_cnt, // add counter for forindex/foreach op_cntpop, // pop counter op_findex, // index counter on the top of forindex_stack plus 1 op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector - op_call, // call identifier - op_callg, - op_calll, + op_callg, // call value in global scope + op_calll, // call value in local scope op_callv, // call vec[index] op_callvi, // call vec[immediate] (used in multi-assign/multi-define) op_callh, // call hash.label @@ -59,11 +57,10 @@ enum op_code op_slcend, // end of slice op_slc, // slice like vec[1] op_slc2, // slice like vec[nil:10] - op_mcall, // get memory of identifier - op_mcallg, - op_mcalll, - op_mcallv, // get memory of vec[index] - op_mcallh, // get memory of hash.label + op_mcallg, // get memory space of value in global scope + op_mcalll, // get memory space of value in local scope + op_mcallv, // get memory space of vec[index] + op_mcallh, // get memory space of hash.label op_ret // return }; @@ -74,7 +71,6 @@ struct }code_table[]= { {op_nop, "nop "}, - {op_load, "load "}, {op_loadg, "loadg "}, {op_loadl, "loadl "}, {op_pnum, "pnum "}, @@ -113,11 +109,10 @@ struct {op_jmp, "jmp "}, {op_jt, "jt "}, {op_jf, "jf "}, - {op_counter, "cnt "}, + {op_cnt, "cnt "}, {op_cntpop, "cntpop"}, {op_findex, "findx "}, {op_feach, "feach "}, - {op_call, "call "}, {op_callg, "callg "}, {op_calll, "calll "}, {op_callv, "callv "}, @@ -129,7 +124,6 @@ struct {op_slcend, "slcend"}, {op_slc, "slc "}, {op_slc2, "slc2 "}, - {op_mcall, "mcall "}, {op_mcallg, "mcallg"}, {op_mcalll, "mcalll"}, {op_mcallv, "mcallv"}, @@ -172,10 +166,12 @@ private: std::vector global; std::list > local; + void die(std::string,int); void regist_number(double); void regist_string(std::string&); - void add_sym(std::string&); - bool find_sym(std::string&); + void add_sym(std::string); + bool local_find(std::string&); + bool global_find(std::string&); void gen(unsigned char,unsigned int); void pop_gen(); void nil_gen(); @@ -212,6 +208,7 @@ private: void ret_gen(nasal_ast&); public: nasal_codegen(); + int get_error(); void main_progress(nasal_ast&); void print_op(int); void print_byte_code(); @@ -228,10 +225,17 @@ nasal_codegen::nasal_codegen() return; } +void nasal_codegen::die(std::string info,int line) +{ + ++error; + std::cout<<">> [code] line "<size();++j) + if((*i)[j]==name) + return; + regist_string(name); + local.front().push_back(name); + } return; } -bool nasal_codegen::find_sym(std::string&) +bool nasal_codegen::local_find(std::string& name) { + for(auto i=local.begin();i!=local.end();++i) + for(int j=0;jsize();++j) + if((*i)[j]==name) + return true; + return false; +} +bool nasal_codegen::global_find(std::string& name) +{ + for(int i=0;i new_scope; + local.push_front(new_scope); // symbol table push front + + // add special keyword 'me' into symbol table + // this symbol is only used in local scope(function's scope) + // this keyword is set to nil as default value + // after calling a hash, this keyword is set to this hash + add_sym("me"); + nasal_ast& ref_arg=ast.get_children()[0]; int arg_size=ref_arg.get_children().size(); for(int i=0;i new_scope; - local.push_front(new_scope); block_gen(block); - local.pop_front(); + local.pop_front(); // symbol table pop front + if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return) { nil_gen(); @@ -404,7 +440,12 @@ void nasal_codegen::call_id(nasal_ast& ast) gen(op_callb,i); return; } - gen(op_call,string_table[str]); + if(local_find(str)) + gen(op_calll,string_table[str]); + else if(global_find(str)) + gen(op_callg,string_table[str]); + else + die("cannot find symbol named \""+str+"\".",ast.get_line()); return; } @@ -479,7 +520,12 @@ void nasal_codegen::mcall_id(nasal_ast& ast) { std::string str=ast.get_str(); regist_string(str); - gen(op_mcall,string_table[str]); + if(local_find(str)) + gen(op_mcalll,string_table[str]); + else if(global_find(str)) + gen(op_mcallg,string_table[str]); + else + die("cannot find symbol named \""+str+"\".",ast.get_line()); return; } @@ -500,10 +546,10 @@ void nasal_codegen::mcall_hash(nasal_ast& ast) void nasal_codegen::single_def(nasal_ast& ast) { - calc_gen(ast.get_children()[1]); std::string str=ast.get_children()[0].get_str(); - regist_string(str); - gen(op_load,string_table[str]); + add_sym(str); + calc_gen(ast.get_children()[1]); + gen(local.empty()?op_loadg:op_loadl,string_table[str]); return; } void nasal_codegen::multi_def(nasal_ast& ast) @@ -513,10 +559,10 @@ void nasal_codegen::multi_def(nasal_ast& ast) { for(int i=0;i& nasal_codegen::get_exec_code() return exec_code; } +int nasal_codegen::get_error() +{ + return error; +} + #endif \ No newline at end of file diff --git a/nasal_gc.h b/nasal_gc.h index 6f8c5bc..a793e4e 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -333,13 +333,13 @@ struct nasal_gc nasal_val* one_addr; // reserved address of nasal_val,type vm_num, 1 nasal_val* nil_addr; // reserved address of nasal_val,type vm_nil nasal_val* global; // global scope address,type vm_scop - nasal_val** val_stack; // main stack + nasal_val* val_stack[STACK_MAX_DEPTH]; nasal_val** stack_top; // stack top std::vector num_addrs; // reserved address for const vm_num std::vector local; // local scope for function block std::vector slice_stack; // slice stack for vec[val,val,val:val] std::vector memory; // gc memory - std::queue free_list; // gc free list + std::queue free_list; // gc free list void mark(); void sweep(); void gc_init(std::vector&); @@ -430,7 +430,6 @@ void nasal_gc::gc_init(std::vector& nums) memory.push_back(tmp); free_list.push(tmp); } - val_stack=new nasal_val*[STACK_MAX_DEPTH]; // init runtime stack stack_top=val_stack; // set stack_top to val_stack zero_addr=new nasal_val(vm_num); // init constant 0 @@ -470,7 +469,6 @@ void nasal_gc::gc_clear() while(!free_list.empty()) free_list.pop(); global=nullptr; - delete []val_stack; local.clear(); slice_stack.clear(); return; diff --git a/nasal_vm.h b/nasal_vm.h index 5ac4ccf..a5e6c26 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -20,7 +20,6 @@ private: void die(std::string); bool condition(nasal_val*); void opr_nop(); - void opr_load(); void opr_loadg(); void opr_loadl(); void opr_pnum(); @@ -63,7 +62,6 @@ private: void opr_cntpop(); void opr_findex(); void opr_feach(); - void opr_call(); void opr_callg(); void opr_calll(); void opr_callv(); @@ -75,7 +73,6 @@ private: void opr_slcend(); void opr_slc(); void opr_slc2(); - void opr_mcall(); void opr_mcallg(); void opr_mcalll(); void opr_mcallv(); @@ -153,12 +150,6 @@ void nasal_vm::opr_nop() loop_mark=false; return; } -void nasal_vm::opr_load() -{ - nasal_val* val=*stack_top--; - (gc.local.empty()?gc.global:gc.local.back())->ptr.scop->elems[exec_code[pc].num]=val; - return; -} void nasal_vm::opr_loadg() { gc.global->ptr.scop->elems[exec_code[pc].num]=*stack_top--; @@ -214,6 +205,7 @@ void nasal_vm::opr_newf() val->ptr.func->entry=exec_code[pc].num; if(!gc.local.empty()) val->ptr.func->closure=gc.local.back()->ptr.scop->elems; + val->ptr.func->closure[me]=gc.nil_addr; *(++stack_top)=val; return; } @@ -561,26 +553,6 @@ void nasal_vm::opr_feach() *(++stack_top)=res; return; } -void nasal_vm::opr_call() -{ - nasal_val* val=nullptr; - int name_index=exec_code[pc].num; - if(!gc.local.empty()) - val=gc.local.back()->ptr.scop->get_val(name_index); - if(val) - { - *(++stack_top)=val; - return; - } - val=gc.global->ptr.scop->get_val(name_index); - if(val) - { - *(++stack_top)=val; - return; - } - die("call: cannot find symbol named \""+str_table[name_index]+"\""); - return; -} void nasal_vm::opr_callg() { *(++stack_top)=gc.global->ptr.scop->elems[exec_code[pc].num]; @@ -826,26 +798,6 @@ void nasal_vm::opr_slc2() aim.push_back(ref[i]); return; } -void nasal_vm::opr_mcall() -{ - nasal_val** mem_addr=nullptr; - int name_index=exec_code[pc].num; - if(!gc.local.empty()) - mem_addr=gc.local.back()->ptr.scop->get_mem(name_index); - if(mem_addr) - { - addr_stack.push(mem_addr); - return; - } - mem_addr=gc.global->ptr.scop->get_mem(name_index); - if(mem_addr) - { - addr_stack.push(mem_addr); - return; - } - die("mcall: cannot find symbol named \""+str_table[name_index]+"\""); - return; -} void nasal_vm::opr_mcallg() { addr_stack.push(&gc.global->ptr.scop->elems[exec_code[pc].num]); @@ -938,7 +890,6 @@ void nasal_vm::run() static void (nasal_vm::*opr_table[])()= { &nasal_vm::opr_nop, - &nasal_vm::opr_load, &nasal_vm::opr_loadg, &nasal_vm::opr_loadl, &nasal_vm::opr_pnum, @@ -981,7 +932,6 @@ void nasal_vm::run() &nasal_vm::opr_cntpop, &nasal_vm::opr_findex, &nasal_vm::opr_feach, - &nasal_vm::opr_call, &nasal_vm::opr_callg, &nasal_vm::opr_calll, &nasal_vm::opr_callv, @@ -993,7 +943,6 @@ void nasal_vm::run() &nasal_vm::opr_slcend, &nasal_vm::opr_slc, &nasal_vm::opr_slc2, - &nasal_vm::opr_mcall, &nasal_vm::opr_mcallg, &nasal_vm::opr_mcalll, &nasal_vm::opr_mcallv, diff --git a/test/ai.nas b/test/ai.nas index d3ff325..f66bc8f 100644 --- a/test/ai.nas +++ b/test/ai.nas @@ -81,13 +81,12 @@ var matrix= var prt_s='[\n'; foreach(var i;mat.mat) { - var s='['; + prt_s~='['; foreach(var j;i) - s~=(j~','); - s~='],\n'; - prt_s~=s; + prt_s~=(j~','); + prt_s~='],\n'; } - prt_s~=']'; + prt_s~=']\n'; print(prt_s); return nil; }, @@ -295,9 +294,9 @@ var bp= var hidden_diff=matrix.mult_mat(); matrix.prt_mat(hidden_diff); - output_layer=matrix.add_mat(output_layer,output_diff); + me.output_layer=matrix.add_mat(me.output_layer,output_diff); var error=0; - foreach(var i;tmp.mat[0]) + foreach(var i;me.result.mat[0]) error+=i; error*=0.5; return error; diff --git a/test/call_ide.nas b/test/call_ide.nas deleted file mode 100644 index 4d593bb..0000000 --- a/test/call_ide.nas +++ /dev/null @@ -1,30 +0,0 @@ -id[0] and id[1]; -1 or 2; -"str" ==1; -1*1/1+1; -2*3*4/1-2+3; -1-1+20-2*10; -1+s1*(s2+s3[0])-1; -var e=1+s1*(s2+s3[0])-1; -id; -"str"; -id(id); -id("str",1,1); -var e=1; -var x=10*2-20; -var id; -var id=[1,2,3,4]; -var id={id:"str"}; -id(); -id.id(); -id.id.id(); -id[0].id.id(id,"str",1,2,3,4).id[10]; -id(0)[1].id; -var hash={ - h:"hello", - parent:[id], -}; -function_test([1,2,3,4,55],1,2,3,{str:"str"}); -var (i,j,k,l,m,n) =[1,2,3,4,5,6]; -(var i,j,k)=[1,2,3]; -e=e[1:][0]; \ No newline at end of file diff --git a/test/choice.nas b/test/choice.nas index 2f9dcec..6de525d 100644 --- a/test/choice.nas +++ b/test/choice.nas @@ -1,4 +1,4 @@ - +import("lib.nas"); var condition_true=1; var condition_false=0; if(condition_true) diff --git a/test/json.nas b/test/json.nas index 8ed0a33..39f5686 100644 --- a/test/json.nas +++ b/test/json.nas @@ -1,4 +1,5 @@ #lib json.nas +import("lib.nas"); var json={ text:'', line:1, diff --git a/test/leetcode1319.nas b/test/leetcode1319.nas index a1e64e4..b34890f 100644 --- a/test/leetcode1319.nas +++ b/test/leetcode1319.nas @@ -29,4 +29,4 @@ var makeConnect=func(n,connections) return cnt; } -print(makeConnect(n,input)); \ No newline at end of file +println(makeConnect(n,input)); \ No newline at end of file diff --git a/test/nasal_test.nas b/test/nasal_test.nas index 3959aa9..4166e8f 100644 --- a/test/nasal_test.nas +++ b/test/nasal_test.nas @@ -1,10 +1,10 @@ -#//This is written for Nasal Intepreter -#//Sidi Liang - +# This is written for Nasal Intepreter +# Sidi Liang +import("lib.nas"); var w = 1; var x = "hello"; var f = func(){ - print("f is called"); + println("f is called"); } var f2 = func(){ return 2; @@ -28,71 +28,27 @@ var z1 = { hashh:z }; var y2 = [w, x, y, z1]; - var z2 = { hashh: z1, listt2: y2, }; -print(w);#//1 -print("\n"); -print(x);#//hello -print("\n"); -print(y);#//Empty -print("\n"); -print(z);#//Empty -print("\n"); -print(z1);#//Empty -print("\n"); -print(y2);#//Empty -print("\n"); -print(y[0]);#//1 -print("\n"); -print(y1[2][1]);#//hello -print("\n"); -print(z.numb);#//1 -print("\n"); -print(z.listt[2][1]);#//hello -print("\n"); -print(z1.hashh.listt[2][1]);#//hello -print("\n"); -print(y2[3].hashh.listt[2][1]);#//hello -print("\n"); -print(f);#//Empty -print("\n"); +println(w);#//1 +println(x);#//hello +println(y);#//[1,hello] +println(z);#//{...} +println(z1);#//{...} +println(y2);#//[...] +println(y[0]);#//1 +println(y1[2][1]);#//hello +println(z.numb);#//1 +println(z.listt[2][1]);#//hello +println(z1.hashh.listt[2][1]);#//hello +println(y2[3].hashh.listt[2][1]);#//hello +println(f);#//func(...){...} f();#//f is called -print("\n"); -print(z.funcc);#//Empty -print("\n"); +println(z.funcc);#//func(...){...} z.funcc();#//f is called -print("\n"); -print(z.funcccall);#//Empty -print("\n"); -z.funcccall();#//f is called -print("\n"); +println(z.funcccall);#//nil z2.listt2[3].hashh.funcc();#//f is called -print("\n"); -print(y1[f2()][w]);#//hello -print("\n"); -#//print(z.f3()); Error -call(f);#//f is called -print("\n"); -call(z.funcc);#//f is called -print("\n"); - - - - - - - - - - - - - - - - - +println(y1[f2()][w]);#//hello \ No newline at end of file diff --git a/test/neo4j.nas b/test/neo4j.nas index 91e7faa..da44c4a 100644 --- a/test/neo4j.nas +++ b/test/neo4j.nas @@ -1,12 +1,12 @@ import("lib.nas"); rand(time(0)); -var chartable=split('','abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'); +var chartable='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; var node=func(type) { var s=""; for(var i=0;i<10;i+=1) - s~=chartable[rand()*62]; + s~=chr(chartable[rand()*62]); return {name:s,type:type,next:[]}; } var film_node=[]; diff --git a/test/quick_sort.nas b/test/quick_sort.nas index 9bc78e7..92c4dd7 100644 --- a/test/quick_sort.nas +++ b/test/quick_sort.nas @@ -26,7 +26,7 @@ var sort=func(vec,left,right) return nil; } var vec=[]; -for(var i=0;i<500;i+=1) +for(var i=0;i<200;i+=1) append(vec,int(rand()*1000)); sort(vec,0,size(vec)-1); println(vec); \ No newline at end of file diff --git a/test/scalar.nas b/test/scalar.nas index d758541..7cccca2 100644 --- a/test/scalar.nas +++ b/test/scalar.nas @@ -115,7 +115,7 @@ var multi_assign_2=[10,9,8,7]; ((-1*2+9))/7-1; ((({num:2})))["num"]*2*2*2; ((((([0,1,2])[0:2]))[0:2]))[1]-1; -(((((((((((((((((((1+1+2+3+5)+8))+13)))+21))))+34)))))+55))))*89; +println((((((((((((((((((((1+1+2+3+5)+8))+13)))+21))))+34)))))+55))))*89); # 12727 number_1*(number_2+number_3)/90-number_4; (func test_func)()-1; hash_3.member_3+(func {return {what:"i don't tell you.",case_small:80,case_large:100}})()["case_large"]/10; @@ -129,7 +129,7 @@ nil and 1+7*8; var hash={str:'hello',f:func{return me.str;}}; var tmp_f=hash.f; hash=1; -print(tmp_f()); +println(tmp_f()); # undefined symbol 'me' # this means that # when generating local_scope for function f, @@ -138,13 +138,13 @@ print(tmp_f()); var h1={str:'hello',f:func{return me.str;}}; var h2={str:'world',f:func{return nil;}}; h2.f=h1.f; -print(h2.f()); +println(h2.f()); # print 'world' # this means that 'me' in hash's functions # only points to the hash this function belongs to -var f1=func(){print(1);return 1;} -var f2=func(){print(2);return 0;} +var f1=func(){println(1);return 1;} +var f2=func(){println(2);return 0;} f1() or f2(); # print '1' # this means that when using 'or' or 'and', diff --git a/test/special.nas b/test/special.nas deleted file mode 100644 index f581ac2..0000000 --- a/test/special.nas +++ /dev/null @@ -1,24 +0,0 @@ -var hash={str:'hello',f:func{return me.str;}}; -var tmp_f=hash.f; -hash=1; -print(tmp_f()); -# undefined symbol 'me' -# this means that -# when generating local_scope for function f, -# nasal_gc will not count 'me' as one reference of this hash - -var h1={str:'hello',f:func{return me.str;}}; -var h2={str:'world',f:func{return nil;}}; -h2.f=h1.f; -print(h2.f()); -# print 'world' -# this means that 'me' in hash's functions -# only points to the hash this function belongs to - -var f1=func(){print(1);return 1;} -var f2=func(){print(2);return 0;} -f1() or f2(); -# print '1' -# this means that when using 'or' or 'and', -# if the result is clear when calculating, -# objects behind will not be calculated \ No newline at end of file