nandi/clonimpublic Fork
⑂ 399bfb7
Commits
⬇ Clone ▾
git clone https://git.rickub.com/nandi/clonim.git
git clone ssh://git@rickub.com/nandi/clonim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

feat: add bitwise integer primitives

sha256 and png codegen in real Clojure programs bottom out in bit ops;
clonim had none. Adds the JVM-semantics set over int64: shift counts mask
to 0..63, bit-shift-right is arithmetic, unsigned-bit-shift-right is not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-21T00:57:05-07:00 Browse files
399bfb7 parent: c735c3d
added examples/bitops.clj +10 -0
new file mode 100644
@@ -0,0 +1,10 @@
1+(ns bitops)
2+
3+(println (bit-and 12 10) (bit-or 12 10) (bit-xor 12 10)) ; 8 14 6
4+(println (bit-and-not 12 10) (bit-not 0) (bit-not 5)) ; 4 -1 -6
5+(println (bit-and 255 170 15) (bit-or 1 2 4) (bit-xor 1 2 4)) ; variadic: 10 7 7
6+(println (bit-shift-left 1 10) (bit-shift-right 1024 3)) ; 1024 128
7+(println (bit-shift-right -8 1) (unsigned-bit-shift-right -1 60)) ; -4 15
8+(println (bit-test 5 0) (bit-test 5 1)) ; true false
9+(println (bit-set 0 4) (bit-clear 31 0) (bit-flip 5 1)) ; 16 30 7
10+(println (reduce bit-xor [1 2 4 8])) ; as a value: 15
new file mode 100644
@@ -0,0 +1,10 @@
1+(ns bitops)
2+
3+(println (bit-and 12 10) (bit-or 12 10) (bit-xor 12 10)) ; 8 14 6
4+(println (bit-and-not 12 10) (bit-not 0) (bit-not 5)) ; 4 -1 -6
5+(println (bit-and 255 170 15) (bit-or 1 2 4) (bit-xor 1 2 4)) ; variadic: 10 7 7
6+(println (bit-shift-left 1 10) (bit-shift-right 1024 3)) ; 1024 128
7+(println (bit-shift-right -8 1) (unsigned-bit-shift-right -1 60)) ; -4 15
8+(println (bit-test 5 0) (bit-test 5 1)) ; true false
9+(println (bit-set 0 4) (bit-clear 31 0) (bit-flip 5 1)) ; 16 30 7
10+(println (reduce bit-xor [1 2 4 8])) ; as a value: 15
modified src/core.nim +29 -0
@@ -419,6 +419,35 @@ proc registerCore*() =
419419 var r = irem(x, y)
420420 if r != 0 and ((r < 0) != (y < 0)): r += y
421421 mkInt(r)
422+ # ---- bitwise (int64, JVM semantics: shift counts mask to 0..63)
423+ def "bit-and", proc (a: openArray[Value]): Value =
424+ result = mkInt(intOf(a[0]))
425+ for i in 1 ..< a.len: result = mkInt(result.i and intOf(a[i]))
426+ def "bit-or", proc (a: openArray[Value]): Value =
427+ result = mkInt(intOf(a[0]))
428+ for i in 1 ..< a.len: result = mkInt(result.i or intOf(a[i]))
429+ def "bit-xor", proc (a: openArray[Value]): Value =
430+ result = mkInt(intOf(a[0]))
431+ for i in 1 ..< a.len: result = mkInt(result.i xor intOf(a[i]))
432+ def "bit-and-not", proc (a: openArray[Value]): Value =
433+ result = mkInt(intOf(a[0]))
434+ for i in 1 ..< a.len: result = mkInt(result.i and not intOf(a[i]))
435+ def "bit-not", proc (a: openArray[Value]): Value = mkInt(not intOf(a[0]))
436+ def "bit-shift-left", proc (a: openArray[Value]): Value =
437+ mkInt(intOf(a[0]) shl (intOf(a[1]) and 63))
438+ def "bit-shift-right", proc (a: openArray[Value]): Value =
439+ # arithmetic: the sign bit is replicated, as on the JVM
440+ mkInt(ashr(intOf(a[0]), intOf(a[1]) and 63))
441+ def "unsigned-bit-shift-right", proc (a: openArray[Value]): Value =
442+ mkInt(cast[int64](cast[uint64](intOf(a[0])) shr uint64(intOf(a[1]) and 63)))
443+ def "bit-test", proc (a: openArray[Value]): Value =
444+ mkBool((ashr(intOf(a[0]), intOf(a[1]) and 63) and 1) != 0)
445+ def "bit-set", proc (a: openArray[Value]): Value =
446+ mkInt(intOf(a[0]) or (1'i64 shl (intOf(a[1]) and 63)))
447+ def "bit-clear", proc (a: openArray[Value]): Value =
448+ mkInt(intOf(a[0]) and not (1'i64 shl (intOf(a[1]) and 63)))
449+ def "bit-flip", proc (a: openArray[Value]): Value =
450+ mkInt(intOf(a[0]) xor (1'i64 shl (intOf(a[1]) and 63)))
422451 def "inc", proc (a: openArray[Value]): Value =
423452 (if a[0].kind == kFloat: mkFloat(a[0].f + 1.0) else: mkInt(a[0].i + 1))
424453 def "dec", proc (a: openArray[Value]): Value =
@@ -419,6 +419,35 @@ proc registerCore*() =
419 var r = irem(x, y)419 var r = irem(x, y)
420 if r != 0 and ((r < 0) != (y < 0)): r += y420 if r != 0 and ((r < 0) != (y < 0)): r += y
421 mkInt(r)421 mkInt(r)
422+ # ---- bitwise (int64, JVM semantics: shift counts mask to 0..63)
423+ def "bit-and", proc (a: openArray[Value]): Value =
424+ result = mkInt(intOf(a[0]))
425+ for i in 1 ..< a.len: result = mkInt(result.i and intOf(a[i]))
426+ def "bit-or", proc (a: openArray[Value]): Value =
427+ result = mkInt(intOf(a[0]))
428+ for i in 1 ..< a.len: result = mkInt(result.i or intOf(a[i]))
429+ def "bit-xor", proc (a: openArray[Value]): Value =
430+ result = mkInt(intOf(a[0]))
431+ for i in 1 ..< a.len: result = mkInt(result.i xor intOf(a[i]))
432+ def "bit-and-not", proc (a: openArray[Value]): Value =
433+ result = mkInt(intOf(a[0]))
434+ for i in 1 ..< a.len: result = mkInt(result.i and not intOf(a[i]))
435+ def "bit-not", proc (a: openArray[Value]): Value = mkInt(not intOf(a[0]))
436+ def "bit-shift-left", proc (a: openArray[Value]): Value =
437+ mkInt(intOf(a[0]) shl (intOf(a[1]) and 63))
438+ def "bit-shift-right", proc (a: openArray[Value]): Value =
439+ # arithmetic: the sign bit is replicated, as on the JVM
440+ mkInt(ashr(intOf(a[0]), intOf(a[1]) and 63))
441+ def "unsigned-bit-shift-right", proc (a: openArray[Value]): Value =
442+ mkInt(cast[int64](cast[uint64](intOf(a[0])) shr uint64(intOf(a[1]) and 63)))
443+ def "bit-test", proc (a: openArray[Value]): Value =
444+ mkBool((ashr(intOf(a[0]), intOf(a[1]) and 63) and 1) != 0)
445+ def "bit-set", proc (a: openArray[Value]): Value =
446+ mkInt(intOf(a[0]) or (1'i64 shl (intOf(a[1]) and 63)))
447+ def "bit-clear", proc (a: openArray[Value]): Value =
448+ mkInt(intOf(a[0]) and not (1'i64 shl (intOf(a[1]) and 63)))
449+ def "bit-flip", proc (a: openArray[Value]): Value =
450+ mkInt(intOf(a[0]) xor (1'i64 shl (intOf(a[1]) and 63)))
422 def "inc", proc (a: openArray[Value]): Value =451 def "inc", proc (a: openArray[Value]): Value =
423 (if a[0].kind == kFloat: mkFloat(a[0].f + 1.0) else: mkInt(a[0].i + 1))452 (if a[0].kind == kFloat: mkFloat(a[0].f + 1.0) else: mkInt(a[0].i + 1))
424 def "dec", proc (a: openArray[Value]): Value =453 def "dec", proc (a: openArray[Value]): Value =
added tests/bitops.expected +8 -0
new file mode 100644
@@ -0,0 +1,8 @@
1+8 14 6
2+4 -1 -6
3+10 7 7
4+1024 128
5+-4 15
6+true false
7+16 30 7
8+15
new file mode 100644
@@ -0,0 +1,8 @@
1+8 14 6
2+4 -1 -6
3+10 7 7
4+1024 128
5+-4 15
6+true false
7+16 30 7
8+15