From 368b057a91be2e71483bbf6e14523eb4a86c7316 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 12 Feb 2023 15:22:05 +0800 Subject: [PATCH] :rocket: add binary negation --- doc/nasal.ebnf | 2 +- makefile | 4 ++-- nasal_ast.h | 8 +++++--- nasal_codegen.h | 12 +++++++++--- nasal_dbg.h | 9 ++++++--- nasal_lexer.h | 10 ++++++++-- nasal_parse.h | 37 ++++++++++++++++++++----------------- nasal_vm.h | 18 +++++++++++++----- test/scalar.nas | 9 ++++++++- 9 files changed, 72 insertions(+), 37 deletions(-) diff --git a/doc/nasal.ebnf b/doc/nasal.ebnf index 339039c..c1a2334 100644 --- a/doc/nasal.ebnf +++ b/doc/nasal.ebnf @@ -60,7 +60,7 @@ multive_expr::= (unary|scalar) ('*' | '/') (unary|scalar) ; unary::= - ('-'|'!') (unary|scalar) + ('-'|'!'|'~') (unary|scalar) ; scalar::= function {call_scalar} diff --git a/makefile b/makefile index 74f998e..884fbc6 100644 --- a/makefile +++ b/makefile @@ -42,7 +42,7 @@ test:nasal @ ./nasal -d test/calc.nas @ ./nasal -e test/choice.nas @ ./nasal -e test/class.nas - @ ./nasal -t -d test/console3D.nas 50 + @ ./nasal -t -d test/console3D.nas 25 @ ./nasal -e test/coroutine.nas @ ./nasal -t -d test/datalog.nas @ ./nasal -e test/diff.nas @@ -63,7 +63,7 @@ test:nasal @ ./nasal -t -d test/md5compare.nas -@ ./nasal -d test/module_test.nas @ ./nasal -e test/nasal_test.nas - @ ./nasal test/occupation.nas 10 + @ ./nasal test/occupation.nas 5 @ ./nasal -t -d test/pi.nas @ ./nasal -c test/ppmgen.nas @ ./nasal -t -d test/prime.nas diff --git a/nasal_ast.h b/nasal_ast.h index 69f00f4..e82e16f 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -46,8 +46,9 @@ enum ast_node:u32 { ast_mult, // * ast_div, // / ast_link, // ~ - ast_neg, // - - ast_not, // ~ + ast_neg, // unary - + ast_not, // unary ! + ast_negate, // unary ~ ast_trino, // ?: ast_for, // for keyword ast_forindex, // forindex keyword @@ -109,7 +110,8 @@ const char* ast_name[]={ "DivExpression", "LinkExpression", "NegativeExpression", - "NotExpression", + "LogicalNegationExpression", + "BinaryNegationExpression", "TrinocularExpression", "ForLoop", "ForindexLoop", diff --git a/nasal_codegen.h b/nasal_codegen.h index 4cf5a9e..25413f0 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -25,8 +25,9 @@ enum op_code_type:u8 { op_para, // normal parameter op_deft, // default parameter op_dyn, // dynamic parameter - op_unot, // ! + op_lnot, // ! logical negation op_usub, // - + op_bnot, // ~ binary negation static_cast op_add, // + op_sub, // - op_mul, // * @@ -91,7 +92,8 @@ const char* opname[]={ "loadl ","loadu ","pnum ","pnil ", "pstr ","newv ","newh ","newf ", "happ ","para ","def ","dyn ", - "not ","usub ","add ","sub ", + "lnot ","usub ","bnot ","add ", + "sub ", "mult ","div ","lnk ","addc ", "subc ","multc ","divc ","lnkc ", "addeq ","subeq ","muleq ","diveq ", @@ -1112,7 +1114,11 @@ void codegen::calc_gen(const ast& node) { break; case ast_not: calc_gen(node[0]); - gen(op_unot,0,node.line()); + gen(op_lnot,0,node.line()); + break; + case ast_negate: + calc_gen(node[0]); + gen(op_bnot,0,node.line()); break; case ast_def: single_def(node); diff --git a/nasal_dbg.h b/nasal_dbg.h index dc6e492..f927823 100644 --- a/nasal_dbg.h +++ b/nasal_dbg.h @@ -206,7 +206,8 @@ void debugger::run( &&loadl, &&loadu, &&pnum, &&pnil, &&pstr, &&newv, &&newh, &&newf, &&happ, &¶, &&deft, &&dyn, - &&unot, &&usub, &&add, &&sub, + &&lnot, &&usub, &&bnot, &&add, + &&sub, &&mul, &&div, &&lnk, &&addc, &&subc, &&mulc, &&divc, &&lnkc, &&addeq, &&subeq, &&muleq, &&diveq, @@ -240,7 +241,8 @@ void debugger::run( &debugger::o_newh, &debugger::o_newf, &debugger::o_happ, &debugger::o_para, &debugger::o_deft, &debugger::o_dyn, - &debugger::o_unot, &debugger::o_usub, + &debugger::o_lnot, &debugger::o_usub, + &debugger::o_bnot, &debugger::o_add, &debugger::o_sub, &debugger::o_mul, &debugger::o_div, &debugger::o_lnk, &debugger::o_addc, @@ -320,8 +322,9 @@ happ: dbg(o_happ ,op_happ ); para: dbg(o_para ,op_para ); deft: dbg(o_deft ,op_deft ); dyn: dbg(o_dyn ,op_dyn ); -unot: dbg(o_unot ,op_unot ); +lnot: dbg(o_lnot ,op_lnot ); usub: dbg(o_usub ,op_usub ); +bnot: dbg(o_bnot ,op_bnot ); add: dbg(o_add ,op_add ); sub: dbg(o_sub ,op_sub ); mul: dbg(o_mul ,op_mul ); diff --git a/nasal_lexer.h b/nasal_lexer.h index ddcc3a9..ff62257 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -51,7 +51,10 @@ enum class tok:u32 { sub, // operator - mult, // operator * div, // operator / - link, // operator ~ + floater, // operator ~ and binary operator ~ + biand, // binary operator & + bior, // binary operator | + bixor, // binary operator ^ opnot, // operator ! eq, // operator = addeq, // operator += @@ -123,7 +126,10 @@ private: {"-" ,tok::sub }, {"*" ,tok::mult }, {"/" ,tok::div }, - {"~" ,tok::link }, + {"~" ,tok::floater }, + {"&" ,tok::biand }, + {"|" ,tok::bior }, + {"^" ,tok::bixor }, {"!" ,tok::opnot }, {"=" ,tok::eq }, {"+=" ,tok::addeq }, diff --git a/nasal_parse.h b/nasal_parse.h index abbca3a..e3c08c6 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -54,7 +54,7 @@ private: ast root; error& err; std::unordered_map tokname { - {tok::rfor ,"for" }, + {tok::rfor ,"for" }, {tok::forindex,"forindex"}, {tok::foreach ,"foreach" }, {tok::rwhile ,"while" }, @@ -85,7 +85,10 @@ private: {tok::sub ,"-" }, {tok::mult ,"*" }, {tok::div ,"/" }, - {tok::link ,"~" }, + {tok::floater ,"~" }, + {tok::biand ,"&" }, + {tok::bior ,"|" }, + {tok::bixor ,"^" }, {tok::opnot ,"!" }, {tok::eq ,"=" }, {tok::addeq ,"+=" }, @@ -356,7 +359,7 @@ ast parse::vec() { const tok panic[]={ tok::id,tok::str,tok::num,tok::tktrue, tok::tkfalse,tok::opnot,tok::sub,tok::tknil, - tok::func,tok::var,tok::lcurve, + tok::func,tok::var,tok::lcurve,tok::floater, tok::lbrace,tok::lbracket,tok::null }; ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_vec,toks[ptr].file); @@ -585,12 +588,12 @@ ast parse::cmp_expr() { ast parse::additive_expr() { ast node=multive_expr(); - while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::link)) { + while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::floater)) { ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file); switch(toks[ptr].type) { - case tok::add: tmp.set_type(ast_add); break; - case tok::sub: tmp.set_type(ast_sub); break; - case tok::link: tmp.set_type(ast_link); break; + case tok::add: tmp.set_type(ast_add); break; + case tok::sub: tmp.set_type(ast_sub); break; + case tok::floater: tmp.set_type(ast_link); break; default: break; } tmp.add(std::move(node)); @@ -602,12 +605,12 @@ ast parse::additive_expr() { } ast parse::multive_expr() { - ast node=(lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar(); + ast node=(lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar(); while(lookahead(tok::mult) || lookahead(tok::div)) { ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,(u32)toks[ptr].type-(u32)tok::mult+ast_mult,toks[ptr].file); tmp.add(std::move(node)); match(toks[ptr].type); - tmp.add((lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar()); + tmp.add((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar()); node=std::move(tmp); } return node; @@ -616,11 +619,12 @@ ast parse::multive_expr() { ast parse::unary() { ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_null,toks[ptr].file); switch(toks[ptr].type) { - case tok::sub: node.set_type(ast_neg);match(tok::sub);break; - case tok::opnot: node.set_type(ast_not);match(tok::opnot);break; + case tok::sub: node.set_type(ast_neg);match(tok::sub);break; + case tok::opnot: node.set_type(ast_not);match(tok::opnot);break; + case tok::floater: node.set_type(ast_negate);match(tok::floater);break; default: break; } - node.add((lookahead(tok::sub) || lookahead(tok::opnot))?unary():scalar()); + node.add((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar()); return node; } @@ -695,9 +699,8 @@ ast parse::callv() { const tok panic[]={ tok::id,tok::str,tok::num,tok::tktrue, tok::tkfalse,tok::opnot,tok::sub,tok::tknil, - tok::func,tok::var,tok::lcurve, - tok::lbrace,tok::lbracket,tok::colon, - tok::null + tok::func,tok::var,tok::lcurve,tok::floater, + tok::lbrace,tok::lbracket,tok::colon,tok::null }; ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_callv,toks[ptr].file); match(tok::lbracket); @@ -725,7 +728,7 @@ ast parse::callf() { const tok panic[]={ tok::id,tok::str,tok::num,tok::tktrue, tok::tkfalse,tok::opnot,tok::sub,tok::tknil, - tok::func,tok::var,tok::lcurve, + tok::func,tok::var,tok::lcurve,tok::floater, tok::lbrace,tok::lbracket,tok::null }; ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_callf,toks[ptr].file); @@ -816,7 +819,7 @@ ast parse::multi_scalar() { const tok panic[]={ tok::id,tok::str,tok::num,tok::tktrue, tok::tkfalse,tok::opnot,tok::sub,tok::tknil, - tok::func,tok::var,tok::lcurve, + tok::func,tok::var,tok::lcurve,tok::floater, tok::lbrace,tok::lbracket,tok::null }; ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_tuple,toks[ptr].file); diff --git a/nasal_vm.h b/nasal_vm.h index b365310..92bbe3d 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -67,8 +67,9 @@ protected: void o_para(); void o_deft(); void o_dyn(); - void o_unot(); + void o_lnot(); void o_usub(); + void o_bnot(); void o_add(); void o_sub(); void o_mul(); @@ -436,7 +437,7 @@ void vm::o_dyn() { top[0].func().dpara=imm[pc]; } -void vm::o_unot() { +void vm::o_lnot() { var val=top[0]; switch(val.type) { case vm_nil:top[0]=one;break; @@ -460,6 +461,10 @@ void vm::o_usub() { top[0]=var::num(-top[0].tonum()); } +void vm::o_bnot() { + top[0]=var::num(~static_cast(top[0].num())); +} + #define op_calc(type)\ top[-1]=var::num(top[-1].tonum() type top[0].tonum());\ --top; @@ -1001,7 +1006,8 @@ void vm::run( &&loadl, &&loadu, &&pnum, &&pnil, &&pstr, &&newv, &&newh, &&newf, &&happ, &¶, &&deft, &&dyn, - &&unot, &&usub, &&add, &&sub, + &&lnot, &&usub, &&bnot, &&add, + &&sub, &&mul, &&div, &&lnk, &&addc, &&subc, &&mulc, &&divc, &&lnkc, &&addeq, &&subeq, &&muleq, &&diveq, @@ -1035,7 +1041,8 @@ void vm::run( &vm::o_newh, &vm::o_newf, &vm::o_happ, &vm::o_para, &vm::o_deft, &vm::o_dyn, - &vm::o_unot, &vm::o_usub, + &vm::o_lnot, &vm::o_usub, + &vm::o_bnot, &vm::o_add, &vm::o_sub, &vm::o_mul, &vm::o_div, &vm::o_lnk, &vm::o_addc, @@ -1115,8 +1122,9 @@ happ: exec_nodie(o_happ ); // -1 para: exec_nodie(o_para ); // -0 deft: exec_nodie(o_deft ); // -1 dyn: exec_nodie(o_dyn ); // -0 -unot: exec_nodie(o_unot ); // -0 +lnot: exec_nodie(o_lnot ); // -0 usub: exec_nodie(o_usub ); // -0 +bnot: exec_nodie(o_bnot ); // -0 add: exec_nodie(o_add ); // -1 sub: exec_nodie(o_sub ); // -1 mul: exec_nodie(o_mul ); // -1 diff --git a/test/scalar.nas b/test/scalar.nas index ec6a0d3..95e461d 100644 --- a/test/scalar.nas +++ b/test/scalar.nas @@ -204,4 +204,11 @@ foreach(i;a){ println(runtime.argv()); func(a,b,c,d="只有红茶可以吗"){ println(a,' ',b,' ',c,' ',d,' true: ',true,' false: ',false); -}(c:1919810,b:514,a:114); \ No newline at end of file +}(c:1919810,b:514,a:114); + +# test binary negation +println("~ 0x80: ",~0x80); +println("~ 0x8000: ",~0x8000); +println("~ 0x80000000: ",~0x80000000); +println("~ 0x8000000000000000: ",~0x8000000000000000); +println(~0x80000000==~0x8000000000000000); \ No newline at end of file