shrimp/src/compiler/tests/bitwise.test.ts

179 lines
4.3 KiB
TypeScript

import { expect, describe, test } from 'bun:test'
describe('bitwise operators', () => {
describe('band (bitwise AND)', () => {
test('basic AND operation', () => {
expect('5 band 3').toEvaluateTo(1)
// 5 = 0101, 3 = 0011, result = 0001 = 1
})
test('AND with zero', () => {
expect('5 band 0').toEvaluateTo(0)
})
test('AND with all bits set', () => {
expect('15 band 7').toEvaluateTo(7)
// 15 = 1111, 7 = 0111, result = 0111 = 7
})
test('AND in assignment', () => {
expect('x = 12 band 10').toEvaluateTo(8)
// 12 = 1100, 10 = 1010, result = 1000 = 8
})
})
describe('bor (bitwise OR)', () => {
test('basic OR operation', () => {
expect('5 bor 3').toEvaluateTo(7)
// 5 = 0101, 3 = 0011, result = 0111 = 7
})
test('OR with zero', () => {
expect('5 bor 0').toEvaluateTo(5)
})
test('OR with all bits set', () => {
expect('8 bor 4').toEvaluateTo(12)
// 8 = 1000, 4 = 0100, result = 1100 = 12
})
})
describe('bxor (bitwise XOR)', () => {
test('basic XOR operation', () => {
expect('5 bxor 3').toEvaluateTo(6)
// 5 = 0101, 3 = 0011, result = 0110 = 6
})
test('XOR with itself returns zero', () => {
expect('5 bxor 5').toEvaluateTo(0)
})
test('XOR with zero returns same value', () => {
expect('7 bxor 0').toEvaluateTo(7)
})
test('XOR in assignment', () => {
expect('result = 8 bxor 12').toEvaluateTo(4)
// 8 = 1000, 12 = 1100, result = 0100 = 4
})
})
describe('bnot (bitwise NOT)', () => {
test('NOT of positive number', () => {
expect('bnot 5').toEvaluateTo(-6)
// ~5 = -6 (two\'s complement)
})
test('NOT of zero', () => {
expect('bnot 0').toEvaluateTo(-1)
})
test('NOT of negative number', () => {
expect('bnot -1').toEvaluateTo(0)
})
test('double NOT returns original', () => {
expect('bnot (bnot 5)').toEvaluateTo(5)
})
})
describe('<< (left shift)', () => {
test('basic left shift', () => {
expect('5 << 2').toEvaluateTo(20)
// 5 << 2 = 20
})
test('shift by zero', () => {
expect('5 << 0').toEvaluateTo(5)
})
test('shift by one', () => {
expect('3 << 1').toEvaluateTo(6)
})
test('large shift', () => {
expect('1 << 10').toEvaluateTo(1024)
})
})
describe('>> (signed right shift)', () => {
test('basic right shift', () => {
expect('20 >> 2').toEvaluateTo(5)
// 20 >> 2 = 5
})
test('shift by zero', () => {
expect('20 >> 0').toEvaluateTo(20)
})
test('preserves sign for negative numbers', () => {
expect('-20 >> 2').toEvaluateTo(-5)
// Sign is preserved
})
test('negative number right shift', () => {
expect('-8 >> 1').toEvaluateTo(-4)
})
})
describe('>>> (unsigned right shift)', () => {
test('basic unsigned right shift', () => {
expect('20 >>> 2').toEvaluateTo(5)
})
test('unsigned shift of -1', () => {
expect('-1 >>> 1').toEvaluateTo(2147483647)
// -1 >>> 1 = 2147483647 (unsigned, no sign extension)
})
test('unsigned shift of negative number', () => {
expect('-8 >>> 1').toEvaluateTo(2147483644)
})
})
describe('compound expressions', () => {
test('multiple bitwise operations', () => {
expect('(5 band 3) bor (8 bxor 12)').toEvaluateTo(5)
// (5 & 3) | (8 ^ 12) = 1 | 4 = 5
})
test('bitwise with variables', () => {
expect(`
a = 5
b = 3
a bor b
`).toEvaluateTo(7)
})
test('shift operations with variables', () => {
expect(`
x = 16
y = 2
x >> y
`).toEvaluateTo(4)
})
test('mixing shifts and bitwise', () => {
expect('(8 << 1) band 15').toEvaluateTo(0)
// (8 << 1) & 15 = 16 & 15 = 0
})
test('mixing shifts and bitwise 2', () => {
expect('(7 << 1) band 15').toEvaluateTo(14)
// (7 << 1) & 15 = 14 & 15 = 14
})
})
describe('precedence', () => {
test('bitwise has correct precedence with arithmetic', () => {
expect('1 + 2 band 3').toEvaluateTo(3)
// (1 + 2) & 3 = 3 & 3 = 3
})
test('shift has correct precedence', () => {
expect('4 + 8 << 1').toEvaluateTo(24)
// (4 + 8) << 1 = 12 << 1 = 24
})
})
})