From 80aa833a9b0a6415786f3f9d77139b9aea8f2ff9 Mon Sep 17 00:00:00 2001
From: Eduard Urbach <eduard@urbach.dev>
Date: Tue, 15 Apr 2025 11:08:33 +0200
Subject: [PATCH] Added a function for memory size alignment

---
 lib/math/math.q                   | 11 +++++++++++
 src/expression/Expression_test.go |  3 +++
 src/expression/Operator.go        |  3 +++
 tests/programs/align.q            | 26 ++++++++++++++++++++++++++
 tests/programs_test.go            |  1 +
 5 files changed, 44 insertions(+)
 create mode 100644 lib/math/math.q
 create mode 100644 tests/programs/align.q

diff --git a/lib/math/math.q b/lib/math/math.q
new file mode 100644
index 0000000..d71b952
--- /dev/null
+++ b/lib/math/math.q
@@ -0,0 +1,11 @@
+align2(x uint64) -> uint64 {
+	x -= 1
+	x |= x >> 1
+	x |= x >> 2
+	x |= x >> 4
+	x |= x >> 8
+	x |= x >> 16
+	x |= x >> 32
+	x += 1
+	return x
+}
\ No newline at end of file
diff --git a/src/expression/Expression_test.go b/src/expression/Expression_test.go
index 15c461c..1880aea 100644
--- a/src/expression/Expression_test.go
+++ b/src/expression/Expression_test.go
@@ -117,6 +117,9 @@ func TestParse(t *testing.T) {
 		{"Dereferencing 2", "[a+b]", "(@ (+ a b))"},
 		{"Dereferencing 3", "[a+b]=c", "(= (@ (+ a b)) c)"},
 		{"Dereferencing 3", "[a+b]=c+d", "(= (@ (+ a b)) (+ c d))"},
+
+		{"Assign bitwise OR", "a|=b", "(|= a b)"},
+		{"Assign bitwise OR 2", "a|=b<<c", "(|= a (<< b c))"},
 	}
 
 	for _, test := range tests {
diff --git a/src/expression/Operator.go b/src/expression/Operator.go
index cd626d4..838e4c2 100644
--- a/src/expression/Operator.go
+++ b/src/expression/Operator.go
@@ -51,6 +51,9 @@ var Operators = [64]Operator{
 	token.MulAssign: {"*=", math.MinInt8, 2},
 	token.DivAssign: {"/=", math.MinInt8, 2},
 	token.ModAssign: {"%=", math.MinInt8, 2},
+	token.AndAssign: {"&=", math.MinInt8, 2},
+	token.OrAssign:  {"|=", math.MinInt8, 2},
+	token.XorAssign: {"^=", math.MinInt8, 2},
 	token.ShrAssign: {">>=", math.MinInt8, 2},
 	token.ShlAssign: {"<<=", math.MinInt8, 2},
 }
diff --git a/tests/programs/align.q b/tests/programs/align.q
new file mode 100644
index 0000000..264ddf9
--- /dev/null
+++ b/tests/programs/align.q
@@ -0,0 +1,26 @@
+import math
+
+main() {
+	assert math.align2(0) == 0
+	assert math.align2(1) == 1
+	assert math.align2(2) == 2
+	assert math.align2(3) == 4
+	assert math.align2(4) == 4
+	assert math.align2(5) == 8
+	assert math.align2(6) == 8
+	assert math.align2(7) == 8
+	assert math.align2(8) == 8
+	assert math.align2(9) == 16
+	assert math.align2(10) == 16
+	assert math.align2(30) == 32
+	assert math.align2(60) == 64
+	assert math.align2(100) == 128
+	assert math.align2(200) == 256
+	assert math.align2(500) == 512
+	assert math.align2(1000) == 1024
+	assert math.align2(2000) == 2048
+	assert math.align2(4000) == 4096
+	assert math.align2(8000) == 8192
+	assert math.align2(16000) == 16384
+	assert math.align2(32000) == 32768
+}
\ No newline at end of file
diff --git a/tests/programs_test.go b/tests/programs_test.go
index 480c089..44047f2 100644
--- a/tests/programs_test.go
+++ b/tests/programs_test.go
@@ -40,6 +40,7 @@ var programs = []struct {
 	{"bitwise-or", 0},
 	{"bitwise-xor", 0},
 	{"shift", 0},
+	{"align", 0},
 	{"modulo", 0},
 	{"modulo-assign", 0},
 	{"div-split", 0},