diff options
Diffstat (limited to 'users/sterni/nix')
-rw-r--r-- | users/sterni/nix/build/buildGopherHole/default.nix | 109 | ||||
-rw-r--r-- | users/sterni/nix/char/tests/default.nix | 6 | ||||
-rw-r--r-- | users/sterni/nix/float/default.nix | 23 | ||||
-rw-r--r-- | users/sterni/nix/float/tests/default.nix | 49 | ||||
-rw-r--r-- | users/sterni/nix/fun/default.nix | 14 | ||||
-rw-r--r-- | users/sterni/nix/html/tests/default.nix | 2 | ||||
-rw-r--r-- | users/sterni/nix/int/default.nix | 38 | ||||
-rw-r--r-- | users/sterni/nix/int/tests/default.nix | 42 | ||||
-rw-r--r-- | users/sterni/nix/list/default.nix | 30 | ||||
-rw-r--r-- | users/sterni/nix/num/default.nix | 17 | ||||
-rw-r--r-- | users/sterni/nix/num/tests/default.nix | 26 | ||||
-rw-r--r-- | users/sterni/nix/string/default.nix | 1 | ||||
-rw-r--r-- | users/sterni/nix/utf8/default.nix | 27 |
13 files changed, 310 insertions, 74 deletions
diff --git a/users/sterni/nix/build/buildGopherHole/default.nix b/users/sterni/nix/build/buildGopherHole/default.nix new file mode 100644 index 0000000000..eec13a8654 --- /dev/null +++ b/users/sterni/nix/build/buildGopherHole/default.nix @@ -0,0 +1,109 @@ +{ depot, pkgs, lib, ... }: + +let + inherit (pkgs) + runCommand + writeText + ; + + inherit (depot.users.sterni.nix.build) + buildGopherHole + ; + + fileTypes = { + # RFC1436 + text = "0"; + menu = "1"; + cso = "2"; + error = "3"; + binhex = "4"; + dos = "5"; + uuencoded = "6"; + index-server = "7"; + telnet = "8"; + binary = "9"; + mirror = "+"; + gif = "g"; + image = "I"; + tn3270 = "T"; + # non-standard + info = "i"; + html = "h"; + }; + + buildFile = { file, name, fileType ? fileTypes.text }: + runCommand name + { + passthru = { + # respect the file type the file derivation passes + # through. otherwise use explicitly set type or + # default value. + fileType = file.fileType or fileType; + }; + } '' + ln -s ${file} "$out" + ''; + + buildGopherMap = dir: + let + /* strings constitute an info line or an empty line + if their length is zero. sets that contain a menu + value have that added to the gophermap as-is. + + all other entries should be a set which can be built using + buildGopherHole and is linked by their name. The resulting + derivation is expected to passthru a fileType containing the + gopher file type char of themselves. + */ + gopherMapLine = e: + if builtins.isString e + then e + else if e ? menu + then e.menu + else + let + drv = buildGopherHole e; + title = e.title or e.name; + in + "${drv.fileType}${title}\t${drv.name}"; + in + writeText ".gophermap" (lib.concatMapStringsSep "\n" gopherMapLine dir); + + buildDir = + { dir, name, ... }: + + let + # filter all entries out that have to be symlinked: + # sets with the file or dir attribute + drvOnly = builtins.map buildGopherHole (builtins.filter + (x: !(builtins.isString x) && (x ? dir || x ? file)) + dir); + gopherMap = buildGopherMap dir; + in + runCommand name + { + passthru = { + fileType = fileTypes.dir; + }; + } + ('' + mkdir -p "$out" + ln -s "${gopherMap}" "$out/.gophermap" + '' + lib.concatMapStrings + (drv: '' + ln -s "${drv}" "$out/${drv.name}" + '') + drvOnly); +in + +{ + # Dispatch into different file / dir handling code + # which is mutually recursive with this function. + __functor = _: args: + if args ? file then buildFile args + else if args ? dir then buildDir args + else builtins.throw "Unrecognized gopher hole item type: " + + lib.generators.toPretty { } args; + + inherit fileTypes; +} diff --git a/users/sterni/nix/char/tests/default.nix b/users/sterni/nix/char/tests/default.nix index 313df47451..cb17b74c57 100644 --- a/users/sterni/nix/char/tests/default.nix +++ b/users/sterni/nix/char/tests/default.nix @@ -10,7 +10,7 @@ let inherit (depot.users.sterni.nix) char string - int + num fun ; @@ -18,10 +18,10 @@ let testAllCharConversion = it "tests conversion of all chars" [ (assertEq "char.chr converts to char.allChars" - (builtins.genList (fun.rl char.chr (int.add 1)) 255) + (builtins.genList (fun.rl char.chr (num.add 1)) 255) charList) (assertEq "char.ord converts from char.allChars" - (builtins.genList (int.add 1) 255) + (builtins.genList (num.add 1) 255) (builtins.map char.ord charList)) ]; diff --git a/users/sterni/nix/float/default.nix b/users/sterni/nix/float/default.nix new file mode 100644 index 0000000000..ecb6465c88 --- /dev/null +++ b/users/sterni/nix/float/default.nix @@ -0,0 +1,23 @@ +{ depot, ... }: + +let + inherit (depot.users.sterni.nix) + num + ; +in + +rec { + # In C++ Nix, the required builtins have been added in version 2.4 + ceil = builtins.ceil or (throw "Nix implementation is missing builtins.ceil"); + floor = builtins.floor or (throw "Nix implementation is missing builtins.floor"); + + truncate = f: if f >= 0 then floor f else ceil f; + round = f: + let + s = num.sign f; + a = s * f; + in + s * (if a >= floor a + 0.5 then ceil a else floor a); + + intToFloat = i: i * 1.0; +} diff --git a/users/sterni/nix/float/tests/default.nix b/users/sterni/nix/float/tests/default.nix new file mode 100644 index 0000000000..75e2a1bfa0 --- /dev/null +++ b/users/sterni/nix/float/tests/default.nix @@ -0,0 +1,49 @@ +{ depot, lib, ... }: + +let + + inherit (depot.nix.runTestsuite) + runTestsuite + it + assertEq + ; + + inherit (depot.users.sterni.nix) + float + ; + + testsBuiltins = it "tests builtin operations" [ + (assertEq "ceil pos" (float.ceil 1.5) 2) + (assertEq "ceil neg" (float.ceil (-1.5)) (-1)) + (assertEq "floor pos" (float.floor 1.5) 1) + (assertEq "floor neg" (float.floor (-1.5)) (-2)) + ]; + + testsConversionFrom = it "tests integer to float conversion" [ + (assertEq "float.intToFloat is identity for floats" (float.intToFloat 1.3) 1.3) + (assertEq "float.intToFloat converts ints" + (builtins.all + (val: builtins.isFloat val) + (builtins.map float.intToFloat (builtins.genList (i: i - 500) 1000))) + true) + ]; + + exampleFloats = [ 0.5 0.45 0.3 0.1 200 203.457847 204.65547 (-1.5) (-2) (-1.3) (-0.45) ]; + testsConversionTo = it "tests float to integer conversion" [ + (assertEq "round" + (builtins.map float.round exampleFloats) + [ 1 0 0 0 200 203 205 (-2) (-2) (-1) 0 ]) + (assertEq "truncate towards zero" + (builtins.map float.truncate exampleFloats) + [ 0 0 0 0 200 203 204 (-1) (-2) (-1) 0 ]) + ]; +in + +runTestsuite "nix.num" ([ + testsConversionFrom +] + # Skip for e.g. C++ Nix < 2.4 +++ lib.optionals (builtins ? ceil && builtins ? floor) [ + testsConversionTo + testsBuiltins +]) diff --git a/users/sterni/nix/fun/default.nix b/users/sterni/nix/fun/default.nix index bb10f9e6c1..824cebfed2 100644 --- a/users/sterni/nix/fun/default.nix +++ b/users/sterni/nix/fun/default.nix @@ -192,20 +192,18 @@ let # and the list of arguments to pass to be found in args. startSet = [ { - key = "0"; - id = 0; + key = 0; final = false; inherit args; } ]; operator = - { id, final, ... }@state: + { key, final, ... }@state: let # Plumbing to make genericClosure happy - newIds = { - key = toString (id + 1); - id = id + 1; + newId = { + key = key + 1; }; # Perform recursion step @@ -215,10 +213,10 @@ let # otherwise signal that we're done. newState = if builtins.isAttrs call && call.__tailCall or false - then newIds // { + then newId // { final = false; inherit (call) args; - } else newIds // { + } else newId // { final = true; value = call; }; diff --git a/users/sterni/nix/html/tests/default.nix b/users/sterni/nix/html/tests/default.nix index 0d80f2f1cd..ed520675c5 100644 --- a/users/sterni/nix/html/tests/default.nix +++ b/users/sterni/nix/html/tests/default.nix @@ -75,7 +75,7 @@ let ]); in -pkgs.runCommandNoCC "html.nix.html" +pkgs.runCommand "html.nix.html" { passAsFile = [ "exampleDocument" ]; inherit exampleDocument; diff --git a/users/sterni/nix/int/default.nix b/users/sterni/nix/int/default.nix index 54b5596472..8707445223 100644 --- a/users/sterni/nix/int/default.nix +++ b/users/sterni/nix/int/default.nix @@ -2,37 +2,28 @@ let - # TODO(sterni): implement nix.float and figure out which of these - # functions can be split out into a common nix.num - # library. - inherit (depot.users.sterni.nix) string + num ; inherit (builtins) bitOr bitAnd bitXor - mul - div - add - sub ; - abs = i: if i < 0 then -i else i; - exp = base: pow: if pow > 0 then base * (exp base (pow - 1)) else if pow < 0 - then 1.0 / exp base (abs pow) + then 1.0 / exp base (num.abs pow) else 1; bitShiftR = bit: count: if count == 0 then bit - else div (bitShiftR bit (count - 1)) 2; + else (bitShiftR bit (count - 1)) / 2; bitShiftL = bit: count: if count == 0 @@ -52,7 +43,7 @@ let in if int == 0 then "0" - else "${sign}${go (abs int)}"; + else "${sign}${go (num.abs int)}"; fromHexMap = builtins.listToAttrs (lib.imap0 (i: c: { name = c; value = i; }) @@ -94,26 +85,24 @@ let odd = x: bitAnd x 1 == 1; even = x: bitAnd x 1 == 0; - # div and mod behave like quot and rem in Haskell, - # i. e. they truncate towards 0 - mod = a: b: let res = a / b; in a - (res * b); - - inRange = a: b: x: x >= a && x <= b; + quot' = builtins.div; # no typecheck + rem = a: b: + assert builtins.isInt a && builtins.isInt b; + let res = quot' a b; in a - (res * b); + quot = a: b: + assert builtins.isInt a && builtins.isInt b; + quot' a b; in { inherit maxBound minBound - abs exp odd even - add - sub - mul - div - mod + quot + rem bitShiftR bitShiftL bitOr @@ -121,6 +110,5 @@ in bitXor toHex fromHex - inRange ; } diff --git a/users/sterni/nix/int/tests/default.nix b/users/sterni/nix/int/tests/default.nix index 8d2263b421..80bd05b6b5 100644 --- a/users/sterni/nix/int/tests/default.nix +++ b/users/sterni/nix/int/tests/default.nix @@ -15,9 +15,6 @@ let ; testBounds = it "checks minBound and maxBound" [ - # this is gonna blow up in my face because - # integer overflow is undefined behavior in - # C++, so most likely anything could happen? (assertEq "maxBound is the maxBound" true (int.maxBound + 1 < int.maxBound)) (assertEq "minBound is the minBound" true @@ -321,7 +318,6 @@ let testBasic = it "checks basic int operations" [ (assertEq "122 is even" (int.even 122 && !(int.odd 122)) true) (assertEq "123 is odd" (int.odd 123 && !(int.even 123)) true) - (assertEq "abs -4959" (int.abs (-4959)) 4959) ]; expNumbers = [ @@ -369,12 +365,12 @@ let checkShiftRDivExp = n: assertEq "${toString n} >> 5 == ${toString n} / 2 ^ 5" (int.bitShiftR n 5) - (int.div n (int.exp 2 5)); + (n / (int.exp 2 5)); checkShiftLMulExp = n: assertEq "${toString n} >> 6 == ${toString n} * 2 ^ 6" (int.bitShiftL n 5) - (int.mul n (int.exp 2 5)); + (n * (int.exp 2 5)); testBit = it "checks bitwise operations" (lib.flatten [ (builtins.map checkShift shifts) @@ -410,40 +406,40 @@ let ]); divisions = [ - { a = 2; b = 1; c = 2; mod = 0; } - { a = 2; b = 2; c = 1; mod = 0; } - { a = 20; b = 10; c = 2; mod = 0; } - { a = 12; b = 5; c = 2; mod = 2; } - { a = 23; b = 4; c = 5; mod = 3; } + { a = 2; b = 1; c = 2; rem = 0; } + { a = 2; b = 2; c = 1; rem = 0; } + { a = 20; b = 10; c = 2; rem = 0; } + { a = 12; b = 5; c = 2; rem = 2; } + { a = 23; b = 4; c = 5; rem = 3; } ]; - checkDiv = n: { a, b, c, mod }: [ - (assertEq "${n}: div result" (int.div a b) c) - (assertEq "${n}: mod result" (int.mod a b) mod) - (assertEq "${n}: divMod law" ((int.div a b) * b + (int.mod a b)) a) + checkQuot = n: { a, b, c, rem }: [ + (assertEq "${n}: quot result" (int.quot a b) c) + (assertEq "${n}: rem result" (int.rem a b) rem) + (assertEq "${n}: quotRem law" ((int.quot a b) * b + (int.rem a b)) a) ]; - testDivMod = it "checks integer division and modulo" + testQuotRem = it "checks integer quotient and remainder" (lib.flatten [ - (builtins.map (checkDiv "+a / +b") divisions) + (builtins.map (checkQuot "+a / +b") divisions) (builtins.map - (fun.rl (checkDiv "-a / +b") (x: x // { + (fun.rl (checkQuot "-a / +b") (x: x // { a = -x.a; c = -x.c; - mod = -x.mod; + rem = -x.rem; })) divisions) (builtins.map - (fun.rl (checkDiv "+a / -b") (x: x // { + (fun.rl (checkQuot "+a / -b") (x: x // { b = -x.b; c = -x.c; })) divisions) (builtins.map - (fun.rl (checkDiv "-a / -b") (x: x // { + (fun.rl (checkQuot "-a / -b") (x: x // { a = -x.a; b = -x.b; - mod = -x.mod; + rem = -x.rem; })) divisions) ]); @@ -455,5 +451,5 @@ runTestsuite "nix.int" [ testBasic testExp testBit - testDivMod + testQuotRem ] diff --git a/users/sterni/nix/list/default.nix b/users/sterni/nix/list/default.nix new file mode 100644 index 0000000000..568a76d637 --- /dev/null +++ b/users/sterni/nix/list/default.nix @@ -0,0 +1,30 @@ +{ ... }: + +{ + /* For a list of length n that consists of lists of length m, + return a list of length m containing lists of length n + so that + + builtins.elemAt (builtins.elemAt orig a) b + == builtins.elemAt (builtins.elemAt transposed b) a + + Essentially, if you think of the nested list as an array with two + dimensions, the two index axes are swapped. + + The length of the inner lists m is determined based on the first element + and assumed to be used for all other lists. Malformed input data may + cause the function to crash or lose data. + + Type: <n>[ <m>[ ] ] -> <m>[ <n>[ ] ] + */ + transpose = list: + let + innerLength = builtins.length (builtins.head list); + outerLength = builtins.length list; + in + builtins.genList + (inner: builtins.genList + (outer: builtins.elemAt (builtins.elemAt list outer) inner) + outerLength) + innerLength; +} diff --git a/users/sterni/nix/num/default.nix b/users/sterni/nix/num/default.nix new file mode 100644 index 0000000000..81e2f8377f --- /dev/null +++ b/users/sterni/nix/num/default.nix @@ -0,0 +1,17 @@ +{ ... }: + +rec { + inherit (builtins) + mul + div + add + sub + ; + + sign = i: if i < 0 then -1 else 1; + abs = i: if i < 0 then -i else i; + + inRange = a: b: x: x >= a && x <= b; + + sum = builtins.foldl' (a: b: a + b) 0; +} diff --git a/users/sterni/nix/num/tests/default.nix b/users/sterni/nix/num/tests/default.nix new file mode 100644 index 0000000000..ca5f861deb --- /dev/null +++ b/users/sterni/nix/num/tests/default.nix @@ -0,0 +1,26 @@ +{ depot, ... }: + +let + + inherit (depot.nix.runTestsuite) + runTestsuite + it + assertEq + ; + + inherit (depot.users.sterni.nix) + num + ; + + testsBasic = it "tests basic operations" [ + (assertEq "abs -4959" (num.abs (-4959)) 4959) + (assertEq "sum" (num.sum [ 123 321 1.5 ]) (123 + 321 + 1.5)) + (assertEq "inRange" + (builtins.map (num.inRange 1.0 5) [ 0 0.5 3 4 4.5 5.5 5 6 ]) + [ false false true true true false true false ]) + ]; +in + +runTestsuite "nix.num" [ + testsBasic +] diff --git a/users/sterni/nix/string/default.nix b/users/sterni/nix/string/default.nix index 852ef2538f..381c8ddff7 100644 --- a/users/sterni/nix/string/default.nix +++ b/users/sterni/nix/string/default.nix @@ -87,7 +87,6 @@ let ({ out ? "", argIndex ? 0 }: token: { argIndex = argIndex + (if specifierWithArg token then 1 else 0); out = - /**/ if token == "%s" then out + builtins.elemAt args argIndex else if token == "%%" then out + "%" else if isSpecifier token then throw "Unsupported format specifier ${token}" diff --git a/users/sterni/nix/utf8/default.nix b/users/sterni/nix/utf8/default.nix index 71c846c042..e76695f128 100644 --- a/users/sterni/nix/utf8/default.nix +++ b/users/sterni/nix/utf8/default.nix @@ -6,6 +6,7 @@ let char flow fun + num int string util @@ -46,17 +47,17 @@ let # byte position as an index starting with 0 pos: let - defaultRange = int.inRange 128 191; + defaultRange = num.inRange 128 191; secondBytePredicate = flow.switch first [ - [ (int.inRange 194 223) defaultRange ] # C2..DF - [ 224 (int.inRange 160 191) ] # E0 - [ (int.inRange 225 236) defaultRange ] # E1..EC - [ 237 (int.inRange 128 159) ] # ED - [ (int.inRange 238 239) defaultRange ] # EE..EF - [ 240 (int.inRange 144 191) ] # F0 - [ (int.inRange 241 243) defaultRange ] # F1..F3 - [ 244 (int.inRange 128 143) ] # F4 + [ (num.inRange 194 223) defaultRange ] # C2..DF + [ 224 (num.inRange 160 191) ] # E0 + [ (num.inRange 225 236) defaultRange ] # E1..EC + [ 237 (num.inRange 128 159) ] # ED + [ (num.inRange 238 239) defaultRange ] # EE..EF + [ 240 (num.inRange 144 191) ] # F0 + [ (num.inRange 241 243) defaultRange ] # F1..F3 + [ 244 (num.inRange 128 143) ] # F4 [ (fun.const true) null ] ]; @@ -225,10 +226,10 @@ let # Note that this doesn't check if the Unicode codepoint is allowed, # but rather allows all theoretically UTF-8-encodeable ones. count = flow.switch cp [ - [ (int.inRange 0 127) 1 ] # 00000000 0xxxxxxx - [ (int.inRange 128 2047) 2 ] # 00000yyy yyxxxxxx - [ (int.inRange 2048 65535) 3 ] # zzzzyyyy yyxxxxxx - [ (int.inRange 65536 1114111) 4 ] # 000uuuuu zzzzyyyy yyxxxxxx, + [ (num.inRange 0 127) 1 ] # 00000000 0xxxxxxx + [ (num.inRange 128 2047) 2 ] # 00000yyy yyxxxxxx + [ (num.inRange 2048 65535) 3 ] # zzzzyyyy yyxxxxxx + [ (num.inRange 65536 1114111) 4 ] # 000uuuuu zzzzyyyy yyxxxxxx, # capped at U+10FFFF [ (fun.const true) (builtins.throw invalidCodepointMsg) ] |