Skip to content

Commit

Permalink
Replace pow operator with xor
Browse files Browse the repository at this point in the history
  • Loading branch information
Askaholic committed Jul 11, 2021
1 parent 733ad25 commit d438c85
Show file tree
Hide file tree
Showing 11 changed files with 42 additions and 13 deletions.
1 change: 1 addition & 0 deletions HISTORY
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This is Lua 5.0 FAF version.
+ new inequality operator: !=
+ new single line comment: # ...
+ new binary operators &, |, << and >>
+ operator ^ means xor instead of pow
Implementation:
+ skip BOM and unix style # comments when reading files

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The most notable changes are:
- Addition of a `continue` statement
- Bash style single line `#` comments
- Bitwise operators `&`, `|`, `<<`, and `>>`
- Pow operator replaced by bitwise xor `^`

See [HISTORY](HISTORY) for a full list of changes.

Expand Down
2 changes: 1 addition & 1 deletion src/lcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {

static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
int o1, int o2) {
if (op <= OPR_POW) { /* arithmetic/bitwise operator? */
if (op <= OPR_XOR) { /* arithmetic/bitwise operator? */
OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */
res->info = luaK_codeABC(fs, opc, 0, o1, o2);
res->k = VRELOCABLE;
Expand Down
2 changes: 1 addition & 1 deletion src/lcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
typedef enum BinOpr {
OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV,
OPR_BAND, OPR_BOR, OPR_BSHL, OPR_BSHR,
OPR_POW,
OPR_XOR,
OPR_CONCAT,
OPR_NE, OPR_EQ,
OPR_LT, OPR_LE, OPR_GT, OPR_GE,
Expand Down
4 changes: 2 additions & 2 deletions src/lopcodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const char *const luaP_opnames[] = {
"BOR",
"BSHL",
"BSHR",
"POW",
"XOR",
"UNM",
"NOT",
"CONCAT",
Expand Down Expand Up @@ -89,7 +89,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_BOR */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_BSHL */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_BSHR */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_POW */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_XOR */
,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_UNM */
,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_NOT */
,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_CONCAT */
Expand Down
2 changes: 1 addition & 1 deletion src/lopcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ OP_BAND,/*A B C R(A) := RK(B) & RK(C) */
OP_BOR,/* A B C R(A) := RK(B) | RK(C) */
OP_BSHL,/*A B C R(A) := RK(B) << RK(C) */
OP_BSHR,/*A B C R(A) := RK(B) >> RK(C) */
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
OP_XOR,/* A B C R(A) := RK(B) ^ RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
OP_NOT,/* A B R(A) := not R(B) */

Expand Down
5 changes: 3 additions & 2 deletions src/lparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ static BinOpr getbinopr (int op) {
case '-': return OPR_SUB;
case '*': return OPR_MULT;
case '/': return OPR_DIV;
case '^': return OPR_POW;
case '^': return OPR_XOR;
case TK_CONCAT: return OPR_CONCAT;
case TK_NE: return OPR_NE;
case TK_EQ: return OPR_EQ;
Expand All @@ -792,7 +792,8 @@ static const struct {
{6, 6}, {6, 6}, /* arithmetic (add/sub) */
{7, 7}, {7, 7}, /* arithmetic (mul/div) */
{8, 8}, {8, 8}, {8, 8}, {8, 8}, /* bitwise (and/or/shl/shr) */
{10, 9}, {5, 4}, /* power and concat (right associative) */
{10, 9}, /* xor (right associative!!!!) */
{5, 4}, /* concat (right associative) */
{3, 3}, {3, 3}, /* equality */
{3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
{2, 2}, {1, 1} /* logical (and/or) */
Expand Down
2 changes: 1 addition & 1 deletion src/ltm.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ typedef enum {
TM_SUB,
TM_MUL,
TM_DIV,
TM_POW,
TM_XOR,
TM_UNM,
TM_LT,
TM_LE,
Expand Down
2 changes: 1 addition & 1 deletion src/luac/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static void PrintCode(const Proto* f)
case OP_BOR:
case OP_BSHL:
case OP_BSHR:
case OP_POW:
case OP_XOR:
case OP_EQ:
case OP_LT:
case OP_LE:
Expand Down
14 changes: 10 additions & 4 deletions src/lvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ static void Arith (lua_State *L, StkId ra,
case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break;
case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
case TM_POW: {
const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
case TM_XOR: {
const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_XOR]);
ptrdiff_t res = savestack(L, ra);
if (!ttisfunction(f))
luaG_runerror(L, "`__pow' (`^' operator) is not a function");
Expand Down Expand Up @@ -598,8 +598,14 @@ StkId luaV_execute (lua_State *L) {
luaG_runerror(L, "`>>' operands must be numbers");
break;
}
case OP_POW: {
Arith(L, ra, RKB(i), RKC(i), TM_POW);
case OP_XOR: {
TObject *rb = RKB(i);
TObject *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, (unsigned int) nvalue(rb) ^ (unsigned int) nvalue(rc));
}
else
Arith(L, ra, RKB(i), RKC(i), TM_XOR);
break;
}
case OP_UNM: {
Expand Down
20 changes: 20 additions & 0 deletions test/faf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ assert(2 >> -1 == 0)
assert(1 << 1 == 2)
print("passed bitwise shift")

assert(2 ^ 2 == 0)
assert(2 ^ 30 == 28)
assert(0xF0F0 ^ 0x0F0F == 0xFFFF)
assert(0xFFFF ^ 0x0F0F == 0xF0F0)
print("passed xor")

-- Supcom has some non-conventional operator precedence
assert(2 ^ 30 - 1 == 27)
assert((2 ^ 30) - (1 << 1) == 26)
assert(2 ^ 30 - 1 << 1 == 26)
assert(2 ^ 30 - 1 << 2 == 24)
assert(2 ^ 30 - 1 << 3 == 20)
-- NOTE: SupCom uses floats and therefore encounters rounding errors. Using
-- doubles the answer would actually be -268435428.
assert(2 ^ 30 - 1 << 2 ^ 30 == -268435424)

-- some special cases
-- Does not pass for 0xffffffff (too large)
local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555, 0x7fffffff}
Expand All @@ -90,6 +106,10 @@ for _, b in pairs(c) do
assert(b | 0 == b)
assert(b | b == b)
assert(b | b | b == b)
assert(b ^ b == 0)
assert(b ^ b ^ b == b)
assert(b ^ b ^ b ^ b == 0)
assert(b ^ 0 == b)
print(" passed " .. b)
end
print("passed binary operators")

0 comments on commit d438c85

Please sign in to comment.