github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/runtime/bitwise.go (about) 1 package runtime 2 3 import "fmt" 4 5 func band(t *Thread, x, y Value) (Value, error) { 6 ix, okx := ToIntNoString(x) 7 iy, oky := ToIntNoString(y) 8 if okx && oky { 9 return IntValue(ix & iy), nil 10 } 11 res, err, ok := metabin(t, "__band", x, y) 12 if ok { 13 return res, err 14 } 15 return NilValue, binaryBitwiseError("and", x, y, okx, oky) 16 } 17 18 func bor(t *Thread, x, y Value) (Value, error) { 19 ix, okx := ToIntNoString(x) 20 iy, oky := ToIntNoString(y) 21 if okx && oky { 22 return IntValue(ix | iy), nil 23 } 24 res, err, ok := metabin(t, "__bor", x, y) 25 if ok { 26 return res, err 27 } 28 return NilValue, binaryBitwiseError("or", x, y, okx, oky) 29 } 30 31 func bxor(t *Thread, x, y Value) (Value, error) { 32 ix, okx := ToIntNoString(x) 33 iy, oky := ToIntNoString(y) 34 if okx && oky { 35 return IntValue(ix ^ iy), nil 36 } 37 res, err, ok := metabin(t, "__bxor", x, y) 38 if ok { 39 return res, err 40 } 41 return NilValue, binaryBitwiseError("xor", x, y, okx, oky) 42 } 43 44 func shl(t *Thread, x, y Value) (Value, error) { 45 ix, okx := ToIntNoString(x) 46 iy, oky := ToIntNoString(y) 47 48 // We turn the value into an uint64 before shifting so that it's a logical 49 // shift, not arithmetic. 50 if okx && oky { 51 if iy < 0 { 52 return IntValue(int64(uint64(ix) >> uint64(-iy))), nil 53 } 54 return IntValue(int64(uint64(ix) << uint64(iy))), nil 55 } 56 res, err, ok := metabin(t, "__shl", x, y) 57 if ok { 58 return res, err 59 } 60 return NilValue, binaryBitwiseError("shl", x, y, okx, oky) 61 } 62 63 func shr(t *Thread, x, y Value) (Value, error) { 64 ix, okx := ToIntNoString(x) 65 iy, oky := ToIntNoString(y) 66 67 // We turn the value into an uint64 before shifting so that it's a logical 68 // shift, not arithmetic. 69 if okx && oky { 70 if iy < 0 { 71 return IntValue(int64(uint64(ix) << uint64(-iy))), nil 72 } 73 return IntValue(int64(uint64(ix) >> uint64(iy))), nil 74 } 75 res, err, ok := metabin(t, "__shr", x, y) 76 if ok { 77 return res, err 78 } 79 return NilValue, binaryBitwiseError("shr", x, y, okx, oky) 80 } 81 82 func bnot(t *Thread, x Value) (Value, error) { 83 ix, okx := ToIntNoString(x) 84 if okx { 85 return IntValue(^ix), nil 86 } 87 res, err, ok := metaun(t, "__bnot", x) 88 if ok { 89 return res, err 90 } 91 return NilValue, binaryBitwiseError("not", x, x, false, true) 92 } 93 94 func binaryBitwiseError(op string, x, y Value, okx, oky bool) error { 95 var wrongVal Value 96 switch { 97 case oky: 98 wrongVal = x 99 case okx: 100 wrongVal = y 101 case x.Type() != FloatType: 102 wrongVal = x 103 case y.Type() != FloatType: 104 wrongVal = y 105 default: 106 // Both x, and y are floats 107 wrongVal = x 108 } 109 if wrongVal.Type() == FloatType { 110 return fmt.Errorf("number has no integer representation") 111 } 112 return fmt.Errorf("attempt to perform bitwise %s on a %s value", op, wrongVal.CustomTypeName()) 113 }