Skip to content

Instantly share code, notes, and snippets.

@puckipedia
Created November 28, 2019 21:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save puckipedia/7c8ecbb391c397dbdaeb88a781fac447 to your computer and use it in GitHub Desktop.
Save puckipedia/7c8ecbb391c397dbdaeb88a781fac447 to your computer and use it in GitHub Desktop.
quantum nix 2.0
with builtins; let
storePathHash = name: contents: hashString "sha256" "text:sha256:${hashString "sha256" contents}:/nix/store:${name}";
hexToDecimal = hex: assert ((stringLength hex) / 2) * 2 == (stringLength hex);
let
nibble = w: if w == "0" then 0
else if w == "1" then 1
else if w == "2" then 2
else if w == "3" then 3
else if w == "4" then 4
else if w == "5" then 5
else if w == "6" then 6
else if w == "7" then 7
else if w == "8" then 8
else if w == "9" then 9
else if w == "a" then 10
else if w == "b" then 11
else if w == "c" then 12
else if w == "d" then 13
else if w == "e" then 14
else if w == "f" then 15
else -1;
byte = w: (nibble (substring 0 1 w)) * 16 + (nibble (substring 1 1 w));
in
genList (a: byte (substring (a * 2) 2 hex)) ((stringLength hex) / 2);
shiftLeft = i: value: if i == 0 then value else (shiftLeft (i - 1) (value * 2));
shiftRight = i: value: if i == 0 then value else (shiftRight (i - 1) (value / 2));
decimalToBase32 = val: let
decimalToBase32Byte = i: let
offsetBits = i * 5;
byteIndex = (offsetBits / 8);
offset = offsetBits - (byteIndex * 8);
firstByte = shiftRight offset (elemAt val byteIndex);
secondByte = shiftLeft (8 - offset)
(if byteIndex >= (length val) - 1 then 0 else (elemAt val (byteIndex + 1)));
value = bitAnd 31 (bitOr firstByte secondByte);
in substring value 1 "0123456789abcdfghijklmnpqrsvwxyz";
len = ((length val) * 8 - 1) / 5 + 1;
chars = genList (a: decimalToBase32Byte (len - 1 - a)) len;
in concatStringsSep "" chars;
compress = outLength: hash:
let
hashLen = (length hash);
forByte = i:
let
count = ((hashLen - i + outLength - 1) / outLength);
toXor = genList (j: elemAt hash (i + (outLength * j))) count;
in
foldl' bitXor 0 toXor;
in
genList forByte outLength;
in
name: contents:
let
hash = storePathHash name contents;
base32 = decimalToBase32 (compress 20 (hexToDecimal hash));
in
"/nix/store/${base32}-${name}"
with builtins; let
filePath = import ./hash.nix;
availableFuseIndex = i:
let
hash = filePath "quantum-fuse" "root-${toString i}";
in
if pathExists hash then (availableFuseIndex (i + 1)) else seq (toFile "quantum-fuse" "root-${toString i}") i;
fuseExists = fuse: index: pathExists (filePath "quantum-fuse" "chain-${toString fuse}-${toString index}");
writeFuse = fuse: index: seq (toFile "quantum-fuse" "chain-${toString fuse}-${toString index}") null;
in rec {
# A fuse. Like a fuse, it can be blown exactly once.
fuse = value:
let
fuseIndex = availableFuseIndex 0;
in
{
isBlown = _: fuseExists fuseIndex 0;
blowFuse = _: deepSeq (writeFuse fuseIndex 0) value;
};
# A breaker, which can be set, reset, and flipped at will.
breaker = _:
let
fuseIndex = availableFuseIndex 0;
unblownIndex = val: if fuseExists fuseIndex val then unblownIndex (val + 1) else val;
in
rec {
getState = _: let index = unblownIndex 0; in (index / 2) * 2 == index;
flip = _: let index = unblownIndex 0; in deepSeq (writeFuse fuseIndex index) ((index / 2) * 2 == index);
setState = state: if (getState null) != state then flip null else state;
flipCount = _: unblownIndex 0;
};
# Uses 64 breakers to store a single (positive, so actually 63 bit) integer.
quantumNumber = initial:
let
breakers = genList breaker 64;
findBit = num: n: if n == 0 then (bitAnd 1 num) == 1 else (findBit (num / 2) (n - 1));
toBits = num: assert isInt num && num >= 0; genList (a: findBit num (63 - a)) 64;
fromBits = bits: foldl' (a: b: a * 2 + (if b then 1 else 0)) 0 bits;
flipBreakers = num:
let
bits = toBits num;
processed = toJSON (genList (n: (elemAt breakers n).setState (elemAt bits n)) 64);
in
seq processed null;
checkBreakers = _: fromBits (map (a: a.getState null) breakers);
in
seq (flipBreakers initial) {
setValue = flipBreakers;
getValue = checkBreakers;
};
# Builds on top of the fuse to create a `once` -- the first time the resulting lambda is called, it will call the first argument.
# Every other time it calls the second one.
once = first: other: let
ownFuse = (fuse 0);
in value:
if ownFuse.isBlown null then
(other value)
else
seq (ownFuse.blowFuse null) (first value);
# Returns a lambda that increments a number every time it is called.
counter = start: let ownBreaker = (breaker null); in _: seq (ownBreaker.flip null) (ownBreaker.flipCount null) + start;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment