diff --git a/README.md b/README.md index 0653075..5d11cb5 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,19 @@ Unary operators `-` `!` have the same function as C/C++. !0; ``` +Bitwise operators `~` `|` `&` `^` have the same function as C/C++. + +```javascript +# these operators will: +# 1. convert f64 to i32 (static_cast) +# 2. do the bitwise function + +~0x80000000; # not 2147483647 +0x8|0x1; # or +0x1&0x2; # and +0x8^0x1; # xor +``` + Operators `=` `+=` `-=` `*=` `/=` `~=` are used in assignment expressions. ```javascript diff --git a/doc/README_zh.md b/doc/README_zh.md index 5492025..4eabb01 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -199,13 +199,26 @@ Nasal拥有基本的四种数学运算符 `+` `-` `*` `/`以及一个特别的 1==0 or 1!=0; ``` -单目运算符`-` `!`与C/C++中的运算符功能类似. +单目运算符`-` `!`与C/C++中的运算符功能类似。 ```javascript -1; !0; ``` +位运算符`~` `|` `&` `^`与C/C++中的运算符功能类似。 + +```javascript +# 运行过程: +# 1. 将 f64 强转为 i32 (static_cast) +# 2. 执行位运算符 + +~0x80000000; # 按位取反 2147483647 +0x8|0x1; # 按位或 +0x1&0x2; # 按位与 +0x8^0x1; # 按位异或 +``` + 赋值运算符`=` `+=` `-=` `*=` `/=` `~=`正如其名,用于进行赋值。 ```javascript diff --git a/nasal_ast.h b/nasal_ast.h index fcc8812..e2447a6 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -48,7 +48,10 @@ enum ast_node:u32 { ast_link, // ~ ast_neg, // unary - ast_lnot, // unary ! - ast_bnot, // unary ~ + ast_bnot, // unary ~ bitwise not + ast_bitor, // bitwise or + ast_bitxor, // bitwise xor + ast_bitand, // bitwise and ast_trino, // ?: ast_for, // for keyword ast_forindex, // forindex keyword @@ -110,8 +113,11 @@ const char* ast_name[]={ "DivExpression", "LinkExpression", "NegativeExpression", - "LogicalNegationExpression", - "BinaryNegationExpression", + "LogicalNotExpression", + "BitwiseNotExpression", + "BitwiseOrExpression", + "BitwiseXorExpression", + "BitwiseAndExpression", "TrinocularExpression", "ForLoop", "ForindexLoop", diff --git a/nasal_codegen.h b/nasal_codegen.h index 501547e..cb4434b 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -27,7 +27,10 @@ enum op_code_type:u8 { op_dyn, // dynamic parameter op_lnot, // ! logical negation op_usub, // - - op_bnot, // ~ binary negation static_cast + op_bnot, // ~ bitwise not static_cast + op_btor, // | bitwise or + op_btxor, // ^ bitwise xor + op_btand, // & bitwise and op_add, // + op_sub, // - op_mul, // * @@ -92,8 +95,8 @@ const char* opname[]={ "loadl ","loadu ","pnum ","pnil ", "pstr ","newv ","newh ","newf ", "happ ","para ","def ","dyn ", - "lnot ","usub ","bnot ","add ", - "sub ", + "lnot ","usub ","bnot ","btor ", + "btxor ","btand ","add ","sub ", "mult ","div ","lnk ","addc ", "subc ","multc ","divc ","lnkc ", "addeq ","subeq ","muleq ","diveq ", @@ -811,6 +814,7 @@ void codegen::for_gen(const ast& node) { case ast_vec:case ast_hash:case ast_func: case ast_call: case ast_neg:case ast_lnot:case ast_bnot: + case ast_bitor:case ast_bitxor:case ast_bitand: case ast_add:case ast_sub: case ast_mult:case ast_div: case ast_link: @@ -877,6 +881,7 @@ void codegen::for_gen(const ast& node) { case ast_vec:case ast_hash:case ast_func: case ast_call: case ast_neg:case ast_lnot:case ast_bnot: + case ast_bitor:case ast_bitxor:case ast_bitand: case ast_add:case ast_sub:case ast_mult: case ast_div:case ast_link: case ast_cmpeq:case ast_neq:case ast_leq: @@ -1120,6 +1125,21 @@ void codegen::calc_gen(const ast& node) { calc_gen(node[0]); gen(op_bnot,0,node.line()); break; + case ast_bitor: + calc_gen(node[0]); + calc_gen(node[1]); + gen(op_btor,0,node.line()); + break; + case ast_bitxor: + calc_gen(node[0]); + calc_gen(node[1]); + gen(op_btxor,0,node.line()); + break; + case ast_bitand: + calc_gen(node[0]); + calc_gen(node[1]); + gen(op_btand,0,node.line()); + break; case ast_def: single_def(node); call_id(node[0]); @@ -1191,6 +1211,9 @@ void codegen::block_gen(const ast& node) { case ast_neg: case ast_lnot: case ast_bnot: + case ast_bitor: + case ast_bitxor: + case ast_bitand: case ast_add: case ast_sub: case ast_mult: diff --git a/nasal_dbg.h b/nasal_dbg.h index f927823..0df8815 100644 --- a/nasal_dbg.h +++ b/nasal_dbg.h @@ -206,8 +206,8 @@ void debugger::run( &&loadl, &&loadu, &&pnum, &&pnil, &&pstr, &&newv, &&newh, &&newf, &&happ, &¶, &&deft, &&dyn, - &&lnot, &&usub, &&bnot, &&add, - &&sub, + &&lnot, &&usub, &&bnot, &&btor, + &&btxor, &&btand, &&add, &&sub, &&mul, &&div, &&lnk, &&addc, &&subc, &&mulc, &&divc, &&lnkc, &&addeq, &&subeq, &&muleq, &&diveq, @@ -242,7 +242,8 @@ void debugger::run( &debugger::o_happ, &debugger::o_para, &debugger::o_deft, &debugger::o_dyn, &debugger::o_lnot, &debugger::o_usub, - &debugger::o_bnot, + &debugger::o_bnot, &debugger::o_btor, + &debugger::o_btxor, &debugger::o_btand, &debugger::o_add, &debugger::o_sub, &debugger::o_mul, &debugger::o_div, &debugger::o_lnk, &debugger::o_addc, @@ -325,6 +326,9 @@ dyn: dbg(o_dyn ,op_dyn ); lnot: dbg(o_lnot ,op_lnot ); usub: dbg(o_usub ,op_usub ); bnot: dbg(o_bnot ,op_bnot ); +btor: dbg(o_btor ,op_btor ); +btxor: dbg(o_btxor ,op_btxor ); +btand: dbg(o_btand ,op_btand ); 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 ff62257..b3e38c2 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -52,9 +52,9 @@ enum class tok:u32 { mult, // operator * div, // operator / floater, // operator ~ and binary operator ~ - biand, // binary operator & - bior, // binary operator | - bixor, // binary operator ^ + btand, // bitwise operator & + btor, // bitwise operator | + btxor, // bitwise operator ^ opnot, // operator ! eq, // operator = addeq, // operator += @@ -127,9 +127,9 @@ private: {"*" ,tok::mult }, {"/" ,tok::div }, {"~" ,tok::floater }, - {"&" ,tok::biand }, - {"|" ,tok::bior }, - {"^" ,tok::bixor }, + {"&" ,tok::btand }, + {"|" ,tok::btor }, + {"^" ,tok::btxor }, {"!" ,tok::opnot }, {"=" ,tok::eq }, {"+=" ,tok::addeq }, diff --git a/nasal_parse.h b/nasal_parse.h index 4facc96..3d0e813 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -86,9 +86,9 @@ private: {tok::mult ,"*" }, {tok::div ,"/" }, {tok::floater ,"~" }, - {tok::biand ,"&" }, - {tok::bior ,"|" }, - {tok::bixor ,"^" }, + {tok::btand ,"&" }, + {tok::btor ,"|" }, + {tok::btxor ,"^" }, {tok::opnot ,"!" }, {tok::eq ,"=" }, {tok::addeq ,"+=" }, @@ -129,6 +129,9 @@ private: ast expr(); ast exprs(); ast calc(); + ast bitwise_or(); + ast bitwise_xor(); + ast bitwise_and(); ast or_expr(); ast and_expr(); ast cmp_expr(); @@ -528,7 +531,7 @@ ast parse::exprs() { } ast parse::calc() { - ast node=or_expr(); + ast node=bitwise_or(); if (lookahead(tok::quesmark)) { // trinocular calculation ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_trino,toks[ptr].file); @@ -549,6 +552,42 @@ ast parse::calc() { return node; } +ast parse::bitwise_or() { + ast node=bitwise_xor(); + while(lookahead(tok::btor)) { + ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_bitor,toks[ptr].file); + tmp.add(std::move(node)); + match(tok::btor); + tmp.add(bitwise_xor()); + node=std::move(tmp); + } + return node; +} + +ast parse::bitwise_xor() { + ast node=bitwise_and(); + while(lookahead(tok::btxor)) { + ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_bitxor,toks[ptr].file); + tmp.add(std::move(node)); + match(tok::btxor); + tmp.add(bitwise_and()); + node=std::move(tmp); + } + return node; +} + +ast parse::bitwise_and() { + ast node=or_expr(); + while(lookahead(tok::btand)) { + ast tmp(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_bitand,toks[ptr].file); + tmp.add(std::move(node)); + match(tok::btand); + tmp.add(or_expr()); + node=std::move(tmp); + } + return node; +} + ast parse::or_expr() { ast node=and_expr(); while(lookahead(tok::opor)) { diff --git a/nasal_vm.h b/nasal_vm.h index 92bbe3d..f097db2 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -70,6 +70,9 @@ protected: void o_lnot(); void o_usub(); void o_bnot(); + void o_btor(); + void o_btxor(); + void o_btand(); void o_add(); void o_sub(); void o_mul(); @@ -465,6 +468,21 @@ void vm::o_bnot() { top[0]=var::num(~static_cast(top[0].num())); } +void vm::o_btor() { + top[-1]=var::num(static_cast(top[-1].tonum())|static_cast(top[0].tonum())); + --top; +} + +void vm::o_btxor() { + top[-1]=var::num(static_cast(top[-1].tonum())^static_cast(top[0].tonum())); + --top; +} + +void vm::o_btand() { + top[-1]=var::num(static_cast(top[-1].tonum())&static_cast(top[0].tonum())); + --top; +} + #define op_calc(type)\ top[-1]=var::num(top[-1].tonum() type top[0].tonum());\ --top; @@ -1006,8 +1024,8 @@ void vm::run( &&loadl, &&loadu, &&pnum, &&pnil, &&pstr, &&newv, &&newh, &&newf, &&happ, &¶, &&deft, &&dyn, - &&lnot, &&usub, &&bnot, &&add, - &&sub, + &&lnot, &&usub, &&bnot, &&btor, + &&btxor, &&btand, &&add, &&sub, &&mul, &&div, &&lnk, &&addc, &&subc, &&mulc, &&divc, &&lnkc, &&addeq, &&subeq, &&muleq, &&diveq, @@ -1042,7 +1060,8 @@ void vm::run( &vm::o_happ, &vm::o_para, &vm::o_deft, &vm::o_dyn, &vm::o_lnot, &vm::o_usub, - &vm::o_bnot, + &vm::o_bnot, &vm::o_btor, + &vm::o_btxor, &vm::o_btand, &vm::o_add, &vm::o_sub, &vm::o_mul, &vm::o_div, &vm::o_lnk, &vm::o_addc, @@ -1125,6 +1144,9 @@ dyn: exec_nodie(o_dyn ); // -0 lnot: exec_nodie(o_lnot ); // -0 usub: exec_nodie(o_usub ); // -0 bnot: exec_nodie(o_bnot ); // -0 +btor: exec_nodie(o_btor ); // -1 +btxor: exec_nodie(o_btxor ); // -1 +btand: exec_nodie(o_btand ); // -1 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 95e461d..28730bd 100644 --- a/test/scalar.nas +++ b/test/scalar.nas @@ -211,4 +211,15 @@ println("~ 0x80: ",~0x80); println("~ 0x8000: ",~0x8000); println("~ 0x80000000: ",~0x80000000); println("~ 0x8000000000000000: ",~0x8000000000000000); -println(~0x80000000==~0x8000000000000000); \ No newline at end of file +println(~0x80000000==~0x8000000000000000); + +var h=split(" ","0 1 2 3 4 5 6 7 8 9 a b c d e f"); +for(var a=0;a<16;a+=1) { + for(var b=0;b<16;b+=1) { + for(var c=0;c<16;c+=1) { + if(((a^b)&c)!=(a^(b&c))) { + println("0x"~h[a],"^","0x"~h[b],"&","0x"~h[c]," -> a^b&c = 0x",h[a^b&c]," (a^b)&c = 0x",h[(a^b)&c]," a^(b&c) = 0x",h[(a^(b&c))]); + } + } + } +} \ No newline at end of file