spec: bitwise operations (bitwise-and/or/xor/not, arithmetic-shift, bit-count, integer-length)

OCaml: land/lor/lxor/lnot/lsl/asr in sx_primitives.ml
JS: & | ^ ~ << >> with Kernighan popcount and Math.clz32 for integer-length
spec/primitives.sx: stdlib.bitwise module with 7 entries
26 tests, 158 assertions, all pass OCaml+JS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 19:06:09 +00:00
parent 1ad9d63f1b
commit a8a79dc902
5 changed files with 289 additions and 2 deletions

View File

@@ -1309,6 +1309,27 @@ PRIMITIVES_JS_MODULES: dict[str, str] = {
return NIL;
};
''',
"stdlib.bitwise": '''
// stdlib.bitwise
PRIMITIVES["bitwise-and"] = function(a, b) { return (a & b) | 0; };
PRIMITIVES["bitwise-or"] = function(a, b) { return (a | b) | 0; };
PRIMITIVES["bitwise-xor"] = function(a, b) { return (a ^ b) | 0; };
PRIMITIVES["bitwise-not"] = function(a) { return ~a; };
PRIMITIVES["arithmetic-shift"] = function(a, count) {
return count >= 0 ? (a << count) | 0 : a >> (-count);
};
PRIMITIVES["bit-count"] = function(a) {
var n = Math.abs(a) >>> 0;
n = n - ((n >> 1) & 0x55555555);
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
return (((n + (n >> 4)) & 0x0f0f0f0f) * 0x01010101) >>> 24;
};
PRIMITIVES["integer-length"] = function(a) {
if (a === 0) return 0;
return 32 - Math.clz32(Math.abs(a));
};
''',
}
# Modules to include by default (all)
_ALL_JS_MODULES = list(PRIMITIVES_JS_MODULES.keys())

View File

@@ -2007,4 +2007,49 @@ let () =
| [rx] ->
let (_, _, flags) = regex_of_value rx in
String flags
| _ -> raise (Eval_error "regex-flags: (regex)"))
| _ -> raise (Eval_error "regex-flags: (regex)"));
(* Bitwise operations *)
register "bitwise-and" (fun args ->
match args with
| [Integer a; Integer b] -> Integer (a land b)
| _ -> raise (Eval_error "bitwise-and: expected (integer integer)"));
register "bitwise-or" (fun args ->
match args with
| [Integer a; Integer b] -> Integer (a lor b)
| _ -> raise (Eval_error "bitwise-or: expected (integer integer)"));
register "bitwise-xor" (fun args ->
match args with
| [Integer a; Integer b] -> Integer (a lxor b)
| _ -> raise (Eval_error "bitwise-xor: expected (integer integer)"));
register "bitwise-not" (fun args ->
match args with
| [Integer a] -> Integer (lnot a)
| _ -> raise (Eval_error "bitwise-not: expected (integer)"));
register "arithmetic-shift" (fun args ->
match args with
| [Integer a; Integer count] ->
Integer (if count >= 0 then a lsl count else a asr (-count))
| _ -> raise (Eval_error "arithmetic-shift: expected (integer integer)"));
register "bit-count" (fun args ->
match args with
| [Integer a] ->
let n = ref (abs a) in
let c = ref 0 in
while !n <> 0 do
c := !c + (!n land 1);
n := !n lsr 1
done;
Integer !c
| _ -> raise (Eval_error "bit-count: expected (integer)"));
register "integer-length" (fun args ->
match args with
| [Integer a] ->
let n = ref (abs a) in
let bits = ref 0 in
while !n <> 0 do
incr bits;
n := !n lsr 1
done;
Integer !bits
| _ -> raise (Eval_error "integer-length: expected (integer)"))