diff --git a/haskell-experiments/.direnv/bin/nix-direnv-reload b/haskell-experiments/.direnv/bin/nix-direnv-reload
new file mode 100755
index 0000000..e8f3a5d
--- /dev/null
+++ b/haskell-experiments/.direnv/bin/nix-direnv-reload
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+set -e
+if [[ ! -d "/home/felix/projects/pyrites/haskell-experiments" ]]; then
+ echo "Cannot find source directory; Did you move it?"
+ echo "(Looking for "/home/felix/projects/pyrites/haskell-experiments")"
+ echo 'Cannot force reload with this script - use "direnv reload" manually and then try again'
+ exit 1
+fi
+
+# rebuild the cache forcefully
+_nix_direnv_force_reload=1 direnv exec "/home/felix/projects/pyrites/haskell-experiments" true
+
+# Update the mtime for .envrc.
+# This will cause direnv to reload again - but without re-building.
+touch "/home/felix/projects/pyrites/haskell-experiments/.envrc"
+
+# Also update the timestamp of whatever profile_rc we have.
+# This makes sure that we know we are up to date.
+touch -r "/home/felix/projects/pyrites/haskell-experiments/.envrc" "/home/felix/projects/pyrites/haskell-experiments/.direnv"/*.rc
diff --git a/haskell-experiments/.direnv/nix-profile-.3357.d351d0653aeb b/haskell-experiments/.direnv/nix-profile-.3357.d351d0653aeb
new file mode 120000
index 0000000..81277b9
--- /dev/null
+++ b/haskell-experiments/.direnv/nix-profile-.3357.d351d0653aeb
@@ -0,0 +1 @@
+/nix/store/yh4sq3dlkly5x6szw95xn5nlw4rn9xz3-ghc-shell-for-haskell-exps-0.1.0.0-0-env
\ No newline at end of file
diff --git a/haskell-experiments/.direnv/nix-profile-.3357.d351d0653aeb.rc b/haskell-experiments/.direnv/nix-profile-.3357.d351d0653aeb.rc
new file mode 100644
index 0000000..0b5405f
--- /dev/null
+++ b/haskell-experiments/.direnv/nix-profile-.3357.d351d0653aeb.rc
@@ -0,0 +1,2132 @@
+unset shellHook
+PATH=${PATH:-}
+nix_saved_PATH="$PATH"
+XDG_DATA_DIRS=${XDG_DATA_DIRS:-}
+nix_saved_XDG_DATA_DIRS="$XDG_DATA_DIRS"
+AR='ar'
+export AR
+AS='as'
+export AS
+BASH='/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash'
+CC='gcc'
+export CC
+CONFIG_SHELL='/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash'
+export CONFIG_SHELL
+CXX='g++'
+export CXX
+HOSTTYPE='x86_64'
+HOST_PATH='/nix/store/yijhn548p2589pkybgvbhll09bqsxy0q-ncurses-6.5/bin:/nix/store/gdni20c8009xdz8gms6yn1r2hfhmk1jk-numactl-2.0.18/bin:/nix/store/imad8dvhp77h0pjbckp6wvmnyhp8dpgg-coreutils-9.8/bin:/nix/store/av4xw9f56xlx5pgv862wabfif6m1yc0a-findutils-4.10.0/bin:/nix/store/20axvl7mgj15m23jgmnq97hx37fgz7bk-diffutils-3.12/bin:/nix/store/drc7kang929jaza6cy9zdx10s4gw1z5p-gnused-4.9/bin:/nix/store/x3zjxxz8m4ki88axp0gn8q8m6bldybba-gnugrep-3.12/bin:/nix/store/y2wdhdcrffp9hnkzk06d178hq3g98jay-gawk-5.3.2/bin:/nix/store/yi3c5karhx764ham5rfwk7iynr8mjf6q-gnutar-1.35/bin:/nix/store/d471xb7sfbah076s8rx02i68zpxc2r5n-gzip-1.14/bin:/nix/store/qm9rxn2sc1vrz91i443rr6f0vxm0zd82-bzip2-1.0.8-bin/bin:/nix/store/3fmzbq9y4m9nk235il7scmvwn8j9zy3p-gnumake-4.4.1/bin:/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin:/nix/store/qrwznp1ikdf0qw05wia2haiwi32ik5n0-patch-2.8/bin:/nix/store/v0rfdwhg6w6i0yb6dbry4srk6pnj3xp0-xz-5.8.1-bin/bin:/nix/store/paj6a1lpzp57hz1djm5bs86b7ci221r0-file-5.45/bin'
+export HOST_PATH
+IFS='
+'
+IN_NIX_SHELL='impure'
+export IN_NIX_SHELL
+LANG='en_US.UTF-8'
+export LANG
+LD='ld'
+export LD
+LINENO='76'
+LOCALE_ARCHIVE='/nix/store/hjlkypp9lpxwzsjycpy7nqg2mnl7qhzv-glibc-locales-2.40-66/lib/locale/locale-archive'
+export LOCALE_ARCHIVE
+MACHTYPE='x86_64-pc-linux-gnu'
+NIX_BINTOOLS='/nix/store/xwydcyvlsa3cvssk0y5llgdhlhjvmqdm-binutils-wrapper-2.44'
+export NIX_BINTOOLS
+NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu='1'
+export NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
+NIX_BUILD_CORES='24'
+export NIX_BUILD_CORES
+NIX_CC='/nix/store/vr15iyyykg9zai6fpgvhcgyw7gckl78w-gcc-wrapper-14.3.0'
+export NIX_CC
+NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu='1'
+export NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
+NIX_CFLAGS_COMPILE=' -frandom-seed=yh4sq3dlkl'
+export NIX_CFLAGS_COMPILE
+NIX_ENFORCE_NO_NATIVE='1'
+export NIX_ENFORCE_NO_NATIVE
+NIX_GHC='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages/bin/ghc'
+export NIX_GHC
+NIX_GHCPKG='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages/bin/ghc-pkg'
+export NIX_GHCPKG
+NIX_GHC_DOCDIR='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages/share/doc/ghc/html'
+export NIX_GHC_DOCDIR
+NIX_GHC_LIBDIR='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages/lib/ghc-9.10.3/lib'
+export NIX_GHC_LIBDIR
+NIX_HARDENING_ENABLE='bindnow format fortify fortify3 libcxxhardeningextensive libcxxhardeningfast pic relro stackclashprotection stackprotector strictoverflow zerocallusedregs'
+export NIX_HARDENING_ENABLE
+NIX_LDFLAGS='-rpath /home/felix/projects/pyrites/haskell-parsing/outputs/out/lib -L/nix/store/yijhn548p2589pkybgvbhll09bqsxy0q-ncurses-6.5/lib -L/nix/store/b9p0zpa93hwvh4d0r1rmgc2500yx2ldn-libffi-3.5.2/lib -L/nix/store/bkicgvyymba52ijm1z5zs96dsqqi59lp-elfutils-0.194/lib -L/nix/store/54jkwsavi3fdciqfyjmbilq0jhvv4jga-gmp-with-cxx-6.3.0/lib -L/nix/store/gdni20c8009xdz8gms6yn1r2hfhmk1jk-numactl-2.0.18/lib -L/nix/store/yijhn548p2589pkybgvbhll09bqsxy0q-ncurses-6.5/lib -L/nix/store/b9p0zpa93hwvh4d0r1rmgc2500yx2ldn-libffi-3.5.2/lib -L/nix/store/bkicgvyymba52ijm1z5zs96dsqqi59lp-elfutils-0.194/lib -L/nix/store/54jkwsavi3fdciqfyjmbilq0jhvv4jga-gmp-with-cxx-6.3.0/lib -L/nix/store/gdni20c8009xdz8gms6yn1r2hfhmk1jk-numactl-2.0.18/lib'
+export NIX_LDFLAGS
+NIX_NO_SELF_RPATH='1'
+NIX_STORE='/nix/store'
+export NIX_STORE
+NM='nm'
+export NM
+OBJCOPY='objcopy'
+export OBJCOPY
+OBJDUMP='objdump'
+export OBJDUMP
+OLDPWD=''
+export OLDPWD
+OPTERR='1'
+OSTYPE='linux-gnu'
+PATH='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages/bin:/nix/store/ck6g9qnipfxipqraq6avjqayf01cax7s-hspec-discover-2.11.14/bin:/nix/store/5si9l7s9w09xi1wnfpf5r85am2shxz0i-haskell-language-server-2.12.0.0/bin:/nix/store/qvnkv8qa1z18nj573541i8182hpb80b0-cabal-install-3.16.0.0/bin:/nix/store/8q2582rd22xp8jlcg1xn1w219q5lx5xa-patchelf-0.15.2/bin:/nix/store/vr15iyyykg9zai6fpgvhcgyw7gckl78w-gcc-wrapper-14.3.0/bin:/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/bin:/nix/store/q6wgv06q39bfhx2xl8ysc05wi6m2zdss-glibc-2.40-66-bin/bin:/nix/store/imad8dvhp77h0pjbckp6wvmnyhp8dpgg-coreutils-9.8/bin:/nix/store/xwydcyvlsa3cvssk0y5llgdhlhjvmqdm-binutils-wrapper-2.44/bin:/nix/store/dc9vaz50jg7mibk9xvqw5dqv89cxzla3-binutils-2.44/bin:/nix/store/yijhn548p2589pkybgvbhll09bqsxy0q-ncurses-6.5/bin:/nix/store/gdni20c8009xdz8gms6yn1r2hfhmk1jk-numactl-2.0.18/bin:/nix/store/imad8dvhp77h0pjbckp6wvmnyhp8dpgg-coreutils-9.8/bin:/nix/store/av4xw9f56xlx5pgv862wabfif6m1yc0a-findutils-4.10.0/bin:/nix/store/20axvl7mgj15m23jgmnq97hx37fgz7bk-diffutils-3.12/bin:/nix/store/drc7kang929jaza6cy9zdx10s4gw1z5p-gnused-4.9/bin:/nix/store/x3zjxxz8m4ki88axp0gn8q8m6bldybba-gnugrep-3.12/bin:/nix/store/y2wdhdcrffp9hnkzk06d178hq3g98jay-gawk-5.3.2/bin:/nix/store/yi3c5karhx764ham5rfwk7iynr8mjf6q-gnutar-1.35/bin:/nix/store/d471xb7sfbah076s8rx02i68zpxc2r5n-gzip-1.14/bin:/nix/store/qm9rxn2sc1vrz91i443rr6f0vxm0zd82-bzip2-1.0.8-bin/bin:/nix/store/3fmzbq9y4m9nk235il7scmvwn8j9zy3p-gnumake-4.4.1/bin:/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin:/nix/store/qrwznp1ikdf0qw05wia2haiwi32ik5n0-patch-2.8/bin:/nix/store/v0rfdwhg6w6i0yb6dbry4srk6pnj3xp0-xz-5.8.1-bin/bin:/nix/store/paj6a1lpzp57hz1djm5bs86b7ci221r0-file-5.45/bin'
+export PATH
+PS4='+ '
+RANLIB='ranlib'
+export RANLIB
+READELF='readelf'
+export READELF
+SHELL='/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash'
+export SHELL
+SIZE='size'
+export SIZE
+SOURCE_DATE_EPOCH='315532800'
+export SOURCE_DATE_EPOCH
+STRINGS='strings'
+export STRINGS
+STRIP='strip'
+export STRIP
+XDG_DATA_DIRS='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages/share:/nix/store/qvnkv8qa1z18nj573541i8182hpb80b0-cabal-install-3.16.0.0/share:/nix/store/8q2582rd22xp8jlcg1xn1w219q5lx5xa-patchelf-0.15.2/share'
+export XDG_DATA_DIRS
+__structuredAttrs=''
+export __structuredAttrs
+_substituteStream_has_warned_replace_deprecation='false'
+buildCommandPath='/build/.attr-0l2nkwhif96f51f4amnlf414lhl4rv9vh8iffyp431v6s28gsr90'
+export buildCommandPath
+buildInputs=''
+export buildInputs
+builder='/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash'
+export builder
+cmakeFlags=''
+export cmakeFlags
+configureFlags=''
+export configureFlags
+defaultBuildInputs=''
+defaultNativeBuildInputs='/nix/store/8q2582rd22xp8jlcg1xn1w219q5lx5xa-patchelf-0.15.2 /nix/store/l2xk4ac1wx9c95kpp8vymv9r9yn57fvh-update-autotools-gnu-config-scripts-hook /nix/store/0y5xmdb7qfvimjwbq7ibg1xdgkgjwqng-no-broken-symlinks.sh /nix/store/cv1d7p48379km6a85h4zp6kr86brh32q-audit-tmpdir.sh /nix/store/85clx3b0xkdf58jn161iy80y5223ilbi-compress-man-pages.sh /nix/store/wgrbkkaldkrlrni33ccvm3b6vbxzb656-make-symlinks-relative.sh /nix/store/5yzw0vhkyszf2d179m0qfkgxmp5wjjx4-move-docs.sh /nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh /nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh /nix/store/pag6l61paj1dc9sv15l7bm5c17xn5kyk-move-systemd-user-units.sh /nix/store/cmzya9irvxzlkh7lfy6i82gbp0saxqj3-multiple-outputs.sh /nix/store/x8c40nfigps493a07sdr2pm5s9j1cdc0-patch-shebangs.sh /nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh /nix/store/xyff06pkhki3qy1ls77w10s0v79c9il0-reproducible-builds.sh /nix/store/z7k98578dfzi6l3hsvbivzm7hfqlk0zc-set-source-date-epoch-to-latest.sh /nix/store/pilsssjjdxvdphlg2h19p0bfx5q0jzkn-strip.sh /nix/store/vr15iyyykg9zai6fpgvhcgyw7gckl78w-gcc-wrapper-14.3.0'
+depsBuildBuild=''
+export depsBuildBuild
+depsBuildBuildPropagated=''
+export depsBuildBuildPropagated
+depsBuildTarget=''
+export depsBuildTarget
+depsBuildTargetPropagated=''
+export depsBuildTargetPropagated
+depsHostHost=''
+export depsHostHost
+depsHostHostPropagated=''
+export depsHostHostPropagated
+depsTargetTarget=''
+export depsTargetTarget
+depsTargetTargetPropagated=''
+export depsTargetTargetPropagated
+doCheck=''
+export doCheck
+doInstallCheck=''
+export doInstallCheck
+dontAddDisableDepTrack='1'
+export dontAddDisableDepTrack
+enableParallelBuilding='1'
+export enableParallelBuilding
+enableParallelChecking='1'
+export enableParallelChecking
+enableParallelInstalling='1'
+export enableParallelInstalling
+declare -a envBuildBuildHooks=()
+declare -a envBuildHostHooks=()
+declare -a envBuildTargetHooks=()
+declare -a envHostHostHooks=('ccWrapper_addCVars' 'bintoolsWrapper_addLDVars' )
+declare -a envHostTargetHooks=('ccWrapper_addCVars' 'bintoolsWrapper_addLDVars' )
+declare -a envTargetTargetHooks=()
+declare -a fixupOutputHooks=('if [ -z "${dontPatchELF-}" ]; then patchELF "$prefix"; fi' 'if [[ -z "${noAuditTmpdir-}" && -e "$prefix" ]]; then auditTmpdir "$prefix"; fi' 'if [ -z "${dontGzipMan-}" ]; then compressManPages "$prefix"; fi' '_moveLib64' '_moveSbin' '_moveSystemdUserUnits' 'patchShebangsAuto' '_pruneLibtoolFiles' '_doStrip' )
+initialPath='/nix/store/imad8dvhp77h0pjbckp6wvmnyhp8dpgg-coreutils-9.8 /nix/store/av4xw9f56xlx5pgv862wabfif6m1yc0a-findutils-4.10.0 /nix/store/20axvl7mgj15m23jgmnq97hx37fgz7bk-diffutils-3.12 /nix/store/drc7kang929jaza6cy9zdx10s4gw1z5p-gnused-4.9 /nix/store/x3zjxxz8m4ki88axp0gn8q8m6bldybba-gnugrep-3.12 /nix/store/y2wdhdcrffp9hnkzk06d178hq3g98jay-gawk-5.3.2 /nix/store/yi3c5karhx764ham5rfwk7iynr8mjf6q-gnutar-1.35 /nix/store/d471xb7sfbah076s8rx02i68zpxc2r5n-gzip-1.14 /nix/store/qm9rxn2sc1vrz91i443rr6f0vxm0zd82-bzip2-1.0.8-bin /nix/store/3fmzbq9y4m9nk235il7scmvwn8j9zy3p-gnumake-4.4.1 /nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3 /nix/store/qrwznp1ikdf0qw05wia2haiwi32ik5n0-patch-2.8 /nix/store/v0rfdwhg6w6i0yb6dbry4srk6pnj3xp0-xz-5.8.1-bin /nix/store/paj6a1lpzp57hz1djm5bs86b7ci221r0-file-5.45'
+mesonFlags=''
+export mesonFlags
+name='ghc-shell-for-haskell-exps-0.1.0.0-0-env'
+export name
+nativeBuildInputs='/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages /nix/store/5si9l7s9w09xi1wnfpf5r85am2shxz0i-haskell-language-server-2.12.0.0 /nix/store/qvnkv8qa1z18nj573541i8182hpb80b0-cabal-install-3.16.0.0'
+export nativeBuildInputs
+out='/home/felix/projects/pyrites/haskell-parsing/outputs/out'
+export out
+outputBin='out'
+outputDev='out'
+outputDevdoc='REMOVE'
+outputDevman='out'
+outputDoc='out'
+outputInclude='out'
+outputInfo='out'
+outputLib='out'
+outputMan='out'
+outputs='out'
+export outputs
+passAsFile='buildCommand'
+export passAsFile
+patches=''
+export patches
+pkg='/nix/store/vr15iyyykg9zai6fpgvhcgyw7gckl78w-gcc-wrapper-14.3.0'
+declare -a pkgsBuildBuild=()
+declare -a pkgsBuildHost=('/nix/store/akjf6m9q6jj1xi422b18rlzsavihsn9z-ghc-9.10.3-with-packages' '/nix/store/y4zpai8n4lljkbd37lm91vgclwy5mss1-hspec-core-2.11.14' '/nix/store/5hm98p022frdgmfrlfzdaxfm0l2imgxc-ansi-terminal-1.1.3' '/nix/store/v40i9pjr6dk0d1h29ljrf11lxx3d571z-ansi-terminal-types-1.1.3' '/nix/store/rl33wldyly5rwr7x8i2lrwgm4dvs9i5j-colour-2.3.6' '/nix/store/0hp69aq6457kpm2abplgm578rppvifz4-call-stack-0.4.0' '/nix/store/87il3qdxaj7gvm44xy53xn2ygl50f43g-haskell-lexer-1.2.1' '/nix/store/2757psbiqvr2afznk0n73mncdpgn7jib-hspec-expectations-0.8.4' '/nix/store/20c3fvkbm68yam91lsxqwgz3027l8zrx-HUnit-1.6.2.0' '/nix/store/9z62vq67hn3q1h7h3g9z7vrgki53vj52-QuickCheck-2.15.0.1' '/nix/store/2w524dah1f344sppc7y9gm928r8j4p3l-random-1.2.1.3' '/nix/store/qwmgqkmvdigbbhc32aq4jqjlxfhjnh3b-splitmix-0.1.3.1' '/nix/store/b1i2xc46c5vsygxslad1fc8w83161fn8-quickcheck-io-0.2.0' '/nix/store/3xc5iiww5vhxn62z3wsi449332cyj6kn-tf-random-0.5' '/nix/store/xrz27qsmayzy18c80ckr4xzpjsn28n3f-primitive-0.9.1.0' '/nix/store/ck6g9qnipfxipqraq6avjqayf01cax7s-hspec-discover-2.11.14' '/nix/store/5si9l7s9w09xi1wnfpf5r85am2shxz0i-haskell-language-server-2.12.0.0' '/nix/store/qvnkv8qa1z18nj573541i8182hpb80b0-cabal-install-3.16.0.0' '/nix/store/8q2582rd22xp8jlcg1xn1w219q5lx5xa-patchelf-0.15.2' '/nix/store/l2xk4ac1wx9c95kpp8vymv9r9yn57fvh-update-autotools-gnu-config-scripts-hook' '/nix/store/0y5xmdb7qfvimjwbq7ibg1xdgkgjwqng-no-broken-symlinks.sh' '/nix/store/cv1d7p48379km6a85h4zp6kr86brh32q-audit-tmpdir.sh' '/nix/store/85clx3b0xkdf58jn161iy80y5223ilbi-compress-man-pages.sh' '/nix/store/wgrbkkaldkrlrni33ccvm3b6vbxzb656-make-symlinks-relative.sh' '/nix/store/5yzw0vhkyszf2d179m0qfkgxmp5wjjx4-move-docs.sh' '/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh' '/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh' '/nix/store/pag6l61paj1dc9sv15l7bm5c17xn5kyk-move-systemd-user-units.sh' '/nix/store/cmzya9irvxzlkh7lfy6i82gbp0saxqj3-multiple-outputs.sh' '/nix/store/x8c40nfigps493a07sdr2pm5s9j1cdc0-patch-shebangs.sh' '/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh' '/nix/store/xyff06pkhki3qy1ls77w10s0v79c9il0-reproducible-builds.sh' '/nix/store/z7k98578dfzi6l3hsvbivzm7hfqlk0zc-set-source-date-epoch-to-latest.sh' '/nix/store/pilsssjjdxvdphlg2h19p0bfx5q0jzkn-strip.sh' '/nix/store/vr15iyyykg9zai6fpgvhcgyw7gckl78w-gcc-wrapper-14.3.0' '/nix/store/xwydcyvlsa3cvssk0y5llgdhlhjvmqdm-binutils-wrapper-2.44' )
+declare -a pkgsBuildTarget=()
+declare -a pkgsHostHost=('/nix/store/yijhn548p2589pkybgvbhll09bqsxy0q-ncurses-6.5' '/nix/store/b9p0zpa93hwvh4d0r1rmgc2500yx2ldn-libffi-3.5.2' '/nix/store/bkicgvyymba52ijm1z5zs96dsqqi59lp-elfutils-0.194' '/nix/store/54jkwsavi3fdciqfyjmbilq0jhvv4jga-gmp-with-cxx-6.3.0' '/nix/store/gdni20c8009xdz8gms6yn1r2hfhmk1jk-numactl-2.0.18' )
+declare -a pkgsHostTarget=()
+declare -a pkgsTargetTarget=()
+declare -a postFixupHooks=('noBrokenSymlinksInAllOutputs' '_makeSymlinksRelativeInAllOutputs' '_multioutPropagateDev' )
+declare -a postUnpackHooks=('_updateSourceDateEpochFromSourceRoot' )
+declare -a preConfigureHooks=('_multioutConfig' )
+preConfigurePhases=' updateAutotoolsGnuConfigScriptsPhase'
+declare -a preFixupHooks=('_moveToShare' '_multioutDocs' '_multioutDevs' )
+prefix='/home/felix/projects/pyrites/haskell-parsing/outputs/out'
+declare -a propagatedBuildDepFiles=('propagated-build-build-deps' 'propagated-native-build-inputs' 'propagated-build-target-deps' )
+propagatedBuildInputs=''
+export propagatedBuildInputs
+declare -a propagatedHostDepFiles=('propagated-host-host-deps' 'propagated-build-inputs' )
+propagatedNativeBuildInputs=''
+export propagatedNativeBuildInputs
+declare -a propagatedTargetDepFiles=('propagated-target-target-deps' )
+shell='/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash'
+export shell
+shellHook='unset TEMP TMP TEMPDIR TMPDIR'
+export shellHook
+stdenv='/nix/store/s3w5m3spa1g71hx0yb82lvk6394j3w5j-stdenv-linux'
+export stdenv
+strictDeps=''
+export strictDeps
+system='x86_64-linux'
+export system
+declare -a unpackCmdHooks=('_defaultUnpack' )
+_activatePkgs ()
+{
+
+ local hostOffset targetOffset;
+ local pkg;
+ for hostOffset in "${allPlatOffsets[@]}";
+ do
+ local pkgsVar="${pkgAccumVarVars[hostOffset + 1]}";
+ for targetOffset in "${allPlatOffsets[@]}";
+ do
+ (( hostOffset <= targetOffset )) || continue;
+ local pkgsRef="${pkgsVar}[$targetOffset - $hostOffset]";
+ local pkgsSlice="${!pkgsRef}[@]";
+ for pkg in ${!pkgsSlice+"${!pkgsSlice}"};
+ do
+ activatePackage "$pkg" "$hostOffset" "$targetOffset";
+ done;
+ done;
+ done
+}
+_addRpathPrefix ()
+{
+
+ if [ "${NIX_NO_SELF_RPATH:-0}" != 1 ]; then
+ export NIX_LDFLAGS="-rpath $1/lib ${NIX_LDFLAGS-}";
+ fi
+}
+_addToEnv ()
+{
+
+ local depHostOffset depTargetOffset;
+ local pkg;
+ for depHostOffset in "${allPlatOffsets[@]}";
+ do
+ local hookVar="${pkgHookVarVars[depHostOffset + 1]}";
+ local pkgsVar="${pkgAccumVarVars[depHostOffset + 1]}";
+ for depTargetOffset in "${allPlatOffsets[@]}";
+ do
+ (( depHostOffset <= depTargetOffset )) || continue;
+ local hookRef="${hookVar}[$depTargetOffset - $depHostOffset]";
+ if [[ -z "${strictDeps-}" ]]; then
+ local visitedPkgs="";
+ for pkg in "${pkgsBuildBuild[@]}" "${pkgsBuildHost[@]}" "${pkgsBuildTarget[@]}" "${pkgsHostHost[@]}" "${pkgsHostTarget[@]}" "${pkgsTargetTarget[@]}";
+ do
+ if [[ "$visitedPkgs" = *"$pkg"* ]]; then
+ continue;
+ fi;
+ runHook "${!hookRef}" "$pkg";
+ visitedPkgs+=" $pkg";
+ done;
+ else
+ local pkgsRef="${pkgsVar}[$depTargetOffset - $depHostOffset]";
+ local pkgsSlice="${!pkgsRef}[@]";
+ for pkg in ${!pkgsSlice+"${!pkgsSlice}"};
+ do
+ runHook "${!hookRef}" "$pkg";
+ done;
+ fi;
+ done;
+ done
+}
+_allFlags ()
+{
+
+ export system pname name version;
+ while IFS='' read -r varName; do
+ nixTalkativeLog "@${varName}@ -> ${!varName}";
+ args+=("--subst-var" "$varName");
+ done < <(awk 'BEGIN { for (v in ENVIRON) if (v ~ /^[a-z][a-zA-Z0-9_]*$/) print v }')
+}
+_assignFirst ()
+{
+
+ local varName="$1";
+ local _var;
+ local REMOVE=REMOVE;
+ shift;
+ for _var in "$@";
+ do
+ if [ -n "${!_var-}" ]; then
+ eval "${varName}"="${_var}";
+ return;
+ fi;
+ done;
+ echo;
+ echo "error: _assignFirst: could not find a non-empty variable whose name to assign to ${varName}.";
+ echo " The following variables were all unset or empty:";
+ echo " $*";
+ if [ -z "${out:-}" ]; then
+ echo ' If you do not want an "out" output in your derivation, make sure to define';
+ echo ' the other specific required outputs. This can be achieved by picking one';
+ echo " of the above as an output.";
+ echo ' You do not have to remove "out" if you want to have a different default';
+ echo ' output, because the first output is taken as a default.';
+ echo;
+ fi;
+ return 1
+}
+_callImplicitHook ()
+{
+
+ local def="$1";
+ local hookName="$2";
+ if declare -F "$hookName" > /dev/null; then
+ nixTalkativeLog "calling implicit '$hookName' function hook";
+ "$hookName";
+ else
+ if type -p "$hookName" > /dev/null; then
+ nixTalkativeLog "sourcing implicit '$hookName' script hook";
+ source "$hookName";
+ else
+ if [ -n "${!hookName:-}" ]; then
+ nixTalkativeLog "evaling implicit '$hookName' string hook";
+ eval "${!hookName}";
+ else
+ return "$def";
+ fi;
+ fi;
+ fi
+}
+_defaultUnpack ()
+{
+
+ local fn="$1";
+ local destination;
+ if [ -d "$fn" ]; then
+ destination="$(stripHash "$fn")";
+ if [ -e "$destination" ]; then
+ echo "Cannot copy $fn to $destination: destination already exists!";
+ echo "Did you specify two \"srcs\" with the same \"name\"?";
+ return 1;
+ fi;
+ cp -r --preserve=timestamps --reflink=auto -- "$fn" "$destination";
+ else
+ case "$fn" in
+ *.tar.xz | *.tar.lzma | *.txz)
+ ( XZ_OPT="--threads=$NIX_BUILD_CORES" xz -d < "$fn";
+ true ) | tar xf - --mode=+w --warning=no-timestamp
+ ;;
+ *.tar | *.tar.* | *.tgz | *.tbz2 | *.tbz)
+ tar xf "$fn" --mode=+w --warning=no-timestamp
+ ;;
+ *)
+ return 1
+ ;;
+ esac;
+ fi
+}
+_doStrip ()
+{
+
+ local -ra flags=(dontStripHost dontStripTarget);
+ local -ra debugDirs=(stripDebugList stripDebugListTarget);
+ local -ra allDirs=(stripAllList stripAllListTarget);
+ local -ra stripCmds=(STRIP STRIP_FOR_TARGET);
+ local -ra ranlibCmds=(RANLIB RANLIB_FOR_TARGET);
+ stripDebugList=${stripDebugList[*]:-lib lib32 lib64 libexec bin sbin Applications Library/Frameworks};
+ stripDebugListTarget=${stripDebugListTarget[*]:-};
+ stripAllList=${stripAllList[*]:-};
+ stripAllListTarget=${stripAllListTarget[*]:-};
+ local i;
+ for i in ${!stripCmds[@]};
+ do
+ local -n flag="${flags[$i]}";
+ local -n debugDirList="${debugDirs[$i]}";
+ local -n allDirList="${allDirs[$i]}";
+ local -n stripCmd="${stripCmds[$i]}";
+ local -n ranlibCmd="${ranlibCmds[$i]}";
+ if [[ -n "${dontStrip-}" || -n "${flag-}" ]] || ! type -f "${stripCmd-}" 2> /dev/null 1>&2; then
+ continue;
+ fi;
+ stripDirs "$stripCmd" "$ranlibCmd" "$debugDirList" "${stripDebugFlags[*]:--S -p}";
+ stripDirs "$stripCmd" "$ranlibCmd" "$allDirList" "${stripAllFlags[*]:--s -p}";
+ done
+}
+_eval ()
+{
+
+ if declare -F "$1" > /dev/null 2>&1; then
+ "$@";
+ else
+ eval "$1";
+ fi
+}
+_logHook ()
+{
+
+ if [[ -z ${NIX_LOG_FD-} ]]; then
+ return;
+ fi;
+ local hookKind="$1";
+ local hookExpr="$2";
+ shift 2;
+ if declare -F "$hookExpr" > /dev/null 2>&1; then
+ nixTalkativeLog "calling '$hookKind' function hook '$hookExpr'" "$@";
+ else
+ if type -p "$hookExpr" > /dev/null; then
+ nixTalkativeLog "sourcing '$hookKind' script hook '$hookExpr'";
+ else
+ if [[ "$hookExpr" != "_callImplicitHook"* ]]; then
+ local exprToOutput;
+ if [[ ${NIX_DEBUG:-0} -ge 5 ]]; then
+ exprToOutput="$hookExpr";
+ else
+ local hookExprLine;
+ while IFS= read -r hookExprLine; do
+ hookExprLine="${hookExprLine#"${hookExprLine%%[![:space:]]*}"}";
+ if [[ -n "$hookExprLine" ]]; then
+ exprToOutput+="$hookExprLine\\n ";
+ fi;
+ done <<< "$hookExpr";
+ exprToOutput="${exprToOutput%%\\n }";
+ fi;
+ nixTalkativeLog "evaling '$hookKind' string hook '$exprToOutput'";
+ fi;
+ fi;
+ fi
+}
+_makeSymlinksRelative ()
+{
+
+ local symlinkTarget;
+ if [ "${dontRewriteSymlinks-}" ] || [ ! -e "$prefix" ]; then
+ return;
+ fi;
+ while IFS= read -r -d '' f; do
+ symlinkTarget=$(readlink "$f");
+ if [[ "$symlinkTarget"/ != "$prefix"/* ]]; then
+ continue;
+ fi;
+ if [ ! -e "$symlinkTarget" ]; then
+ echo "the symlink $f is broken, it points to $symlinkTarget (which is missing)";
+ fi;
+ echo "rewriting symlink $f to be relative to $prefix";
+ ln -snrf "$symlinkTarget" "$f";
+ done < <(find $prefix -type l -print0)
+}
+_makeSymlinksRelativeInAllOutputs ()
+{
+
+ local output;
+ for output in $(getAllOutputNames);
+ do
+ prefix="${!output}" _makeSymlinksRelative;
+ done
+}
+_moveLib64 ()
+{
+
+ if [ "${dontMoveLib64-}" = 1 ]; then
+ return;
+ fi;
+ if [ ! -e "$prefix/lib64" -o -L "$prefix/lib64" ]; then
+ return;
+ fi;
+ echo "moving $prefix/lib64/* to $prefix/lib";
+ mkdir -p $prefix/lib;
+ shopt -s dotglob;
+ for i in $prefix/lib64/*;
+ do
+ mv --no-clobber "$i" $prefix/lib;
+ done;
+ shopt -u dotglob;
+ rmdir $prefix/lib64;
+ ln -s lib $prefix/lib64
+}
+_moveSbin ()
+{
+
+ if [ "${dontMoveSbin-}" = 1 ]; then
+ return;
+ fi;
+ if [ ! -e "$prefix/sbin" -o -L "$prefix/sbin" ]; then
+ return;
+ fi;
+ echo "moving $prefix/sbin/* to $prefix/bin";
+ mkdir -p $prefix/bin;
+ shopt -s dotglob;
+ for i in $prefix/sbin/*;
+ do
+ mv "$i" $prefix/bin;
+ done;
+ shopt -u dotglob;
+ rmdir $prefix/sbin;
+ ln -s bin $prefix/sbin
+}
+_moveSystemdUserUnits ()
+{
+
+ if [ "${dontMoveSystemdUserUnits:-0}" = 1 ]; then
+ return;
+ fi;
+ if [ ! -e "${prefix:?}/lib/systemd/user" ]; then
+ return;
+ fi;
+ local source="$prefix/lib/systemd/user";
+ local target="$prefix/share/systemd/user";
+ echo "moving $source/* to $target";
+ mkdir -p "$target";
+ ( shopt -s dotglob;
+ for i in "$source"/*;
+ do
+ mv "$i" "$target";
+ done );
+ rmdir "$source";
+ ln -s "$target" "$source"
+}
+_moveToShare ()
+{
+
+ if [ -n "$__structuredAttrs" ]; then
+ if [ -z "${forceShare-}" ]; then
+ forceShare=(man doc info);
+ fi;
+ else
+ forceShare=(${forceShare:-man doc info});
+ fi;
+ if [[ -z "$out" ]]; then
+ return;
+ fi;
+ for d in "${forceShare[@]}";
+ do
+ if [ -d "$out/$d" ]; then
+ if [ -d "$out/share/$d" ]; then
+ echo "both $d/ and share/$d/ exist!";
+ else
+ echo "moving $out/$d to $out/share/$d";
+ mkdir -p $out/share;
+ mv $out/$d $out/share/;
+ fi;
+ fi;
+ done
+}
+_multioutConfig ()
+{
+
+ if [ "$(getAllOutputNames)" = "out" ] || [ -z "${setOutputFlags-1}" ]; then
+ return;
+ fi;
+ if [ -z "${shareDocName:-}" ]; then
+ local confScript="${configureScript:-}";
+ if [ -z "$confScript" ] && [ -x ./configure ]; then
+ confScript=./configure;
+ fi;
+ if [ -f "$confScript" ]; then
+ local shareDocName="$(sed -n "s/^PACKAGE_TARNAME='\(.*\)'$/\1/p" < "$confScript")";
+ fi;
+ if [ -z "$shareDocName" ] || echo "$shareDocName" | grep -q '[^a-zA-Z0-9_-]'; then
+ shareDocName="$(echo "$name" | sed 's/-[^a-zA-Z].*//')";
+ fi;
+ fi;
+ prependToVar configureFlags --bindir="${!outputBin}"/bin --sbindir="${!outputBin}"/sbin --includedir="${!outputInclude}"/include --mandir="${!outputMan}"/share/man --infodir="${!outputInfo}"/share/info --docdir="${!outputDoc}"/share/doc/"${shareDocName}" --libdir="${!outputLib}"/lib --libexecdir="${!outputLib}"/libexec --localedir="${!outputLib}"/share/locale;
+ prependToVar installFlags pkgconfigdir="${!outputDev}"/lib/pkgconfig m4datadir="${!outputDev}"/share/aclocal aclocaldir="${!outputDev}"/share/aclocal
+}
+_multioutDevs ()
+{
+
+ if [ "$(getAllOutputNames)" = "out" ] || [ -z "${moveToDev-1}" ]; then
+ return;
+ fi;
+ moveToOutput include "${!outputInclude}";
+ moveToOutput lib/pkgconfig "${!outputDev}";
+ moveToOutput share/pkgconfig "${!outputDev}";
+ moveToOutput lib/cmake "${!outputDev}";
+ moveToOutput share/aclocal "${!outputDev}";
+ for f in "${!outputDev}"/{lib,share}/pkgconfig/*.pc;
+ do
+ echo "Patching '$f' includedir to output ${!outputInclude}";
+ sed -i "/^includedir=/s,=\${prefix},=${!outputInclude}," "$f";
+ done
+}
+_multioutDocs ()
+{
+
+ local REMOVE=REMOVE;
+ moveToOutput share/info "${!outputInfo}";
+ moveToOutput share/doc "${!outputDoc}";
+ moveToOutput share/gtk-doc "${!outputDevdoc}";
+ moveToOutput share/devhelp/books "${!outputDevdoc}";
+ moveToOutput share/man "${!outputMan}";
+ moveToOutput share/man/man3 "${!outputDevman}"
+}
+_multioutPropagateDev ()
+{
+
+ if [ "$(getAllOutputNames)" = "out" ]; then
+ return;
+ fi;
+ local outputFirst;
+ for outputFirst in $(getAllOutputNames);
+ do
+ break;
+ done;
+ local propagaterOutput="$outputDev";
+ if [ -z "$propagaterOutput" ]; then
+ propagaterOutput="$outputFirst";
+ fi;
+ if [ -z "${propagatedBuildOutputs+1}" ]; then
+ local po_dirty="$outputBin $outputInclude $outputLib";
+ set +o pipefail;
+ propagatedBuildOutputs=`echo "$po_dirty" | tr -s ' ' '\n' | grep -v -F "$propagaterOutput" | sort -u | tr '\n' ' ' `;
+ set -o pipefail;
+ fi;
+ if [ -z "$propagatedBuildOutputs" ]; then
+ return;
+ fi;
+ mkdir -p "${!propagaterOutput}"/nix-support;
+ for output in $propagatedBuildOutputs;
+ do
+ echo -n " ${!output}" >> "${!propagaterOutput}"/nix-support/propagated-build-inputs;
+ done
+}
+_nixLogWithLevel ()
+{
+
+ [[ -z ${NIX_LOG_FD-} || ${NIX_DEBUG:-0} -lt ${1:?} ]] && return 0;
+ local logLevel;
+ case "${1:?}" in
+ 0)
+ logLevel=ERROR
+ ;;
+ 1)
+ logLevel=WARN
+ ;;
+ 2)
+ logLevel=NOTICE
+ ;;
+ 3)
+ logLevel=INFO
+ ;;
+ 4)
+ logLevel=TALKATIVE
+ ;;
+ 5)
+ logLevel=CHATTY
+ ;;
+ 6)
+ logLevel=DEBUG
+ ;;
+ 7)
+ logLevel=VOMIT
+ ;;
+ *)
+ echo "_nixLogWithLevel: called with invalid log level: ${1:?}" >&"$NIX_LOG_FD";
+ return 1
+ ;;
+ esac;
+ local callerName="${FUNCNAME[2]}";
+ if [[ $callerName == "_callImplicitHook" ]]; then
+ callerName="${hookName:?}";
+ fi;
+ printf "%s: %s: %s\n" "$logLevel" "$callerName" "${2:?}" >&"$NIX_LOG_FD"
+}
+_overrideFirst ()
+{
+
+ if [ -z "${!1-}" ]; then
+ _assignFirst "$@";
+ fi
+}
+_pruneLibtoolFiles ()
+{
+
+ if [ "${dontPruneLibtoolFiles-}" ] || [ ! -e "$prefix" ]; then
+ return;
+ fi;
+ find "$prefix" -type f -name '*.la' -exec grep -q '^# Generated by .*libtool' {} \; -exec grep -q "^old_library=''" {} \; -exec sed -i {} -e "/^dependency_libs='[^']/ c dependency_libs='' #pruned" \;
+}
+_updateSourceDateEpochFromSourceRoot ()
+{
+
+ if [ -n "$sourceRoot" ]; then
+ updateSourceDateEpoch "$sourceRoot";
+ fi
+}
+activatePackage ()
+{
+
+ local pkg="$1";
+ local -r hostOffset="$2";
+ local -r targetOffset="$3";
+ (( hostOffset <= targetOffset )) || exit 1;
+ if [ -f "$pkg" ]; then
+ nixTalkativeLog "sourcing setup hook '$pkg'";
+ source "$pkg";
+ fi;
+ if [[ -z "${strictDeps-}" || "$hostOffset" -le -1 ]]; then
+ addToSearchPath _PATH "$pkg/bin";
+ fi;
+ if (( hostOffset <= -1 )); then
+ addToSearchPath _XDG_DATA_DIRS "$pkg/share";
+ fi;
+ if [[ "$hostOffset" -eq 0 && -d "$pkg/bin" ]]; then
+ addToSearchPath _HOST_PATH "$pkg/bin";
+ fi;
+ if [[ -f "$pkg/nix-support/setup-hook" ]]; then
+ nixTalkativeLog "sourcing setup hook '$pkg/nix-support/setup-hook'";
+ source "$pkg/nix-support/setup-hook";
+ fi
+}
+addEnvHooks ()
+{
+
+ local depHostOffset="$1";
+ shift;
+ local pkgHookVarsSlice="${pkgHookVarVars[$depHostOffset + 1]}[@]";
+ local pkgHookVar;
+ for pkgHookVar in "${!pkgHookVarsSlice}";
+ do
+ eval "${pkgHookVar}s"'+=("$@")';
+ done
+}
+addToSearchPath ()
+{
+
+ addToSearchPathWithCustomDelimiter ":" "$@"
+}
+addToSearchPathWithCustomDelimiter ()
+{
+
+ local delimiter="$1";
+ local varName="$2";
+ local dir="$3";
+ if [[ -d "$dir" && "${!varName:+${delimiter}${!varName}${delimiter}}" != *"${delimiter}${dir}${delimiter}"* ]]; then
+ export "${varName}=${!varName:+${!varName}${delimiter}}${dir}";
+ fi
+}
+appendToVar ()
+{
+
+ local -n nameref="$1";
+ local useArray type;
+ if [ -n "$__structuredAttrs" ]; then
+ useArray=true;
+ else
+ useArray=false;
+ fi;
+ if type=$(declare -p "$1" 2> /dev/null); then
+ case "${type#* }" in
+ -A*)
+ echo "appendToVar(): ERROR: trying to use appendToVar on an associative array, use variable+=([\"X\"]=\"Y\") instead." 1>&2;
+ return 1
+ ;;
+ -a*)
+ useArray=true
+ ;;
+ *)
+ useArray=false
+ ;;
+ esac;
+ fi;
+ shift;
+ if $useArray; then
+ nameref=(${nameref+"${nameref[@]}"} "$@");
+ else
+ nameref="${nameref-} $*";
+ fi
+}
+auditTmpdir ()
+{
+
+ local dir="$1";
+ [ -e "$dir" ] || return 0;
+ echo "checking for references to $TMPDIR/ in $dir...";
+ local tmpdir elf_fifo script_fifo;
+ tmpdir="$(mktemp -d)";
+ elf_fifo="$tmpdir/elf";
+ script_fifo="$tmpdir/script";
+ mkfifo "$elf_fifo" "$script_fifo";
+ ( find "$dir" -type f -not -path '*/.build-id/*' -print0 | while IFS= read -r -d '' file; do
+ if isELF "$file"; then
+ printf '%s\0' "$file" 1>&3;
+ else
+ if isScript "$file"; then
+ filename=${file##*/};
+ dir=${file%/*};
+ if [ -e "$dir/.$filename-wrapped" ]; then
+ printf '%s\0' "$file" 1>&4;
+ fi;
+ fi;
+ fi;
+ done;
+ exec 3>&- 4>&- ) 3> "$elf_fifo" 4> "$script_fifo" & ( xargs -0 -r -P "$NIX_BUILD_CORES" -n 1 sh -c '
+ if { printf :; patchelf --print-rpath "$1"; } | grep -q -F ":$TMPDIR/"; then
+ echo "RPATH of binary $1 contains a forbidden reference to $TMPDIR/"
+ exit 1
+ fi
+ ' _ < "$elf_fifo" ) & local pid_elf=$!;
+ local pid_script;
+ ( xargs -0 -r -P "$NIX_BUILD_CORES" -n 1 sh -c '
+ if grep -q -F "$TMPDIR/" "$1"; then
+ echo "wrapper script $1 contains a forbidden reference to $TMPDIR/"
+ exit 1
+ fi
+ ' _ < "$script_fifo" ) & local pid_script=$!;
+ wait "$pid_elf" || {
+ echo "Some binaries contain forbidden references to $TMPDIR/. Check the error above!";
+ exit 1
+ };
+ wait "$pid_script" || {
+ echo "Some scripts contain forbidden references to $TMPDIR/. Check the error above!";
+ exit 1
+ };
+ rm -r "$tmpdir"
+}
+bintoolsWrapper_addLDVars ()
+{
+
+ local role_post;
+ getHostRoleEnvHook;
+ if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then
+ export NIX_LDFLAGS${role_post}+=" -L$1/lib64";
+ fi;
+ if [[ -d "$1/lib" ]]; then
+ local -a glob=($1/lib/lib*);
+ if [ "${#glob[*]}" -gt 0 ]; then
+ export NIX_LDFLAGS${role_post}+=" -L$1/lib";
+ fi;
+ fi
+}
+buildPhase ()
+{
+
+ runHook preBuild;
+ if [[ -z "${makeFlags-}" && -z "${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ]]; then
+ echo "no Makefile or custom buildPhase, doing nothing";
+ else
+ foundMakefile=1;
+ local flagsArray=(${enableParallelBuilding:+-j${NIX_BUILD_CORES}} SHELL="$SHELL");
+ concatTo flagsArray makeFlags makeFlagsArray buildFlags buildFlagsArray;
+ echoCmd 'build flags' "${flagsArray[@]}";
+ make ${makefile:+-f $makefile} "${flagsArray[@]}";
+ unset flagsArray;
+ fi;
+ runHook postBuild
+}
+ccWrapper_addCVars ()
+{
+
+ local role_post;
+ getHostRoleEnvHook;
+ local found=;
+ if [ -d "$1/include" ]; then
+ export NIX_CFLAGS_COMPILE${role_post}+=" -isystem $1/include";
+ found=1;
+ fi;
+ if [ -d "$1/Library/Frameworks" ]; then
+ export NIX_CFLAGS_COMPILE${role_post}+=" -iframework $1/Library/Frameworks";
+ found=1;
+ fi;
+ if [[ -n "" && -n ${NIX_STORE:-} && -n $found ]]; then
+ local scrubbed="$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${1#"$NIX_STORE"/*-}";
+ export NIX_CFLAGS_COMPILE${role_post}+=" -fmacro-prefix-map=$1=$scrubbed";
+ fi
+}
+checkPhase ()
+{
+
+ runHook preCheck;
+ if [[ -z "${foundMakefile:-}" ]]; then
+ echo "no Makefile or custom checkPhase, doing nothing";
+ runHook postCheck;
+ return;
+ fi;
+ if [[ -z "${checkTarget:-}" ]]; then
+ if make -n ${makefile:+-f $makefile} check > /dev/null 2>&1; then
+ checkTarget="check";
+ else
+ if make -n ${makefile:+-f $makefile} test > /dev/null 2>&1; then
+ checkTarget="test";
+ fi;
+ fi;
+ fi;
+ if [[ -z "${checkTarget:-}" ]]; then
+ echo "no check/test target in ${makefile:-Makefile}, doing nothing";
+ else
+ local flagsArray=(${enableParallelChecking:+-j${NIX_BUILD_CORES}} SHELL="$SHELL");
+ concatTo flagsArray makeFlags makeFlagsArray checkFlags=VERBOSE=y checkFlagsArray checkTarget;
+ echoCmd 'check flags' "${flagsArray[@]}";
+ make ${makefile:+-f $makefile} "${flagsArray[@]}";
+ unset flagsArray;
+ fi;
+ runHook postCheck
+}
+compressManPages ()
+{
+
+ local dir="$1";
+ if [ -L "$dir"/share ] || [ -L "$dir"/share/man ] || [ ! -d "$dir/share/man" ]; then
+ return;
+ fi;
+ echo "gzipping man pages under $dir/share/man/";
+ find "$dir"/share/man/ -type f -a '!' -regex '.*\.\(bz2\|gz\|xz\)$' -print0 | xargs -0 -n1 -P "$NIX_BUILD_CORES" gzip -n -f;
+ find "$dir"/share/man/ -type l -a '!' -regex '.*\.\(bz2\|gz\|xz\)$' -print0 | sort -z | while IFS= read -r -d '' f; do
+ local target;
+ target="$(readlink -f "$f")";
+ if [ -f "$target".gz ]; then
+ ln -sf "$target".gz "$f".gz && rm "$f";
+ fi;
+ done
+}
+concatStringsSep ()
+{
+
+ local sep="$1";
+ local name="$2";
+ local type oldifs;
+ if type=$(declare -p "$name" 2> /dev/null); then
+ local -n nameref="$name";
+ case "${type#* }" in
+ -A*)
+ echo "concatStringsSep(): ERROR: trying to use concatStringsSep on an associative array." 1>&2;
+ return 1
+ ;;
+ -a*)
+ local IFS="$(printf '\036')"
+ ;;
+ *)
+ local IFS=" "
+ ;;
+ esac;
+ local ifs_separated="${nameref[*]}";
+ echo -n "${ifs_separated//"$IFS"/"$sep"}";
+ fi
+}
+concatTo ()
+{
+
+ local -;
+ set -o noglob;
+ local -n targetref="$1";
+ shift;
+ local arg default name type;
+ for arg in "$@";
+ do
+ IFS="=" read -r name default <<< "$arg";
+ local -n nameref="$name";
+ if [[ -z "${nameref[*]}" && -n "$default" ]]; then
+ targetref+=("$default");
+ else
+ if type=$(declare -p "$name" 2> /dev/null); then
+ case "${type#* }" in
+ -A*)
+ echo "concatTo(): ERROR: trying to use concatTo on an associative array." 1>&2;
+ return 1
+ ;;
+ -a*)
+ targetref+=("${nameref[@]}")
+ ;;
+ *)
+ if [[ "$name" = *"Array" ]]; then
+ nixErrorLog "concatTo(): $name is not declared as array, treating as a singleton. This will become an error in future";
+ targetref+=(${nameref+"${nameref[@]}"});
+ else
+ targetref+=(${nameref-});
+ fi
+ ;;
+ esac;
+ fi;
+ fi;
+ done
+}
+configurePhase ()
+{
+
+ runHook preConfigure;
+ : "${configureScript=}";
+ if [[ -z "$configureScript" && -x ./configure ]]; then
+ configureScript=./configure;
+ fi;
+ if [ -z "${dontFixLibtool:-}" ]; then
+ export lt_cv_deplibs_check_method="${lt_cv_deplibs_check_method-pass_all}";
+ local i;
+ find . -iname "ltmain.sh" -print0 | while IFS='' read -r -d '' i; do
+ echo "fixing libtool script $i";
+ fixLibtool "$i";
+ done;
+ CONFIGURE_MTIME_REFERENCE=$(mktemp configure.mtime.reference.XXXXXX);
+ find . -executable -type f -name configure -exec grep -l 'GNU Libtool is free software; you can redistribute it and/or modify' {} \; -exec touch -r {} "$CONFIGURE_MTIME_REFERENCE" \; -exec sed -i s_/usr/bin/file_file_g {} \; -exec touch -r "$CONFIGURE_MTIME_REFERENCE" {} \;;
+ rm -f "$CONFIGURE_MTIME_REFERENCE";
+ fi;
+ if [[ -z "${dontAddPrefix:-}" && -n "$prefix" ]]; then
+ prependToVar configureFlags "${prefixKey:---prefix=}$prefix";
+ fi;
+ if [[ -f "$configureScript" ]]; then
+ if [ -z "${dontAddDisableDepTrack:-}" ]; then
+ if grep -q dependency-tracking "$configureScript"; then
+ prependToVar configureFlags --disable-dependency-tracking;
+ fi;
+ fi;
+ if [ -z "${dontDisableStatic:-}" ]; then
+ if grep -q enable-static "$configureScript"; then
+ prependToVar configureFlags --disable-static;
+ fi;
+ fi;
+ if [ -z "${dontPatchShebangsInConfigure:-}" ]; then
+ patchShebangs --build "$configureScript";
+ fi;
+ fi;
+ if [ -n "$configureScript" ]; then
+ local -a flagsArray;
+ concatTo flagsArray configureFlags configureFlagsArray;
+ echoCmd 'configure flags' "${flagsArray[@]}";
+ $configureScript "${flagsArray[@]}";
+ unset flagsArray;
+ else
+ echo "no configure script, doing nothing";
+ fi;
+ runHook postConfigure
+}
+consumeEntire ()
+{
+
+ if IFS='' read -r -d '' "$1"; then
+ echo "consumeEntire(): ERROR: Input null bytes, won't process" 1>&2;
+ return 1;
+ fi
+}
+distPhase ()
+{
+
+ runHook preDist;
+ local flagsArray=();
+ concatTo flagsArray distFlags distFlagsArray distTarget=dist;
+ echo 'dist flags: %q' "${flagsArray[@]}";
+ make ${makefile:+-f $makefile} "${flagsArray[@]}";
+ if [ "${dontCopyDist:-0}" != 1 ]; then
+ mkdir -p "$out/tarballs";
+ cp -pvd ${tarballs[*]:-*.tar.gz} "$out/tarballs";
+ fi;
+ runHook postDist
+}
+dumpVars ()
+{
+
+ if [[ "${noDumpEnvVars:-0}" != 1 && -d "$NIX_BUILD_TOP" ]]; then
+ local old_umask;
+ old_umask=$(umask);
+ umask 0077;
+ export 2> /dev/null > "$NIX_BUILD_TOP/env-vars";
+ umask "$old_umask";
+ fi
+}
+echoCmd ()
+{
+
+ printf "%s:" "$1";
+ shift;
+ printf ' %q' "$@";
+ echo
+}
+exitHandler ()
+{
+
+ exitCode="$?";
+ set +e;
+ if [ -n "${showBuildStats:-}" ]; then
+ read -r -d '' -a buildTimes < <(times);
+ echo "build times:";
+ echo "user time for the shell ${buildTimes[0]}";
+ echo "system time for the shell ${buildTimes[1]}";
+ echo "user time for all child processes ${buildTimes[2]}";
+ echo "system time for all child processes ${buildTimes[3]}";
+ fi;
+ if (( "$exitCode" != 0 )); then
+ runHook failureHook;
+ if [ -n "${succeedOnFailure:-}" ]; then
+ echo "build failed with exit code $exitCode (ignored)";
+ mkdir -p "$out/nix-support";
+ printf "%s" "$exitCode" > "$out/nix-support/failed";
+ exit 0;
+ fi;
+ else
+ runHook exitHook;
+ fi;
+ return "$exitCode"
+}
+findInputs ()
+{
+
+ local -r pkg="$1";
+ local -r hostOffset="$2";
+ local -r targetOffset="$3";
+ (( hostOffset <= targetOffset )) || exit 1;
+ local varVar="${pkgAccumVarVars[hostOffset + 1]}";
+ local varRef="$varVar[$((targetOffset - hostOffset))]";
+ local var="${!varRef}";
+ unset -v varVar varRef;
+ local varSlice="$var[*]";
+ case " ${!varSlice-} " in
+ *" $pkg "*)
+ return 0
+ ;;
+ esac;
+ unset -v varSlice;
+ eval "$var"'+=("$pkg")';
+ if ! [ -e "$pkg" ]; then
+ echo "build input $pkg does not exist" 1>&2;
+ exit 1;
+ fi;
+ function mapOffset ()
+ {
+ local -r inputOffset="$1";
+ local -n outputOffset="$2";
+ if (( inputOffset <= 0 )); then
+ outputOffset=$((inputOffset + hostOffset));
+ else
+ outputOffset=$((inputOffset - 1 + targetOffset));
+ fi
+ };
+ local relHostOffset;
+ for relHostOffset in "${allPlatOffsets[@]}";
+ do
+ local files="${propagatedDepFilesVars[relHostOffset + 1]}";
+ local hostOffsetNext;
+ mapOffset "$relHostOffset" hostOffsetNext;
+ (( -1 <= hostOffsetNext && hostOffsetNext <= 1 )) || continue;
+ local relTargetOffset;
+ for relTargetOffset in "${allPlatOffsets[@]}";
+ do
+ (( "$relHostOffset" <= "$relTargetOffset" )) || continue;
+ local fileRef="${files}[$relTargetOffset - $relHostOffset]";
+ local file="${!fileRef}";
+ unset -v fileRef;
+ local targetOffsetNext;
+ mapOffset "$relTargetOffset" targetOffsetNext;
+ (( -1 <= hostOffsetNext && hostOffsetNext <= 1 )) || continue;
+ [[ -f "$pkg/nix-support/$file" ]] || continue;
+ local pkgNext;
+ read -r -d '' pkgNext < "$pkg/nix-support/$file" || true;
+ for pkgNext in $pkgNext;
+ do
+ findInputs "$pkgNext" "$hostOffsetNext" "$targetOffsetNext";
+ done;
+ done;
+ done
+}
+fixLibtool ()
+{
+
+ local search_path;
+ for flag in $NIX_LDFLAGS;
+ do
+ case $flag in
+ -L*)
+ search_path+=" ${flag#-L}"
+ ;;
+ esac;
+ done;
+ sed -i "$1" -e "s^eval \(sys_lib_search_path=\).*^\1'${search_path:-}'^" -e 's^eval sys_lib_.+search_path=.*^^'
+}
+fixupPhase ()
+{
+
+ local output;
+ for output in $(getAllOutputNames);
+ do
+ if [ -e "${!output}" ]; then
+ chmod -R u+w,u-s,g-s "${!output}";
+ fi;
+ done;
+ runHook preFixup;
+ local output;
+ for output in $(getAllOutputNames);
+ do
+ prefix="${!output}" runHook fixupOutput;
+ done;
+ recordPropagatedDependencies;
+ if [ -n "${setupHook:-}" ]; then
+ mkdir -p "${!outputDev}/nix-support";
+ substituteAll "$setupHook" "${!outputDev}/nix-support/setup-hook";
+ fi;
+ if [ -n "${setupHooks:-}" ]; then
+ mkdir -p "${!outputDev}/nix-support";
+ local hook;
+ for hook in ${setupHooks[@]};
+ do
+ local content;
+ consumeEntire content < "$hook";
+ substituteAllStream content "file '$hook'" >> "${!outputDev}/nix-support/setup-hook";
+ unset -v content;
+ done;
+ unset -v hook;
+ fi;
+ if [ -n "${propagatedUserEnvPkgs[*]:-}" ]; then
+ mkdir -p "${!outputBin}/nix-support";
+ printWords "${propagatedUserEnvPkgs[@]}" > "${!outputBin}/nix-support/propagated-user-env-packages";
+ fi;
+ runHook postFixup
+}
+genericBuild ()
+{
+
+ export GZIP_NO_TIMESTAMPS=1;
+ if [ -f "${buildCommandPath:-}" ]; then
+ source "$buildCommandPath";
+ return;
+ fi;
+ if [ -n "${buildCommand:-}" ]; then
+ eval "$buildCommand";
+ return;
+ fi;
+ if [ -z "${phases[*]:-}" ]; then
+ phases="${prePhases[*]:-} unpackPhase patchPhase ${preConfigurePhases[*]:-} configurePhase ${preBuildPhases[*]:-} buildPhase checkPhase ${preInstallPhases[*]:-} installPhase ${preFixupPhases[*]:-} fixupPhase installCheckPhase ${preDistPhases[*]:-} distPhase ${postPhases[*]:-}";
+ fi;
+ for curPhase in ${phases[*]};
+ do
+ runPhase "$curPhase";
+ done
+}
+getAllOutputNames ()
+{
+
+ if [ -n "$__structuredAttrs" ]; then
+ echo "${!outputs[*]}";
+ else
+ echo "$outputs";
+ fi
+}
+getHostRole ()
+{
+
+ getRole "$hostOffset"
+}
+getHostRoleEnvHook ()
+{
+
+ getRole "$depHostOffset"
+}
+getRole ()
+{
+
+ case $1 in
+ -1)
+ role_post='_FOR_BUILD'
+ ;;
+ 0)
+ role_post=''
+ ;;
+ 1)
+ role_post='_FOR_TARGET'
+ ;;
+ *)
+ echo "binutils-wrapper-2.44: used as improper sort of dependency" 1>&2;
+ return 1
+ ;;
+ esac
+}
+getTargetRole ()
+{
+
+ getRole "$targetOffset"
+}
+getTargetRoleEnvHook ()
+{
+
+ getRole "$depTargetOffset"
+}
+getTargetRoleWrapper ()
+{
+
+ case $targetOffset in
+ -1)
+ export NIX_BINTOOLS_WRAPPER_TARGET_BUILD_x86_64_unknown_linux_gnu=1
+ ;;
+ 0)
+ export NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu=1
+ ;;
+ 1)
+ export NIX_BINTOOLS_WRAPPER_TARGET_TARGET_x86_64_unknown_linux_gnu=1
+ ;;
+ *)
+ echo "binutils-wrapper-2.44: used as improper sort of dependency" 1>&2;
+ return 1
+ ;;
+ esac
+}
+installCheckPhase ()
+{
+
+ runHook preInstallCheck;
+ if [[ -z "${foundMakefile:-}" ]]; then
+ echo "no Makefile or custom installCheckPhase, doing nothing";
+ else
+ if [[ -z "${installCheckTarget:-}" ]] && ! make -n ${makefile:+-f $makefile} "${installCheckTarget:-installcheck}" > /dev/null 2>&1; then
+ echo "no installcheck target in ${makefile:-Makefile}, doing nothing";
+ else
+ local flagsArray=(${enableParallelChecking:+-j${NIX_BUILD_CORES}} SHELL="$SHELL");
+ concatTo flagsArray makeFlags makeFlagsArray installCheckFlags installCheckFlagsArray installCheckTarget=installcheck;
+ echoCmd 'installcheck flags' "${flagsArray[@]}";
+ make ${makefile:+-f $makefile} "${flagsArray[@]}";
+ unset flagsArray;
+ fi;
+ fi;
+ runHook postInstallCheck
+}
+installPhase ()
+{
+
+ runHook preInstall;
+ if [[ -z "${makeFlags-}" && -z "${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ]]; then
+ echo "no Makefile or custom installPhase, doing nothing";
+ runHook postInstall;
+ return;
+ else
+ foundMakefile=1;
+ fi;
+ if [ -n "$prefix" ]; then
+ mkdir -p "$prefix";
+ fi;
+ local flagsArray=(${enableParallelInstalling:+-j${NIX_BUILD_CORES}} SHELL="$SHELL");
+ concatTo flagsArray makeFlags makeFlagsArray installFlags installFlagsArray installTargets=install;
+ echoCmd 'install flags' "${flagsArray[@]}";
+ make ${makefile:+-f $makefile} "${flagsArray[@]}";
+ unset flagsArray;
+ runHook postInstall
+}
+isELF ()
+{
+
+ local fn="$1";
+ local fd;
+ local magic;
+ exec {fd}< "$fn";
+ LANG=C read -r -n 4 -u "$fd" magic;
+ exec {fd}>&-;
+ if [ "$magic" = 'ELF' ]; then
+ return 0;
+ else
+ return 1;
+ fi
+}
+isMachO ()
+{
+
+ local fn="$1";
+ local fd;
+ local magic;
+ exec {fd}< "$fn";
+ LANG=C read -r -n 4 -u "$fd" magic;
+ exec {fd}>&-;
+ if [[ "$magic" = $(echo -ne "\xfe\xed\xfa\xcf") || "$magic" = $(echo -ne "\xcf\xfa\xed\xfe") ]]; then
+ return 0;
+ else
+ if [[ "$magic" = $(echo -ne "\xfe\xed\xfa\xce") || "$magic" = $(echo -ne "\xce\xfa\xed\xfe") ]]; then
+ return 0;
+ else
+ if [[ "$magic" = $(echo -ne "\xca\xfe\xba\xbe") || "$magic" = $(echo -ne "\xbe\xba\xfe\xca") ]]; then
+ return 0;
+ else
+ return 1;
+ fi;
+ fi;
+ fi
+}
+isScript ()
+{
+
+ local fn="$1";
+ local fd;
+ local magic;
+ exec {fd}< "$fn";
+ LANG=C read -r -n 2 -u "$fd" magic;
+ exec {fd}>&-;
+ if [[ "$magic" =~ \#! ]]; then
+ return 0;
+ else
+ return 1;
+ fi
+}
+mapOffset ()
+{
+
+ local -r inputOffset="$1";
+ local -n outputOffset="$2";
+ if (( inputOffset <= 0 )); then
+ outputOffset=$((inputOffset + hostOffset));
+ else
+ outputOffset=$((inputOffset - 1 + targetOffset));
+ fi
+}
+moveToOutput ()
+{
+
+ local patt="$1";
+ local dstOut="$2";
+ local output;
+ for output in $(getAllOutputNames);
+ do
+ if [ "${!output}" = "$dstOut" ]; then
+ continue;
+ fi;
+ local srcPath;
+ for srcPath in "${!output}"/$patt;
+ do
+ if [ ! -e "$srcPath" ] && [ ! -L "$srcPath" ]; then
+ continue;
+ fi;
+ if [ "$dstOut" = REMOVE ]; then
+ echo "Removing $srcPath";
+ rm -r "$srcPath";
+ else
+ local dstPath="$dstOut${srcPath#${!output}}";
+ echo "Moving $srcPath to $dstPath";
+ if [ -d "$dstPath" ] && [ -d "$srcPath" ]; then
+ rmdir "$srcPath" --ignore-fail-on-non-empty;
+ if [ -d "$srcPath" ]; then
+ mv -t "$dstPath" "$srcPath"/*;
+ rmdir "$srcPath";
+ fi;
+ else
+ mkdir -p "$(readlink -m "$dstPath/..")";
+ mv "$srcPath" "$dstPath";
+ fi;
+ fi;
+ local srcParent="$(readlink -m "$srcPath/..")";
+ if [ -n "$(find "$srcParent" -maxdepth 0 -type d -empty 2> /dev/null)" ]; then
+ echo "Removing empty $srcParent/ and (possibly) its parents";
+ rmdir -p --ignore-fail-on-non-empty "$srcParent" 2> /dev/null || true;
+ fi;
+ done;
+ done
+}
+nixChattyLog ()
+{
+
+ _nixLogWithLevel 5 "$*"
+}
+nixDebugLog ()
+{
+
+ _nixLogWithLevel 6 "$*"
+}
+nixErrorLog ()
+{
+
+ _nixLogWithLevel 0 "$*"
+}
+nixInfoLog ()
+{
+
+ _nixLogWithLevel 3 "$*"
+}
+nixLog ()
+{
+
+ [[ -z ${NIX_LOG_FD-} ]] && return 0;
+ local callerName="${FUNCNAME[1]}";
+ if [[ $callerName == "_callImplicitHook" ]]; then
+ callerName="${hookName:?}";
+ fi;
+ printf "%s: %s\n" "$callerName" "$*" >&"$NIX_LOG_FD"
+}
+nixNoticeLog ()
+{
+
+ _nixLogWithLevel 2 "$*"
+}
+nixTalkativeLog ()
+{
+
+ _nixLogWithLevel 4 "$*"
+}
+nixVomitLog ()
+{
+
+ _nixLogWithLevel 7 "$*"
+}
+nixWarnLog ()
+{
+
+ _nixLogWithLevel 1 "$*"
+}
+noBrokenSymlinks ()
+{
+
+ local -r output="${1:?}";
+ local path;
+ local pathParent;
+ local symlinkTarget;
+ local -i numDanglingSymlinks=0;
+ local -i numReflexiveSymlinks=0;
+ local -i numUnreadableSymlinks=0;
+ if [[ ! -e $output ]]; then
+ nixWarnLog "skipping non-existent output $output";
+ return 0;
+ fi;
+ nixInfoLog "running on $output";
+ while IFS= read -r -d '' path; do
+ pathParent="$(dirname "$path")";
+ if ! symlinkTarget="$(readlink "$path")"; then
+ nixErrorLog "the symlink $path is unreadable";
+ numUnreadableSymlinks+=1;
+ continue;
+ fi;
+ if [[ $symlinkTarget == /* ]]; then
+ nixInfoLog "symlink $path points to absolute target $symlinkTarget";
+ else
+ nixInfoLog "symlink $path points to relative target $symlinkTarget";
+ symlinkTarget="$(realpath --no-symlinks --canonicalize-missing "$pathParent/$symlinkTarget")";
+ fi;
+ if [[ $symlinkTarget = "$TMPDIR"/* ]]; then
+ nixErrorLog "the symlink $path points to $TMPDIR directory: $symlinkTarget";
+ numDanglingSymlinks+=1;
+ continue;
+ fi;
+ if [[ $symlinkTarget != "$NIX_STORE"/* ]]; then
+ nixInfoLog "symlink $path points outside the Nix store; ignoring";
+ continue;
+ fi;
+ if [[ $path == "$symlinkTarget" ]]; then
+ nixErrorLog "the symlink $path is reflexive";
+ numReflexiveSymlinks+=1;
+ else
+ if [[ ! -e $symlinkTarget ]]; then
+ nixErrorLog "the symlink $path points to a missing target: $symlinkTarget";
+ numDanglingSymlinks+=1;
+ else
+ nixDebugLog "the symlink $path is irreflexive and points to a target which exists";
+ fi;
+ fi;
+ done < <(find "$output" -type l -print0);
+ if ((numDanglingSymlinks > 0 || numReflexiveSymlinks > 0 || numUnreadableSymlinks > 0)); then
+ nixErrorLog "found $numDanglingSymlinks dangling symlinks, $numReflexiveSymlinks reflexive symlinks and $numUnreadableSymlinks unreadable symlinks";
+ exit 1;
+ fi;
+ return 0
+}
+noBrokenSymlinksInAllOutputs ()
+{
+
+ if [[ -z ${dontCheckForBrokenSymlinks-} ]]; then
+ for output in $(getAllOutputNames);
+ do
+ noBrokenSymlinks "${!output}";
+ done;
+ fi
+}
+patchELF ()
+{
+
+ local dir="$1";
+ [ -e "$dir" ] || return 0;
+ echo "shrinking RPATHs of ELF executables and libraries in $dir";
+ local i;
+ while IFS= read -r -d '' i; do
+ if [[ "$i" =~ .build-id ]]; then
+ continue;
+ fi;
+ if ! isELF "$i"; then
+ continue;
+ fi;
+ echo "shrinking $i";
+ patchelf --shrink-rpath "$i" || true;
+ done < <(find "$dir" -type f -print0)
+}
+patchPhase ()
+{
+
+ runHook prePatch;
+ local -a patchesArray;
+ concatTo patchesArray patches;
+ local -a flagsArray;
+ concatTo flagsArray patchFlags=-p1;
+ for i in "${patchesArray[@]}";
+ do
+ echo "applying patch $i";
+ local uncompress=cat;
+ case "$i" in
+ *.gz)
+ uncompress="gzip -d"
+ ;;
+ *.bz2)
+ uncompress="bzip2 -d"
+ ;;
+ *.xz)
+ uncompress="xz -d"
+ ;;
+ *.lzma)
+ uncompress="lzma -d"
+ ;;
+ esac;
+ $uncompress < "$i" 2>&1 | patch "${flagsArray[@]}";
+ done;
+ runHook postPatch
+}
+patchShebangs ()
+{
+
+ local pathName;
+ local update=false;
+ while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --host)
+ pathName=HOST_PATH;
+ shift
+ ;;
+ --build)
+ pathName=PATH;
+ shift
+ ;;
+ --update)
+ update=true;
+ shift
+ ;;
+ --)
+ shift;
+ break
+ ;;
+ -* | --*)
+ echo "Unknown option $1 supplied to patchShebangs" 1>&2;
+ return 1
+ ;;
+ *)
+ break
+ ;;
+ esac;
+ done;
+ echo "patching script interpreter paths in $@";
+ local f;
+ local oldPath;
+ local newPath;
+ local arg0;
+ local args;
+ local oldInterpreterLine;
+ local newInterpreterLine;
+ if [[ $# -eq 0 ]]; then
+ echo "No arguments supplied to patchShebangs" 1>&2;
+ return 0;
+ fi;
+ local f;
+ while IFS= read -r -d '' f; do
+ isScript "$f" || continue;
+ read -r oldInterpreterLine < "$f" || [ "$oldInterpreterLine" ];
+ read -r oldPath arg0 args <<< "${oldInterpreterLine:2}";
+ if [[ -z "${pathName:-}" ]]; then
+ if [[ -n $strictDeps && $f == "$NIX_STORE"* ]]; then
+ pathName=HOST_PATH;
+ else
+ pathName=PATH;
+ fi;
+ fi;
+ if [[ "$oldPath" == *"/bin/env" ]]; then
+ if [[ $arg0 == "-S" ]]; then
+ arg0=${args%% *};
+ [[ "$args" == *" "* ]] && args=${args#* } || args=;
+ newPath="$(PATH="${!pathName}" type -P "env" || true)";
+ args="-S $(PATH="${!pathName}" type -P "$arg0" || true) $args";
+ else
+ if [[ $arg0 == "-"* || $arg0 == *"="* ]]; then
+ echo "$f: unsupported interpreter directive \"$oldInterpreterLine\" (set dontPatchShebangs=1 and handle shebang patching yourself)" 1>&2;
+ exit 1;
+ else
+ newPath="$(PATH="${!pathName}" type -P "$arg0" || true)";
+ fi;
+ fi;
+ else
+ if [[ -z $oldPath ]]; then
+ oldPath="/bin/sh";
+ fi;
+ newPath="$(PATH="${!pathName}" type -P "$(basename "$oldPath")" || true)";
+ args="$arg0 $args";
+ fi;
+ newInterpreterLine="$newPath $args";
+ newInterpreterLine=${newInterpreterLine%${newInterpreterLine##*[![:space:]]}};
+ if [[ -n "$oldPath" && ( "$update" == true || "${oldPath:0:${#NIX_STORE}}" != "$NIX_STORE" ) ]]; then
+ if [[ -n "$newPath" && "$newPath" != "$oldPath" ]]; then
+ echo "$f: interpreter directive changed from \"$oldInterpreterLine\" to \"$newInterpreterLine\"";
+ escapedInterpreterLine=${newInterpreterLine//\\/\\\\};
+ timestamp=$(stat --printf "%y" "$f");
+ tmpFile=$(mktemp -t patchShebangs.XXXXXXXXXX);
+ sed -e "1 s|.*|#\!$escapedInterpreterLine|" "$f" > "$tmpFile";
+ local restoreReadOnly;
+ if [[ ! -w "$f" ]]; then
+ chmod +w "$f";
+ restoreReadOnly=true;
+ fi;
+ cat "$tmpFile" > "$f";
+ rm "$tmpFile";
+ if [[ -n "${restoreReadOnly:-}" ]]; then
+ chmod -w "$f";
+ fi;
+ touch --date "$timestamp" "$f";
+ fi;
+ fi;
+ done < <(find "$@" -type f -perm -0100 -print0)
+}
+patchShebangsAuto ()
+{
+
+ if [[ -z "${dontPatchShebangs-}" && -e "$prefix" ]]; then
+ if [[ "$output" != out && "$output" = "$outputDev" ]]; then
+ patchShebangs --build "$prefix";
+ else
+ patchShebangs --host "$prefix";
+ fi;
+ fi
+}
+prependToVar ()
+{
+
+ local -n nameref="$1";
+ local useArray type;
+ if [ -n "$__structuredAttrs" ]; then
+ useArray=true;
+ else
+ useArray=false;
+ fi;
+ if type=$(declare -p "$1" 2> /dev/null); then
+ case "${type#* }" in
+ -A*)
+ echo "prependToVar(): ERROR: trying to use prependToVar on an associative array." 1>&2;
+ return 1
+ ;;
+ -a*)
+ useArray=true
+ ;;
+ *)
+ useArray=false
+ ;;
+ esac;
+ fi;
+ shift;
+ if $useArray; then
+ nameref=("$@" ${nameref+"${nameref[@]}"});
+ else
+ nameref="$* ${nameref-}";
+ fi
+}
+printLines ()
+{
+
+ (( "$#" > 0 )) || return 0;
+ printf '%s\n' "$@"
+}
+printWords ()
+{
+
+ (( "$#" > 0 )) || return 0;
+ printf '%s ' "$@"
+}
+recordPropagatedDependencies ()
+{
+
+ declare -ra flatVars=(depsBuildBuildPropagated propagatedNativeBuildInputs depsBuildTargetPropagated depsHostHostPropagated propagatedBuildInputs depsTargetTargetPropagated);
+ declare -ra flatFiles=("${propagatedBuildDepFiles[@]}" "${propagatedHostDepFiles[@]}" "${propagatedTargetDepFiles[@]}");
+ local propagatedInputsIndex;
+ for propagatedInputsIndex in "${!flatVars[@]}";
+ do
+ local propagatedInputsSlice="${flatVars[$propagatedInputsIndex]}[@]";
+ local propagatedInputsFile="${flatFiles[$propagatedInputsIndex]}";
+ [[ -n "${!propagatedInputsSlice}" ]] || continue;
+ mkdir -p "${!outputDev}/nix-support";
+ printWords ${!propagatedInputsSlice} > "${!outputDev}/nix-support/$propagatedInputsFile";
+ done
+}
+runHook ()
+{
+
+ local hookName="$1";
+ shift;
+ local hooksSlice="${hookName%Hook}Hooks[@]";
+ local hook;
+ for hook in "_callImplicitHook 0 $hookName" ${!hooksSlice+"${!hooksSlice}"};
+ do
+ _logHook "$hookName" "$hook" "$@";
+ _eval "$hook" "$@";
+ done;
+ return 0
+}
+runOneHook ()
+{
+
+ local hookName="$1";
+ shift;
+ local hooksSlice="${hookName%Hook}Hooks[@]";
+ local hook ret=1;
+ for hook in "_callImplicitHook 1 $hookName" ${!hooksSlice+"${!hooksSlice}"};
+ do
+ _logHook "$hookName" "$hook" "$@";
+ if _eval "$hook" "$@"; then
+ ret=0;
+ break;
+ fi;
+ done;
+ return "$ret"
+}
+runPhase ()
+{
+
+ local curPhase="$*";
+ if [[ "$curPhase" = unpackPhase && -n "${dontUnpack:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = patchPhase && -n "${dontPatch:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = configurePhase && -n "${dontConfigure:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = buildPhase && -n "${dontBuild:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = checkPhase && -z "${doCheck:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = installPhase && -n "${dontInstall:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = fixupPhase && -n "${dontFixup:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = installCheckPhase && -z "${doInstallCheck:-}" ]]; then
+ return;
+ fi;
+ if [[ "$curPhase" = distPhase && -z "${doDist:-}" ]]; then
+ return;
+ fi;
+ showPhaseHeader "$curPhase";
+ dumpVars;
+ local startTime endTime;
+ startTime=$(date +"%s");
+ eval "${!curPhase:-$curPhase}";
+ endTime=$(date +"%s");
+ showPhaseFooter "$curPhase" "$startTime" "$endTime";
+ if [ "$curPhase" = unpackPhase ]; then
+ [ -n "${sourceRoot:-}" ] && chmod +x -- "${sourceRoot}";
+ cd -- "${sourceRoot:-.}";
+ fi
+}
+showPhaseFooter ()
+{
+
+ local phase="$1";
+ local startTime="$2";
+ local endTime="$3";
+ local delta=$(( endTime - startTime ));
+ (( delta < 30 )) && return;
+ local H=$((delta/3600));
+ local M=$((delta%3600/60));
+ local S=$((delta%60));
+ echo -n "$phase completed in ";
+ (( H > 0 )) && echo -n "$H hours ";
+ (( M > 0 )) && echo -n "$M minutes ";
+ echo "$S seconds"
+}
+showPhaseHeader ()
+{
+
+ local phase="$1";
+ echo "Running phase: $phase";
+ if [[ -z ${NIX_LOG_FD-} ]]; then
+ return;
+ fi;
+ printf "@nix { \"action\": \"setPhase\", \"phase\": \"%s\" }\n" "$phase" >&"$NIX_LOG_FD"
+}
+stripDirs ()
+{
+
+ local cmd="$1";
+ local ranlibCmd="$2";
+ local paths="$3";
+ local stripFlags="$4";
+ local excludeFlags=();
+ local pathsNew=;
+ [ -z "$cmd" ] && echo "stripDirs: Strip command is empty" 1>&2 && exit 1;
+ [ -z "$ranlibCmd" ] && echo "stripDirs: Ranlib command is empty" 1>&2 && exit 1;
+ local pattern;
+ if [ -n "${stripExclude:-}" ]; then
+ for pattern in "${stripExclude[@]}";
+ do
+ excludeFlags+=(-a '!' '(' -name "$pattern" -o -wholename "$prefix/$pattern" ')');
+ done;
+ fi;
+ local p;
+ for p in ${paths};
+ do
+ if [ -e "$prefix/$p" ]; then
+ pathsNew="${pathsNew} $prefix/$p";
+ fi;
+ done;
+ paths=${pathsNew};
+ if [ -n "${paths}" ]; then
+ echo "stripping (with command $cmd and flags $stripFlags) in $paths";
+ local striperr;
+ striperr="$(mktemp --tmpdir="$TMPDIR" 'striperr.XXXXXX')";
+ find $paths -type f "${excludeFlags[@]}" -a '!' -path "$prefix/lib/debug/*" -printf '%D-%i,%p\0' | sort -t, -k1,1 -u -z | cut -d, -f2- -z | xargs -r -0 -n1 -P "$NIX_BUILD_CORES" -- $cmd $stripFlags 2> "$striperr" || exit_code=$?;
+ [[ "$exit_code" = 123 || -z "$exit_code" ]] || ( cat "$striperr" 1>&2 && exit 1 );
+ rm "$striperr";
+ find $paths -name '*.a' -type f -exec $ranlibCmd '{}' \; 2> /dev/null;
+ fi
+}
+stripHash ()
+{
+
+ local strippedName casematchOpt=0;
+ strippedName="$(basename -- "$1")";
+ shopt -q nocasematch && casematchOpt=1;
+ shopt -u nocasematch;
+ if [[ "$strippedName" =~ ^[a-z0-9]{32}- ]]; then
+ echo "${strippedName:33}";
+ else
+ echo "$strippedName";
+ fi;
+ if (( casematchOpt )); then
+ shopt -s nocasematch;
+ fi
+}
+substitute ()
+{
+
+ local input="$1";
+ local output="$2";
+ shift 2;
+ if [ ! -f "$input" ]; then
+ echo "substitute(): ERROR: file '$input' does not exist" 1>&2;
+ return 1;
+ fi;
+ local content;
+ consumeEntire content < "$input";
+ if [ -e "$output" ]; then
+ chmod +w "$output";
+ fi;
+ substituteStream content "file '$input'" "$@" > "$output"
+}
+substituteAll ()
+{
+
+ local input="$1";
+ local output="$2";
+ local -a args=();
+ _allFlags;
+ substitute "$input" "$output" "${args[@]}"
+}
+substituteAllInPlace ()
+{
+
+ local fileName="$1";
+ shift;
+ substituteAll "$fileName" "$fileName" "$@"
+}
+substituteAllStream ()
+{
+
+ local -a args=();
+ _allFlags;
+ substituteStream "$1" "$2" "${args[@]}"
+}
+substituteInPlace ()
+{
+
+ local -a fileNames=();
+ for arg in "$@";
+ do
+ if [[ "$arg" = "--"* ]]; then
+ break;
+ fi;
+ fileNames+=("$arg");
+ shift;
+ done;
+ if ! [[ "${#fileNames[@]}" -gt 0 ]]; then
+ echo "substituteInPlace called without any files to operate on (files must come before options!)" 1>&2;
+ return 1;
+ fi;
+ for file in "${fileNames[@]}";
+ do
+ substitute "$file" "$file" "$@";
+ done
+}
+substituteStream ()
+{
+
+ local var=$1;
+ local description=$2;
+ shift 2;
+ while (( "$#" )); do
+ local replace_mode="$1";
+ case "$1" in
+ --replace)
+ if ! "$_substituteStream_has_warned_replace_deprecation"; then
+ echo "substituteStream() in derivation $name: WARNING: '--replace' is deprecated, use --replace-{fail,warn,quiet}. ($description)" 1>&2;
+ _substituteStream_has_warned_replace_deprecation=true;
+ fi;
+ replace_mode='--replace-warn'
+ ;&
+ --replace-quiet | --replace-warn | --replace-fail)
+ pattern="$2";
+ replacement="$3";
+ shift 3;
+ if ! [[ "${!var}" == *"$pattern"* ]]; then
+ if [ "$replace_mode" == --replace-warn ]; then
+ printf "substituteStream() in derivation $name: WARNING: pattern %q doesn't match anything in %s\n" "$pattern" "$description" 1>&2;
+ else
+ if [ "$replace_mode" == --replace-fail ]; then
+ printf "substituteStream() in derivation $name: ERROR: pattern %q doesn't match anything in %s\n" "$pattern" "$description" 1>&2;
+ return 1;
+ fi;
+ fi;
+ fi;
+ eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}'
+ ;;
+ --subst-var)
+ local varName="$2";
+ shift 2;
+ if ! [[ "$varName" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then
+ echo "substituteStream() in derivation $name: ERROR: substitution variables must be valid Bash names, \"$varName\" isn't." 1>&2;
+ return 1;
+ fi;
+ if [ -z ${!varName+x} ]; then
+ echo "substituteStream() in derivation $name: ERROR: variable \$$varName is unset" 1>&2;
+ return 1;
+ fi;
+ pattern="@$varName@";
+ replacement="${!varName}";
+ eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}'
+ ;;
+ --subst-var-by)
+ pattern="@$2@";
+ replacement="$3";
+ eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}';
+ shift 3
+ ;;
+ *)
+ echo "substituteStream() in derivation $name: ERROR: Invalid command line argument: $1" 1>&2;
+ return 1
+ ;;
+ esac;
+ done;
+ printf "%s" "${!var}"
+}
+unpackFile ()
+{
+
+ curSrc="$1";
+ echo "unpacking source archive $curSrc";
+ if ! runOneHook unpackCmd "$curSrc"; then
+ echo "do not know how to unpack source archive $curSrc";
+ exit 1;
+ fi
+}
+unpackPhase ()
+{
+
+ runHook preUnpack;
+ if [ -z "${srcs:-}" ]; then
+ if [ -z "${src:-}" ]; then
+ echo 'variable $src or $srcs should point to the source';
+ exit 1;
+ fi;
+ srcs="$src";
+ fi;
+ local -a srcsArray;
+ concatTo srcsArray srcs;
+ local dirsBefore="";
+ for i in *;
+ do
+ if [ -d "$i" ]; then
+ dirsBefore="$dirsBefore $i ";
+ fi;
+ done;
+ for i in "${srcsArray[@]}";
+ do
+ unpackFile "$i";
+ done;
+ : "${sourceRoot=}";
+ if [ -n "${setSourceRoot:-}" ]; then
+ runOneHook setSourceRoot;
+ else
+ if [ -z "$sourceRoot" ]; then
+ for i in *;
+ do
+ if [ -d "$i" ]; then
+ case $dirsBefore in
+ *\ $i\ *)
+
+ ;;
+ *)
+ if [ -n "$sourceRoot" ]; then
+ echo "unpacker produced multiple directories";
+ exit 1;
+ fi;
+ sourceRoot="$i"
+ ;;
+ esac;
+ fi;
+ done;
+ fi;
+ fi;
+ if [ -z "$sourceRoot" ]; then
+ echo "unpacker appears to have produced no directories";
+ exit 1;
+ fi;
+ echo "source root is $sourceRoot";
+ if [ "${dontMakeSourcesWritable:-0}" != 1 ]; then
+ chmod -R u+w -- "$sourceRoot";
+ fi;
+ runHook postUnpack
+}
+updateAutotoolsGnuConfigScriptsPhase ()
+{
+
+ if [ -n "${dontUpdateAutotoolsGnuConfigScripts-}" ]; then
+ return;
+ fi;
+ for script in config.sub config.guess;
+ do
+ for f in $(find . -type f -name "$script");
+ do
+ echo "Updating Autotools / GNU config script to a newer upstream version: $f";
+ cp -f "/nix/store/1kzclixw4c13wxin0b6cij1zykvwp0wb-gnu-config-2024-01-01/$script" "$f";
+ done;
+ done
+}
+updateSourceDateEpoch ()
+{
+
+ local path="$1";
+ [[ $path == -* ]] && path="./$path";
+ local -a res=($(find "$path" -type f -not -newer "$NIX_BUILD_TOP/.." -printf '%T@ "%p"\0' | sort -n --zero-terminated | tail -n1 --zero-terminated | head -c -1));
+ local time="${res[0]//\.[0-9]*/}";
+ local newestFile="${res[1]}";
+ if [ "${time:-0}" -gt "$SOURCE_DATE_EPOCH" ]; then
+ echo "setting SOURCE_DATE_EPOCH to timestamp $time of file $newestFile";
+ export SOURCE_DATE_EPOCH="$time";
+ local now="$(date +%s)";
+ if [ "$time" -gt $((now - 60)) ]; then
+ echo "warning: file $newestFile may be generated; SOURCE_DATE_EPOCH may be non-deterministic";
+ fi;
+ fi
+}
+PATH="$PATH${nix_saved_PATH:+:$nix_saved_PATH}"
+XDG_DATA_DIRS="$XDG_DATA_DIRS${nix_saved_XDG_DATA_DIRS:+:$nix_saved_XDG_DATA_DIRS}"
+export NIX_BUILD_TOP="$(mktemp -d -t nix-shell.XXXXXX)"
+export TMP="$NIX_BUILD_TOP"
+export TMPDIR="$NIX_BUILD_TOP"
+export TEMP="$NIX_BUILD_TOP"
+export TEMPDIR="$NIX_BUILD_TOP"
+eval "${shellHook:-}"
diff --git a/haskell-experiments/.envrc b/haskell-experiments/.envrc
new file mode 100644
index 0000000..1d953f4
--- /dev/null
+++ b/haskell-experiments/.envrc
@@ -0,0 +1 @@
+use nix
diff --git a/haskell-experiments/.idea/.gitignore b/haskell-experiments/.idea/.gitignore
new file mode 100644
index 0000000..a0ccf77
--- /dev/null
+++ b/haskell-experiments/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Environment-dependent path to Maven home directory
+/mavenHomeManager.xml
diff --git a/haskell-experiments/.idea/codeStyles/Project.xml b/haskell-experiments/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..919ce1f
--- /dev/null
+++ b/haskell-experiments/.idea/codeStyles/Project.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/.idea/codeStyles/codeStyleConfig.xml b/haskell-experiments/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/haskell-experiments/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/.idea/material_theme_project_new.xml b/haskell-experiments/.idea/material_theme_project_new.xml
new file mode 100644
index 0000000..d582fbf
--- /dev/null
+++ b/haskell-experiments/.idea/material_theme_project_new.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/.idea/misc.xml b/haskell-experiments/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/haskell-experiments/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/.idea/modules.xml b/haskell-experiments/.idea/modules.xml
new file mode 100644
index 0000000..4145e71
--- /dev/null
+++ b/haskell-experiments/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/.idea/vcs.xml b/haskell-experiments/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/haskell-experiments/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/haskell-experiments.cabal b/haskell-experiments/haskell-experiments.cabal
new file mode 100644
index 0000000..bde08fd
--- /dev/null
+++ b/haskell-experiments/haskell-experiments.cabal
@@ -0,0 +1,95 @@
+cabal-version: 3.0
+-- The cabal-version field refers to the version of the .cabal specification,
+-- and can be different from the cabal-install (the tool) version and the
+-- Cabal (the library) version you are using. As such, the Cabal (the library)
+-- version used must be equal or greater than the version stated in this field.
+-- Starting from the specification version 2.2, the cabal-version field must be
+-- the first thing in the cabal file.
+
+-- Initial package description 'haskell-exps' generated by
+-- 'cabal init'. For further documentation, see:
+-- http://haskell.org/cabal/users-guide/
+--
+-- The name of the package.
+name: haskell-experiments
+
+-- The package version.
+-- See the Haskell package versioning policy (PVP) for standards
+-- guiding when and how versions should be incremented.
+-- https://pvp.haskell.org
+-- PVP summary: +-+------- breaking API changes
+-- | | +----- non-breaking API additions
+-- | | | +--- code changes with no API change
+version: 0.1.0.0
+
+-- A short (one-line) description of the package.
+synopsis: Sandbox
+
+-- A longer description of the package.
+-- description:
+
+-- The license under which the package is released.
+license: BSD-3-Clause
+
+-- The file containing the license text.
+license-file: LICENSE
+
+-- The package author(s).
+author: fdilke
+
+-- An email address to which users can send suggestions, bug reports, and patches.
+maintainer: fdilke@gmail.com
+
+-- A copyright notice.
+-- copyright:
+category: Development
+build-type: Simple
+
+-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.
+extra-doc-files: CHANGELOG.md
+
+-- Extra source files to be distributed with the package, such as examples, or a tutorial module.
+-- extra-source-files:
+
+common warnings
+ ghc-options: -Wall
+
+test-suite haskell-exps-test
+ -- Import common warning flags.
+ import: warnings
+
+ -- Base language which the package is written in.
+ default-language: Haskell2010
+
+ -- Modules included in this executable, other than Main.
+ -- other-modules:
+
+ -- LANGUAGE extensions used by modules in this package.
+ -- other-extensions:
+
+ -- The interface type and version of the test suite.
+ type: exitcode-stdio-1.0
+
+ -- Directories containing source files.
+ hs-source-dirs: test
+
+ -- The entrypoint to the test suite.
+ main-is: Main.hs
+
+ -- Test dependencies.
+ build-depends: base, hspec, langfeatures
+ other-modules: Test.OlogsSpec
+
+
+library langfeatures
+ build-depends: base, containers
+ hs-source-dirs: src
+ exposed-modules: Ologs
+ ghc-options: -Wall
+
+executable haskell-experiments
+ build-depends: base, containers
+ main-is: Main.hs
+ hs-source-dirs: src
+ default-language: Haskell2010
+
diff --git a/haskell-experiments/haskell-experiments.iml b/haskell-experiments/haskell-experiments.iml
new file mode 100644
index 0000000..8021953
--- /dev/null
+++ b/haskell-experiments/haskell-experiments.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/haskell-experiments.nix b/haskell-experiments/haskell-experiments.nix
new file mode 100644
index 0000000..8f85afd
--- /dev/null
+++ b/haskell-experiments/haskell-experiments.nix
@@ -0,0 +1,15 @@
+{ mkDerivation, base, hspec, lib }:
+mkDerivation {
+ pname = "haskell-exps";
+ version = "0.1.0.0";
+ src = ./.;
+ isLibrary = false;
+ isExecutable = true;
+ libraryHaskellDepends = [ base ];
+ executableHaskellDepends = [ base ];
+ testHaskellDepends = [ base hspec ];
+ doHaddock = false;
+ description = "Sandbox";
+ license = lib.licenses.bsd3;
+ mainProgram = "haskell-exps";
+}
diff --git a/haskell-experiments/haskell-parsing.iml b/haskell-experiments/haskell-parsing.iml
new file mode 100644
index 0000000..8021953
--- /dev/null
+++ b/haskell-experiments/haskell-parsing.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/haskell-experiments/shell.nix b/haskell-experiments/shell.nix
new file mode 100644
index 0000000..5d299a6
--- /dev/null
+++ b/haskell-experiments/shell.nix
@@ -0,0 +1,12 @@
+{pkgs ? import {}}:
+pkgs.haskellPackages.shellFor {
+ packages = hpkgs: [
+ (hpkgs.callPackage ./haskell-experiments.nix {})
+ ];
+ nativeBuildInputs = with pkgs; [
+ haskell-language-server
+ cabal-install
+ ];
+ withHoogle = true;
+ shellHook = "unset TEMP TMP TEMPDIR TMPDIR";
+}
diff --git a/haskell-experiments/src/Main.hs b/haskell-experiments/src/Main.hs
new file mode 100644
index 0000000..64f2149
--- /dev/null
+++ b/haskell-experiments/src/Main.hs
@@ -0,0 +1,5 @@
+module Main (main) where
+
+main :: IO ()
+main = putStrLn "Hello Haskell!"
+
diff --git a/haskell-experiments/src/Ologs.hs b/haskell-experiments/src/Ologs.hs
new file mode 100644
index 0000000..377c6a0
--- /dev/null
+++ b/haskell-experiments/src/Ologs.hs
@@ -0,0 +1,237 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+{-# HLINT ignore "Unused LANGUAGE pragma" #-}
+{-# HLINT ignore "Use concatMap" #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# HLINT ignore "Move catMaybes" #-}
+{-# HLINT ignore "Use mapMaybe" #-}
+{-# HLINT ignore "Use list comprehension" #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE NoFieldSelectors #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
+
+module Ologs
+ ( Arc,
+ Identity,
+ Olog,
+ makeOlog,
+ MakeOlogError (..),
+ )
+where
+
+import Control.Monad
+import Data.Foldable (for_)
+import Data.List.NonEmpty (NonEmpty, nonEmpty)
+import qualified Data.List.NonEmpty as NE
+import Data.Map (Map)
+import qualified Data.Map as Map
+import Data.Maybe
+import Data.Traversable
+import Debug.Trace
+
+data Arc dot = Arc
+ { name :: String,
+ source :: dot,
+ target :: dot
+ }
+ deriving (Show, Eq)
+
+data Identity = Identity
+ { lhs :: [String],
+ rhs :: [String]
+ }
+ deriving (Show, Eq)
+
+data Olog dot = Olog
+ { dots :: [dot],
+ arcs :: [Arc dot],
+ identities :: [Identity]
+ }
+ deriving (Show, Eq)
+
+makeOlogOld ::
+ forall dot.
+ (Eq dot, Show dot) =>
+ [dot] ->
+ [(String, dot, dot)] ->
+ [([String], [String])] ->
+ Either (MakeOlogError dot) (Olog dot)
+makeOlogOld dots preArcs preIdentities =
+ case errors of
+ [] ->
+ Right $
+ Olog
+ dots
+ (map (\(name, src, tgt) -> Arc {name = name, source = src, target = tgt}) preArcs)
+ ( (\(path1, path2) -> Identity {lhs = path1, rhs = path2}) <$> preIdentities
+ )
+ err : _ -> Left err
+ where
+ errorUnless b e = if b then Nothing else Just e
+ errors :: [MakeOlogError dot] = arcErrors <> identityErrors
+ arcErrors =
+ concat . concat $
+ map
+ ( fmap maybeToList . \(dotMapper, errorPrefix) ->
+ map (\arc@(name, _, _) -> (\dot -> errorUnless (dot `elem` dots) $ errorPrefix name dot) $ dotMapper arc) preArcs
+ )
+ [ (\(_, src, _) -> src, UnknownSource),
+ (\(_, _, tgt) -> tgt, UnknownTarget)
+ ]
+ knownArcNames = map (\(name, _, _) -> name) preArcs
+ identityErrors :: [MakeOlogError dot] =
+ identityKnownArcErrors <> identityLhsJoinErrors <> identityRhsJoinErrors <> identityMismatchErrors
+ identityKnownArcErrors =
+ concat $
+ map
+ ( \(lhs, rhs) ->
+ -- TODO: don't need to check triviality here
+ (if null lhs && null rhs then [ForbiddenTrivialIdentity] else [])
+ <> catMaybes
+ ( map
+ (\arcName -> errorUnless (arcName `elem` knownArcNames) $ UnknownArc arcName)
+ $ lhs <> rhs
+ )
+ )
+ preIdentities
+ namesToArcs :: Map String (dot, dot) = Map.fromList $ (\(s, src, tgt) -> (s, (src, tgt))) <$> preArcs
+ identityLhsJoinErrors = identityXhsJoinErrors NonJoiningExpressionLhs fst
+ identityRhsJoinErrors = identityXhsJoinErrors NonJoiningExpressionRhs snd
+ identityXhsJoinErrors ::
+ ([String] -> MakeOlogError dot) ->
+ (([String], [String]) -> [String]) ->
+ [MakeOlogError dot]
+ identityXhsJoinErrors errorFactory picker = catMaybes $ map (checkTerm errorFactory . picker) preIdentities
+ checkTerm :: ([String] -> MakeOlogError dot) -> [String] -> Maybe (MakeOlogError dot)
+ checkTerm errorFactory arcNames = errorUnless (targets == sources) $ errorFactory arcNames
+ where
+ arcs :: [(dot, dot)] = catMaybes $ flip Map.lookup namesToArcs <$> arcNames
+ targets :: [dot] = tail $ snd <$> arcs
+ sources :: [dot] = init $ fst <$> arcs
+ identityMismatchErrors = catMaybes $ checkMismatch <$> preIdentities
+ checkMismatch :: ([String], [String]) -> Maybe (MakeOlogError dot)
+ checkMismatch (lhs, rhs) = do
+ nonEmptyLhsAndSig <- case nonEmpty lhs of
+ Nothing ->
+ -- lhs empty
+ Just Nothing
+ Just nonEmptyLhs -> do
+ -- lhs non-empty
+ sig <- signature nonEmptyLhs
+ Just $ Just sig
+ nonEmptyRhsAndSig <- case nonEmpty rhs of
+ Nothing ->
+ -- rhs empty
+ Just Nothing
+ Just nonEmptyRhs -> do
+ -- rhs non-empty
+ sig <- signature nonEmptyRhs
+ Just $ Just sig
+ case (nonEmptyLhsAndSig, nonEmptyRhsAndSig) of
+ (Nothing, Nothing) ->
+ -- both empty
+ Just ForbiddenTrivialIdentity
+ (Just (src, tgt), Nothing) ->
+ -- right empty
+ errorUnless (src == tgt) $ NotALoop lhs
+ (Nothing, Just (src, tgt)) ->
+ -- left empty
+ errorUnless (src == tgt) $ NotALoop rhs
+ (Just lSig, Just rSig) ->
+ -- both non-empty
+ errorUnless (lSig == rSig) $ IdentityMismatch lhs rhs lSig rSig
+ where
+ signature :: NonEmpty String -> Maybe (dot, dot)
+ signature terms =
+ case Map.lookup (NE.last terms) namesToArcs of
+ Nothing -> Nothing
+ Just (src, _) ->
+ case Map.lookup (NE.head terms) namesToArcs of
+ Nothing -> Nothing
+ Just (_, tgt) -> Just (src, tgt)
+
+-- type f $ x = f x
+-- type ($) f x = f x
+
+data MakeOlogError dot
+ = UnknownSource String dot
+ | UnknownTarget String dot
+ | ForbiddenTrivialIdentity
+ | UnknownArc String
+ | NonJoiningExpressionLhs [String]
+ | NonJoiningExpressionRhs [String]
+ | IdentityMismatch [String] [String] (dot, dot) (dot, dot)
+ | NotALoop [String]
+ deriving (Show, Eq)
+
+makeOlog ::
+ forall dot.
+ (Eq dot) =>
+ [dot] ->
+ [(String, dot, dot)] ->
+ [([String], [String])] ->
+ Either (MakeOlogError dot) (Olog dot)
+makeOlog dots preArcs preIdentities = do
+ arcs <- for preArcs \(name, source, target) -> do
+ -- TODO reuse `namesToArcs`?
+ unless (source `elem` dots) $ Left $ UnknownSource name source
+ unless (target `elem` dots) $ Left $ UnknownTarget name target
+ pure Arc{name, source, target}
+ identities <- for preIdentities \(lhs, rhs) -> do
+ lhs' :: [(String, (dot, dot))] <- for lhs \arcName -> case Map.lookup arcName namesToArcs of
+ Nothing -> Left $ UnknownArc arcName
+ Just srcAndTgt -> pure (arcName, srcAndTgt)
+ rhs' :: [(String, (dot, dot))] <- for rhs \arcName -> case Map.lookup arcName namesToArcs of
+ Nothing -> Left $ UnknownArc arcName
+ Just srcAndTgt -> pure (arcName, srcAndTgt)
+ case (nonEmpty lhs', nonEmpty rhs') of
+ (Nothing, Nothing) ->
+ Left ForbiddenTrivialIdentity
+ (Just l, Nothing) -> do
+ checkTerm NonJoiningExpressionLhs l
+ let (_, (_, tgt)) = NE.head l
+ let (_, (src, _)) = NE.last l
+ errorWhen (src /= tgt) $ NotALoop lhs
+ (Nothing, Just r) -> do
+ checkTerm NonJoiningExpressionRhs r
+ let (_, (_, tgt)) = NE.head r
+ let (_, (src, _)) = NE.last r
+ errorWhen (src /= tgt) $ NotALoop rhs
+ (Just l, Just r) -> do
+ checkTerm NonJoiningExpressionLhs l
+ checkTerm NonJoiningExpressionRhs r
+ let combinedSrcTgt xhs = (fst $ snd $ NE.last xhs, snd $ snd $ NE.head xhs)
+ l' = combinedSrcTgt l
+ r' = combinedSrcTgt r
+ errorWhen (l' /= r') $ IdentityMismatch lhs rhs l' r'
+ pure Identity {lhs, rhs}
+ pure Olog {dots, arcs, identities}
+ where
+ checkTerm errorFactory arcs = do
+ let
+ targets = NE.tail $ snd . snd <$> (arcs :: (NonEmpty (String, (dot, dot))))
+ sources = NE.init $ fst . snd <$> arcs
+ errorWhen (sources /= targets) $ errorFactory $ map fst $ NE.toList arcs
+ errorWhen b e = if b then Left e else Right ()
+ namesToArcs = Map.fromList $ (\(name, src, tgt) -> (name, (src, tgt))) <$> preArcs
+
+-- checkArc :: (PreArc dot -> dot, String) -> PreArc dot -> Maybe String
+-- checkArc (mapper, errorPrefix) preArc =
+-- if mapper preArc `elem` dots then Nothing else Just $ errorPrefix <> show dot
+-- checkers :: [(PreArc dot -> dot, String)] =
+-- [ (\(_, src, _) -> src, "bad source: "),
+-- (\(_, _, tgt) -> tgt, "bad target: ")
+-- ]
+-- applyChecker :: (PreArc dot -> dot, String) -> Maybe String
+-- applyChecker (mapper, prefix) =
+-- map mapper arcs
+-- rawStrings :: [Maybe String] = map applyChecker [
+-- (\(_, src, _) -> src, "bad source: "),
+-- (\(_, _, tgt) -> tgt, "bad target: ")
+-- ]
+-- errors = []
diff --git a/haskell-experiments/test/Main.hs b/haskell-experiments/test/Main.hs
new file mode 100644
index 0000000..8fcaf22
--- /dev/null
+++ b/haskell-experiments/test/Main.hs
@@ -0,0 +1,11 @@
+module Main (main) where
+import Test.Hspec
+
+import qualified Test.OlogsSpec as Ologs
+--import Test.FooSpec
+
+main :: IO ()
+main = hspec $ do
+ describe "Ologs" Ologs.spec
+-- describe "My amazing tests" [ FastLaneSpec FooSpec ]
+
diff --git a/haskell-experiments/test/Test/OlogsSpec.hs b/haskell-experiments/test/Test/OlogsSpec.hs
new file mode 100644
index 0000000..b3b6bcd
--- /dev/null
+++ b/haskell-experiments/test/Test/OlogsSpec.hs
@@ -0,0 +1,93 @@
+{-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+{-# HLINT ignore "Use const" #-}
+{-# HLINT ignore "Unused LANGUAGE pragma" #-}
+{-# HLINT ignore "Avoid lambda" #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE NoFieldSelectors #-}
+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Test.OlogsSpec where
+
+import Data.Either (isRight)
+import Ologs
+import Test.Hspec
+
+type MaybeOlog = Either (MakeOlogError Int) (Olog Int)
+
+spec :: Spec
+spec = do
+ describe "olog sanity checks" $ do
+ it "arcs must have a source of a known dot" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog [1] [("source", 0, 1)] []
+ in badOlog `shouldBe` Left (UnknownSource "source" 0)
+ it "arcs must have a target of a known dot" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog [0] [("source", 0, 1)] []
+ in badOlog `shouldBe` Left (UnknownTarget "source" 1)
+ it "arc is then ok" $
+ let goodOlog :: MaybeOlog
+ goodOlog =
+ makeOlog [0, 1] [("y", 1, 0), ("x", 0, 1)] []
+ in isRight goodOlog `shouldBe` True
+ it "identities can't just say 1 = 1" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog [0] [] [([], [])]
+ in badOlog `shouldBe` Left ForbiddenTrivialIdentity
+ it "identities should only use known names" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog [0] [] [(["identity"], [])]
+ in badOlog `shouldBe` Left (UnknownArc "identity")
+ it "arcs in lhs of identities join up" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog
+ [0, 1, 2]
+ [("0to1", 0, 1), ("1to2", 1, 2), ("0to2", 0, 2), ("1to0", 1, 0)]
+ [(["0to1", "1to2"], ["0to2"])]
+ in badOlog `shouldBe` Left (NonJoiningExpressionLhs ["0to1", "1to2"])
+ it "arcs in rhs of identities join up" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog
+ [0, 1, 2]
+ [("0to1", 0, 1), ("1to2", 1, 2), ("0to2", 0, 2), ("1to0", 1, 0)]
+ [(["0to2"], ["0to1", "1to2"])]
+ in badOlog `shouldBe` Left (NonJoiningExpressionRhs ["0to1", "1to2"])
+ it "lhs and rhs of identities have same source and target" $
+ let badOlog :: MaybeOlog
+ badOlog =
+ makeOlog
+ [0, 1, 2]
+ [("0to1", 0, 1), ("1to2", 1, 2), ("0to2", 0, 2), ("1to0", 1, 0)]
+ [(["1to0", "0to1"], ["1to2", "0to1"])]
+ in badOlog `shouldBe` Left (IdentityMismatch ["1to0", "0to1"] ["1to2", "0to1"] (0, 0) (0, 2))
+ it "consistent joined-up identities are ok" $
+ let goodOlog :: MaybeOlog
+ goodOlog =
+ makeOlog
+ [0, 1, 2]
+ [("0to1", 0, 1), ("1to2", 1, 2), ("0to2", 0, 2), ("1to0", 1, 0)]
+ [(["1to2", "0to1"], ["0to2"])]
+ in
+ case goodOlog of
+ Left err -> expectationFailure $ show err
+ Right _ -> pure ()
+
+-- it "identities should have the same source and target on both sides" $
+-- describe "create a basic olog" $ do
+-- it "the graph olog" $
+-- let -- x :: Int
+-- -- x = 3
+-- graphOlog :: Either String (Olog Int)
+-- graphOlog =
+-- makeOlog [0, 1] [("source", 0, 1), ("target", 1, 0)] []
+-- in do
+-- [7, 8] `shouldBe` [7, 8]
+-- TODO: add test when [] == something that isn't a loop