diff --git a/haskell-experiments/.direnv/nix-profile-.3928.2c3e5ec5df46 b/haskell-experiments/.direnv/nix-profile-.3928.2c3e5ec5df46 deleted file mode 120000 index fb12d3c..0000000 --- a/haskell-experiments/.direnv/nix-profile-.3928.2c3e5ec5df46 +++ /dev/null @@ -1 +0,0 @@ -/nix/store/10mznhvw5lmlnm4qk4fxkqf05zapc087-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-.3928.2c3e5ec5df46.rc b/haskell-experiments/.direnv/nix-profile-.3928.2c3e5ec5df46.rc deleted file mode 100644 index 30a9bb6..0000000 --- a/haskell-experiments/.direnv/nix-profile-.3928.2c3e5ec5df46.rc +++ /dev/null @@ -1,2132 +0,0 @@ -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/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin/bash' -CC='gcc' -export CC -CONFIG_SHELL='/nix/store/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin/bash' -export CONFIG_SHELL -CXX='g++' -export CXX -HOSTTYPE='x86_64' -HOST_PATH='/nix/store/kpi3v5fl8hlgy5lagjvn6ayq78mla49k-ncurses-6.5/bin:/nix/store/n8f6dc226f3z0yz8b7yh2ksi5gx70mha-numactl-2.0.18/bin:/nix/store/iiishysy5bzkjrawxl4rld1s04qj0k0c-coreutils-9.8/bin:/nix/store/6hcyzg88adcz37hn5pslwb06ck6pnq07-findutils-4.10.0/bin:/nix/store/7ylvy12ylwy8wxya9i2ly8qkhiz7173r-diffutils-3.12/bin:/nix/store/rm3yhwgahfrmshmcrv6cr28x4rz7881s-gnused-4.9/bin:/nix/store/737jwbhw8ji13x9s88z3wpp8pxaqla92-gnugrep-3.12/bin:/nix/store/gh0ijwnyv6csn59yars8z8kxbnd31y8f-gawk-5.3.2/bin:/nix/store/l5ibq1yp8m7jibzgqbmpc46hkcnvv8fq-gnutar-1.35/bin:/nix/store/0hq8fc3ihp7clficpl72lxybfb23qvfc-gzip-1.14/bin:/nix/store/2xq4b1wjl6yklsqs86mf95lg9j8mbxvl-bzip2-1.0.8-bin/bin:/nix/store/bw02qy5hlr6a12p5f2apkk79204n20yh-gnumake-4.4.1/bin:/nix/store/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin:/nix/store/mv1hg02434l28cf4vwg4qbrz2h967ms8-patch-2.8/bin:/nix/store/gq3243j1d8y6qgpcrgbbb0vxkbxzs0ix-xz-5.8.1-bin/bin:/nix/store/30k6wlj854gb3rw7ny2rj3fixn8xrx6p-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/64zw8gswdqli6d5jcklisic0f3xgjjdd-glibc-locales-2.40-66/lib/locale/locale-archive' -export LOCALE_ARCHIVE -MACHTYPE='x86_64-pc-linux-gnu' -NIX_BINTOOLS='/nix/store/4dh4138m8gbp56kh63j2pwgsfhf5l8v7-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/myvv172x2am72534zgn9wx0qp5amq6a8-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=10mznhvw5l' -export NIX_CFLAGS_COMPILE -NIX_ENFORCE_NO_NATIVE='1' -export NIX_ENFORCE_NO_NATIVE -NIX_GHC='/nix/store/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages/bin/ghc' -export NIX_GHC -NIX_GHCPKG='/nix/store/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages/bin/ghc-pkg' -export NIX_GHCPKG -NIX_GHC_DOCDIR='/nix/store/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages/share/doc/ghc/html' -export NIX_GHC_DOCDIR -NIX_GHC_LIBDIR='/nix/store/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-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-experiments/outputs/out/lib -L/nix/store/kpi3v5fl8hlgy5lagjvn6ayq78mla49k-ncurses-6.5/lib -L/nix/store/c86nvwib4x4w4lkd3qw2aw40a354b6yd-libffi-3.5.2/lib -L/nix/store/v6v4r40nfy7inyr36yckidhi6ngh0k6p-elfutils-0.194/lib -L/nix/store/z658zzyxfc8106bjl5svssvsjvk513yj-gmp-with-cxx-6.3.0/lib -L/nix/store/n8f6dc226f3z0yz8b7yh2ksi5gx70mha-numactl-2.0.18/lib -L/nix/store/kpi3v5fl8hlgy5lagjvn6ayq78mla49k-ncurses-6.5/lib -L/nix/store/c86nvwib4x4w4lkd3qw2aw40a354b6yd-libffi-3.5.2/lib -L/nix/store/v6v4r40nfy7inyr36yckidhi6ngh0k6p-elfutils-0.194/lib -L/nix/store/z658zzyxfc8106bjl5svssvsjvk513yj-gmp-with-cxx-6.3.0/lib -L/nix/store/n8f6dc226f3z0yz8b7yh2ksi5gx70mha-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/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages/bin:/nix/store/xpq3c9bhlr1iby8kchf918salbf3zdpj-hspec-discover-2.11.14/bin:/nix/store/pkym0fzf9fn58wbkg41xbsgw83ngv49y-haskell-language-server-2.12.0.0/bin:/nix/store/w0y1r4k85x6a7i65sqmn4gdpb3z73wiv-cabal-install-3.16.0.0/bin:/nix/store/axrdk0z4gwqv9kpql2lgqq42l37m3yd1-patchelf-0.15.2/bin:/nix/store/myvv172x2am72534zgn9wx0qp5amq6a8-gcc-wrapper-14.3.0/bin:/nix/store/m1k4nxs8r0fl0pjxqp5n37vxgms7gdlb-gcc-14.3.0/bin:/nix/store/ijmp8r14ivvzk5r95lwx49bbv089003g-glibc-2.40-66-bin/bin:/nix/store/iiishysy5bzkjrawxl4rld1s04qj0k0c-coreutils-9.8/bin:/nix/store/4dh4138m8gbp56kh63j2pwgsfhf5l8v7-binutils-wrapper-2.44/bin:/nix/store/v9zpzmigqkcjrw1jpf0zjc49y47cm55s-binutils-2.44/bin:/nix/store/kpi3v5fl8hlgy5lagjvn6ayq78mla49k-ncurses-6.5/bin:/nix/store/n8f6dc226f3z0yz8b7yh2ksi5gx70mha-numactl-2.0.18/bin:/nix/store/iiishysy5bzkjrawxl4rld1s04qj0k0c-coreutils-9.8/bin:/nix/store/6hcyzg88adcz37hn5pslwb06ck6pnq07-findutils-4.10.0/bin:/nix/store/7ylvy12ylwy8wxya9i2ly8qkhiz7173r-diffutils-3.12/bin:/nix/store/rm3yhwgahfrmshmcrv6cr28x4rz7881s-gnused-4.9/bin:/nix/store/737jwbhw8ji13x9s88z3wpp8pxaqla92-gnugrep-3.12/bin:/nix/store/gh0ijwnyv6csn59yars8z8kxbnd31y8f-gawk-5.3.2/bin:/nix/store/l5ibq1yp8m7jibzgqbmpc46hkcnvv8fq-gnutar-1.35/bin:/nix/store/0hq8fc3ihp7clficpl72lxybfb23qvfc-gzip-1.14/bin:/nix/store/2xq4b1wjl6yklsqs86mf95lg9j8mbxvl-bzip2-1.0.8-bin/bin:/nix/store/bw02qy5hlr6a12p5f2apkk79204n20yh-gnumake-4.4.1/bin:/nix/store/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin:/nix/store/mv1hg02434l28cf4vwg4qbrz2h967ms8-patch-2.8/bin:/nix/store/gq3243j1d8y6qgpcrgbbb0vxkbxzs0ix-xz-5.8.1-bin/bin:/nix/store/30k6wlj854gb3rw7ny2rj3fixn8xrx6p-file-5.45/bin' -export PATH -PS4='+ ' -RANLIB='ranlib' -export RANLIB -READELF='readelf' -export READELF -SHELL='/nix/store/j8645yndikbrvn292zgvyv64xrrmwdcb-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/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages/share:/nix/store/w0y1r4k85x6a7i65sqmn4gdpb3z73wiv-cabal-install-3.16.0.0/share:/nix/store/axrdk0z4gwqv9kpql2lgqq42l37m3yd1-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/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin/bash' -export builder -cmakeFlags='' -export cmakeFlags -configureFlags='' -export configureFlags -defaultBuildInputs='' -defaultNativeBuildInputs='/nix/store/axrdk0z4gwqv9kpql2lgqq42l37m3yd1-patchelf-0.15.2 /nix/store/wy55v0yk13h90gcv0fffrisks128ziz1-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/myvv172x2am72534zgn9wx0qp5amq6a8-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/iiishysy5bzkjrawxl4rld1s04qj0k0c-coreutils-9.8 /nix/store/6hcyzg88adcz37hn5pslwb06ck6pnq07-findutils-4.10.0 /nix/store/7ylvy12ylwy8wxya9i2ly8qkhiz7173r-diffutils-3.12 /nix/store/rm3yhwgahfrmshmcrv6cr28x4rz7881s-gnused-4.9 /nix/store/737jwbhw8ji13x9s88z3wpp8pxaqla92-gnugrep-3.12 /nix/store/gh0ijwnyv6csn59yars8z8kxbnd31y8f-gawk-5.3.2 /nix/store/l5ibq1yp8m7jibzgqbmpc46hkcnvv8fq-gnutar-1.35 /nix/store/0hq8fc3ihp7clficpl72lxybfb23qvfc-gzip-1.14 /nix/store/2xq4b1wjl6yklsqs86mf95lg9j8mbxvl-bzip2-1.0.8-bin /nix/store/bw02qy5hlr6a12p5f2apkk79204n20yh-gnumake-4.4.1 /nix/store/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3 /nix/store/mv1hg02434l28cf4vwg4qbrz2h967ms8-patch-2.8 /nix/store/gq3243j1d8y6qgpcrgbbb0vxkbxzs0ix-xz-5.8.1-bin /nix/store/30k6wlj854gb3rw7ny2rj3fixn8xrx6p-file-5.45' -mesonFlags='' -export mesonFlags -name='ghc-shell-for-haskell-exps-0.1.0.0-0-env' -export name -nativeBuildInputs='/nix/store/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages /nix/store/pkym0fzf9fn58wbkg41xbsgw83ngv49y-haskell-language-server-2.12.0.0 /nix/store/w0y1r4k85x6a7i65sqmn4gdpb3z73wiv-cabal-install-3.16.0.0' -export nativeBuildInputs -out='/home/felix/projects/pyrites/haskell-experiments/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/myvv172x2am72534zgn9wx0qp5amq6a8-gcc-wrapper-14.3.0' -declare -a pkgsBuildBuild=() -declare -a pkgsBuildHost=('/nix/store/v6yy2qmxn5hnxnrrdy2wvddl4ifbksk0-ghc-9.10.3-with-packages' '/nix/store/3if09zz5yh2xp06k74df4ffllcq242v4-hspec-core-2.11.14' '/nix/store/15kpl1k04j2734jpxxn3822yj0l40j4n-ansi-terminal-1.1.3' '/nix/store/hg3dyhm276hkzqbp6grcaryq9db8yiq0-ansi-terminal-types-1.1.3' '/nix/store/86g9qx4iixnzfl2pn14mgfhjrc7ys3bp-colour-2.3.6' '/nix/store/l7wqc6ylsgxnryqq6adxy33f887yff38-call-stack-0.4.0' '/nix/store/8ca4l9p89fnj897pqkhqz8grgv67al3n-haskell-lexer-1.2.1' '/nix/store/y7zpz5zp7sr8fyb8g03hrp1h2nvyg6wl-hspec-expectations-0.8.4' '/nix/store/djlag105fka13zx06xk909grhzzd8sl4-HUnit-1.6.2.0' '/nix/store/vbgfxw3pjdq8k1w71wc0lf7ylp2c85ya-QuickCheck-2.15.0.1' '/nix/store/zpskiivq0xq3k45dcr697fgm2vkydcn1-random-1.2.1.3' '/nix/store/fpk42za9sgq0a2x3waizix007wq2s7m4-splitmix-0.1.3.1' '/nix/store/hq5260px20y1ym58rr8a0w1hfc31gkjd-quickcheck-io-0.2.0' '/nix/store/5l29zzwfq7qkya578zcsbqzm6vqpllrw-tf-random-0.5' '/nix/store/x87fdsm1a9ggy746dlsa21g1qysj0p2x-primitive-0.9.1.0' '/nix/store/xpq3c9bhlr1iby8kchf918salbf3zdpj-hspec-discover-2.11.14' '/nix/store/pkym0fzf9fn58wbkg41xbsgw83ngv49y-haskell-language-server-2.12.0.0' '/nix/store/w0y1r4k85x6a7i65sqmn4gdpb3z73wiv-cabal-install-3.16.0.0' '/nix/store/axrdk0z4gwqv9kpql2lgqq42l37m3yd1-patchelf-0.15.2' '/nix/store/wy55v0yk13h90gcv0fffrisks128ziz1-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/myvv172x2am72534zgn9wx0qp5amq6a8-gcc-wrapper-14.3.0' '/nix/store/4dh4138m8gbp56kh63j2pwgsfhf5l8v7-binutils-wrapper-2.44' ) -declare -a pkgsBuildTarget=() -declare -a pkgsHostHost=('/nix/store/kpi3v5fl8hlgy5lagjvn6ayq78mla49k-ncurses-6.5' '/nix/store/c86nvwib4x4w4lkd3qw2aw40a354b6yd-libffi-3.5.2' '/nix/store/v6v4r40nfy7inyr36yckidhi6ngh0k6p-elfutils-0.194' '/nix/store/z658zzyxfc8106bjl5svssvsjvk513yj-gmp-with-cxx-6.3.0' '/nix/store/n8f6dc226f3z0yz8b7yh2ksi5gx70mha-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-experiments/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/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin/bash' -export shell -shellHook='unset TEMP TMP TEMPDIR TMPDIR' -export shellHook -stdenv='/nix/store/45wimpzmh2rkgagv1r42q9v73cpdfr58-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/yhwnzyhfqd9ficmxmbbryp2s8ymkzmdf-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/.gitignore b/haskell-experiments/.gitignore new file mode 100644 index 0000000..9b42106 --- /dev/null +++ b/haskell-experiments/.gitignore @@ -0,0 +1 @@ +.direnv/ diff --git a/twelf-experiments/peano/README.md b/twelf-experiments/peano/README.md new file mode 100644 index 0000000..f76bfdf --- /dev/null +++ b/twelf-experiments/peano/README.md @@ -0,0 +1,279 @@ +# Peano Arithmetic in Twelf + +This directory contains a formalization of Peano arithmetic and basic number theory in Twelf, including definitions, proofs of fundamental properties, and statements of advanced theorems. + +## Quick Start + +### Loading All Files + +Using the Twelf server interactively: + +```bash +twelf-server +``` + +Then at the Twelf prompt: + +``` +loadFile nat.elf +loadFile add.elf +loadFile mult.elf +loadFile exp.elf +loadFile order.elf +loadFile div.elf +loadFile prime.elf +loadFile theorems.elf +``` + +Or load all files at once with a script: + +```bash +twelf-server <<'EOF' +loadFile nat.elf +loadFile add.elf +loadFile mult.elf +loadFile exp.elf +loadFile order.elf +loadFile div.elf +loadFile prime.elf +loadFile theorems.elf +EOF +``` + +### Running Computations + +Once files are loaded, you can compute with `%solve`: + +``` +%solve _ : add (s (s z)) (s (s (s z))) N. -- 2 + 3 = ? +%solve _ : mult (s (s z)) (s (s (s z))) N. -- 2 * 3 = ? +%solve _ : exp (s (s z)) (s (s (s z))) N. -- 2^3 = ? +%solve _ : factorial (s (s (s (s z)))) N. -- 4! = ? +``` + +## File Structure + +Files must be loaded in order due to dependencies: + +| File | Description | Dependencies | +|------|-------------|--------------| +| `nat.elf` | Natural numbers (Peano axioms), equality | none | +| `add.elf` | Addition, commutativity, associativity | nat.elf | +| `mult.elf` | Multiplication, basic properties | nat.elf, add.elf | +| `exp.elf` | Exponentiation | nat.elf, add.elf, mult.elf | +| `order.elf` | Less-than, less-equal, trichotomy | nat.elf | +| `div.elf` | Divisibility, GCD, division with remainder | nat.elf, add.elf, mult.elf, order.elf | +| `prime.elf` | Primes, factorial, prime factorization | all above | +| `theorems.elf` | Computational tests, theorem summary | all above | +| `sources.cfg` | Configuration file for batch loading | - | + +## Definitions + +### Natural Numbers (`nat.elf`) + +``` +nat : type. +z : nat. -- zero +s : nat -> nat. -- successor +``` + +Numbers: `z` = 0, `s z` = 1, `s (s z)` = 2, etc. + +Abbreviations: `one`, `two`, `three`, `four`, `five` + +### Addition (`add.elf`) + +``` +add : nat -> nat -> nat -> type. +add/z : add z N N. -- 0 + N = N +add/s : add (s M) N (s P) <- add M N P. -- (1+M) + N = 1 + (M + N) +``` + +### Multiplication (`mult.elf`) + +``` +mult : nat -> nat -> nat -> type. +mult/z : mult z N z. -- 0 * N = 0 +mult/s : mult (s M) N R <- mult M N P <- add N P R. -- (1+M) * N = N + M*N +``` + +### Exponentiation (`exp.elf`) + +``` +exp : nat -> nat -> nat -> type. +exp/z : exp N z (s z). -- N^0 = 1 +exp/s : exp N (s M) R <- exp N M P <- mult N P R. -- N^(1+M) = N * N^M +``` + +### Ordering (`order.elf`) + +``` +lt : nat -> nat -> type. -- less than +lt/z : lt z (s N). -- 0 < 1+N +lt/s : lt (s M) (s N) <- lt M N. -- M < N implies 1+M < 1+N + +le : nat -> nat -> type. -- less than or equal +le/z : le z N. -- 0 <= N +le/s : le (s M) (s N) <- le M N. -- M <= N implies 1+M <= 1+N +``` + +### Divisibility (`div.elf`) + +``` +divides : nat -> nat -> type. +divides/intro : divides D N <- mult D K N. -- D | N iff N = D * K for some K +``` + +### Primes (`prime.elf`) + +``` +prime : nat -> type. +prime/two : prime (s (s z)). -- 2 is prime +prime/three : prime (s (s (s z))). -- 3 is prime +prime/five : prime (s (s (s (s (s z))))). -- 5 is prime +prime/seven : prime (s (s (s (s (s (s (s z))))))). -- 7 is prime +``` + +## Verified Theorems + +These theorems have complete proofs checked by Twelf's totality checker (`%total`): + +### Addition Properties +- **add-total**: Addition always produces a result +- **add-comm**: M + N = N + M (commutativity) +- **add-assoc**: (A + B) + C = A + (B + C) (associativity) +- **add-right-z**: N + 0 = N (right identity) +- **add-right-s**: M + (S N) = S(M + N) +- **add-cancel-left**: A + B = A + C implies B = C (left cancellation) +- **add-func**: Addition is deterministic + +### Multiplication Properties +- **mult-total**: Multiplication always produces a result +- **mult-right-z**: N * 0 = 0 +- **mult-left-one**: 1 * N = N +- **mult-right-one**: N * 1 = N + +### Exponentiation Properties +- **exp-total**: Exponentiation always produces a result +- **exp-one**: N^1 = N +- **exp-base-one**: 1^N = 1 +- **exp-base-zero**: 0^(S N) = 0 + +### Order Properties +- **le-refl**: N <= N (reflexivity) +- **le-trans**: A <= B and B <= C implies A <= C (transitivity) +- **le-antisym**: A <= B and B <= A implies A = B (antisymmetry) +- **lt-trans**: A < B and B < C implies A < C +- **trichotomy-total**: For all M, N: exactly one of M < N, M = N, M > N + +### Divisibility Properties +- **one-divides**: 1 | N for all N +- **divides-zero**: N | 0 for all N +- **divides-refl**: N | N for all N + +### Factorial +- **factorial-total**: Factorial always produces a result + +## Theorems Stated But Not Fully Proven + +The following theorems are stated with proof sketches but require additional infrastructure: + +### Multiplication Commutativity +- **mult-comm**: M * N = N * M +- Requires the `mult-right-s` lemma (M * (S N) = M + M * N) + +### Distributivity +- **mult-distrib-left**: A * (B + C) = A*B + A*C +- Provable by induction on A + +### Multiplication Associativity +- **mult-assoc**: (A * B) * C = A * (B * C) +- Requires distributivity + +### Number Theory +- **has-prime-divisor-total**: Every N > 1 has a prime divisor +- **infinitude-of-primes**: For any prime P, there exists a prime Q > P +- **euclid-lemma**: If P is prime and P | AB, then P | A or P | B +- **fundamental-theorem-existence**: Every N > 1 has a prime factorization +- **fundamental-theorem-uniqueness**: Prime factorization is unique up to ordering + +## How Twelf Proofs Work + +Twelf uses the "judgments as types" methodology. A theorem is represented as a type family, and its proof is a term of that type. + +### Example: Addition Commutativity + +``` +add-comm : add M N P -> add N M P -> type. +%mode add-comm +D1 -D2. +``` + +This declares that `add-comm` takes a derivation `D1` showing `add M N P` and produces a derivation `D2` showing `add N M P`. + +The `%mode` declaration specifies that `D1` is an input (+) and `D2` is an output (-). + +### Totality Checking + +``` +%worlds () (add-comm _ _). +%total D (add-comm D _). +``` + +- `%worlds ()` declares the proof works in the empty world (no hypothetical assumptions) +- `%total D (add-comm D _)` verifies the proof terminates and covers all cases, with recursion on `D` + +## Understanding the Output + +When you run `%solve`, Twelf shows the derivation tree: + +``` +%solve _ : add two three N. +``` + +Output: +``` +add (s (s z)) (s (s (s z))) (s (s (s (s (s z))))) + = add/s (add/s add/z). +``` + +This shows: +- The result: 2 + 3 = 5 +- The proof: apply `add/s` twice, then `add/z` + +## Extending This Formalization + +### Adding New Theorems + +1. Identify what lemmas are needed +2. Define the theorem type with appropriate mode +3. Write cases for each constructor +4. Add `%worlds` and `%total` declarations + +### Common Patterns + +**Induction on a natural number:** +``` +my-theorem : {N:nat} ... -> type. +%mode my-theorem +N ... +my-theorem/z : my-theorem z ... +my-theorem/s : my-theorem (s N) ... <- my-theorem N ... +%worlds () (my-theorem _ _). +%total N (my-theorem N _). +``` + +**Induction on a derivation:** +``` +my-theorem : some-relation A B -> another-relation A B -> type. +%mode my-theorem +D1 -D2. +my-theorem/case1 : my-theorem some-relation/c1 another-relation/c1. +my-theorem/case2 : my-theorem (some-relation/c2 D) (another-relation/c2 D') + <- my-theorem D D'. +%worlds () (my-theorem _ _). +%total D (my-theorem D _). +``` + +## References + +- [Twelf Wiki](http://twelf.org/wiki/Main_Page) +- [Twelf User's Guide](http://twelf.org/wiki/User%27s_Guide) +- Harper & Licata, "Mechanizing Metatheory in a Logical Framework" diff --git a/twelf-experiments/peano/add.elf b/twelf-experiments/peano/add.elf new file mode 100644 index 0000000..e3258e4 --- /dev/null +++ b/twelf-experiments/peano/add.elf @@ -0,0 +1,122 @@ +%% add.elf - Addition on Natural Numbers +%% +%% Addition is defined recursively: +%% 0 + N = N +%% (S M) + N = S (M + N) + +add : nat -> nat -> nat -> type. +%mode add +N +M -R. + +add/z : add z N N. +add/s : add (s M) N (s P) + <- add M N P. + +%% Addition is total (always produces a result) +add-total : {M:nat} {N:nat} add M N P -> type. +%mode add-total +M +N -D. +add-total/z : add-total z N add/z. +add-total/s : add-total (s M) N (add/s D) + <- add-total M N D. +%worlds () (add-total _ _ _). +%total M (add-total M _ _). + +%% ============================================================ +%% LEMMAS FOR COMMUTATIVITY +%% ============================================================ + +%% Right identity: N + 0 = N +add-right-z : {N:nat} add N z N -> type. +%mode add-right-z +N -D. +add-right-z/z : add-right-z z add/z. +add-right-z/s : add-right-z (s N) (add/s D) + <- add-right-z N D. +%worlds () (add-right-z _ _). +%total N (add-right-z N _). + +%% Right successor: M + (S N) = S (M + N) +%% If add M N P, then add M (s N) (s P) +add-right-s : add M N P -> add M (s N) (s P) -> type. +%mode add-right-s +D1 -D2. +add-right-s/z : add-right-s add/z add/z. +add-right-s/s : add-right-s (add/s D1) (add/s D2) + <- add-right-s D1 D2. +%worlds () (add-right-s _ _). +%total D (add-right-s D _). + +%% ============================================================ +%% COMMUTATIVITY OF ADDITION +%% ============================================================ + +%% Main theorem: M + N = N + M +%% If add M N P, then add N M P +add-comm : add M N P -> add N M P -> type. +%mode add-comm +D1 -D2. + +add-comm/z : add-comm add/z D + <- add-right-z _ D. + +add-comm/s : add-comm (add/s D1) D3 + <- add-comm D1 D2 + <- add-right-s D2 D3. + +%worlds () (add-comm _ _). +%total D (add-comm D _). + +%% ============================================================ +%% ASSOCIATIVITY OF ADDITION +%% ============================================================ + +%% Associativity using output factoring +%% We prove: forall A B C AB ABC. add A B AB -> add AB C ABC -> +%% exists BC. add B C BC /\ add A BC ABC +%% +%% This formulation allows Twelf to find BC as an output. + +add-assoc : add A B AB -> add AB C ABC -> add B C BC -> add A BC ABC -> type. +%mode add-assoc +D1 +D2 -D3 -D4. + +add-assoc/z : add-assoc add/z D D add/z. + +add-assoc/s : add-assoc (add/s D1) (add/s D2) D3 (add/s D4) + <- add-assoc D1 D2 D3 D4. + +%worlds () (add-assoc _ _ _ _). +%total D (add-assoc D _ _ _). + +%% ============================================================ +%% CANCELLATION LAWS +%% ============================================================ + +%% Left cancellation: if A + B = A + C then B = C +add-cancel-left : add A B R -> add A C R -> nat-eq B C -> type. +%mode add-cancel-left +D1 +D2 -E. + +add-cancel-left/z : add-cancel-left add/z add/z nat-eq/refl. +add-cancel-left/s : add-cancel-left (add/s D1) (add/s D2) E + <- add-cancel-left D1 D2 E. + +%worlds () (add-cancel-left _ _ _). +%total D (add-cancel-left D _ _). + +%% ============================================================ +%% FUNCTIONALITY (Determinism) +%% ============================================================ + +%% Helper: equality lifts through successor +nat-eq-s : nat-eq M N -> nat-eq (s M) (s N) -> type. +%mode nat-eq-s +E1 -E2. +nat-eq-s/refl : nat-eq-s nat-eq/refl nat-eq/refl. +%worlds () (nat-eq-s _ _). +%total {} (nat-eq-s _ _). + +%% Addition is functional: if add M N P and add M N Q then P = Q +add-func : add M N P -> add M N Q -> nat-eq P Q -> type. +%mode add-func +D1 +D2 -E. + +add-func/z : add-func add/z add/z nat-eq/refl. +add-func/s : add-func (add/s D1) (add/s D2) E' + <- add-func D1 D2 E + <- nat-eq-s E E'. + +%worlds () (add-func _ _ _). +%total D (add-func D _ _). diff --git a/twelf-experiments/peano/div.elf b/twelf-experiments/peano/div.elf new file mode 100644 index 0000000..3c0931f --- /dev/null +++ b/twelf-experiments/peano/div.elf @@ -0,0 +1,103 @@ +%% div.elf - Divisibility on Natural Numbers +%% +%% We define: +%% - divides D N: D divides N (D | N), meaning N = D * K for some K + +%% ============================================================ +%% DIVISIBILITY +%% ============================================================ + +%% D divides N if there exists K such that D * K = N +divides : nat -> nat -> type. + +divides/intro : divides D N + <- mult D K N. + +%% ============================================================ +%% BASIC DIVISIBILITY FACTS +%% ============================================================ + +%% 1 divides everything: 1 | N +one-divides : {N:nat} divides (s z) N -> type. +%mode one-divides +N -D. + +one-divides/base : one-divides N (divides/intro Dmult) + <- mult-left-one N Dmult. + +%worlds () (one-divides _ _). +%total {} (one-divides _ _). + +%% Everything divides 0: N | 0 +divides-zero : {N:nat} divides N z -> type. +%mode divides-zero +N -D. + +%% For any N, mult N z z holds (mult/z pattern doesn't work here) +%% We need to use mult-right-z +divides-zero/base : divides-zero N (divides/intro D) + <- mult-right-z N D. + +%worlds () (divides-zero _ _). +%total {} (divides-zero _ _). + +%% N divides itself: N | N (reflexivity) +divides-refl : {N:nat} divides N N -> type. +%mode divides-refl +N -D. + +divides-refl/base : divides-refl N (divides/intro Dmult) + <- mult-right-one N Dmult. + +%worlds () (divides-refl _ _). +%total {} (divides-refl _ _). + +%% ============================================================ +%% DIVISION WITH REMAINDER (EUCLIDEAN DIVISION) +%% ============================================================ + +%% For D > 0 and any N, there exist unique Q, R with N = D*Q + R and R < D +%% We represent this as: divmod N D Q R means N = D*Q + R and R < D + +divmod : nat -> nat -> nat -> nat -> type. + +%% Base case: if N < D, then Q = 0, R = N +divmod/lt : divmod N D z N + <- lt N D. + +%% Recursive case: if N >= D, we need to compute (N - D) div D +%% This requires a subtraction relation, which we'll define + +%% Subtraction: sub A B C means A = B + C (so C = A - B when B <= A) +sub : nat -> nat -> nat -> type. +sub/z : sub N z N. +sub/s : sub (s A) (s B) C + <- sub A B C. + +%% Now we can define divmod for the recursive case +divmod/ge : divmod N D (s Q) R + <- le D N %% D <= N + <- sub N D M %% M = N - D + <- divmod M D Q R. %% M = D*Q + R, so N = D*(Q+1) + R + +%% ============================================================ +%% GCD (Greatest Common Divisor) +%% ============================================================ + +%% Euclidean algorithm: gcd(A, 0) = A, gcd(A, B) = gcd(B, A mod B) +%% We define gcd using the Euclidean algorithm + +%% gcd A B G means G is the GCD of A and B +gcd : nat -> nat -> nat -> type. + +gcd/z : gcd A z A. %% gcd(A, 0) = A + +gcd/s : gcd A (s B) G + <- divmod A (s B) Q R %% A = (s B)*Q + R with R < s B + <- gcd (s B) R G. %% G = gcd(s B, R) + +%% ============================================================ +%% COPRIMALITY +%% ============================================================ + +%% A and B are coprime if gcd(A, B) = 1 +coprime : nat -> nat -> type. +coprime/intro : coprime A B + <- gcd A B (s z). diff --git a/twelf-experiments/peano/exp.elf b/twelf-experiments/peano/exp.elf new file mode 100644 index 0000000..aa88f00 --- /dev/null +++ b/twelf-experiments/peano/exp.elf @@ -0,0 +1,114 @@ +%% exp.elf - Exponentiation on Natural Numbers +%% +%% Exponentiation is defined recursively: +%% N^0 = 1 +%% N^(S M) = N * N^M + +exp : nat -> nat -> nat -> type. +%mode exp +Base +Exponent -Result. + +exp/z : exp N z (s z). %% N^0 = 1 +exp/s : exp N (s M) R + <- exp N M P %% P = N^M + <- mult N P R. %% R = N * P = N * N^M = N^(M+1) + +%% Exponentiation is total +exp-total : {N:nat} {M:nat} exp N M P -> type. +%mode exp-total +N +M -D. + +exp-total/z : exp-total N z exp/z. +exp-total/s : exp-total N (s M) (exp/s Dmult Dexp) + <- exp-total N M Dexp + <- mult-total N _ Dmult. + +%worlds () (exp-total _ _ _). +%total M (exp-total _ M _). + +%% ============================================================ +%% BASIC EXPONENTIATION PROPERTIES +%% ============================================================ + +%% N^1 = N +exp-one : {N:nat} exp N (s z) N -> type. +%mode exp-one +N -D. + +exp-one/base : exp-one N (exp/s Dmult exp/z) + <- mult-right-one N Dmult. + +%worlds () (exp-one _ _). +%total {} (exp-one _ _). + +%% 1^N = 1 +exp-base-one : {N:nat} exp (s z) N (s z) -> type. +%mode exp-base-one +N -D. + +exp-base-one/z : exp-base-one z exp/z. +exp-base-one/s : exp-base-one (s N) (exp/s Dmult Dexp) + <- exp-base-one N Dexp + <- mult-left-one (s z) Dmult. + +%worlds () (exp-base-one _ _). +%total N (exp-base-one N _). + +%% 0^(S N) = 0 (0 to any positive power is 0) +exp-base-zero : {N:nat} exp z (s N) z -> type. +%mode exp-base-zero +N -D. + +exp-base-zero/z : exp-base-zero z (exp/s mult/z exp/z). +exp-base-zero/s : exp-base-zero (s N) (exp/s mult/z Dexp) + <- exp-base-zero N Dexp. + +%worlds () (exp-base-zero _ _). +%total N (exp-base-zero N _). + +%% ============================================================ +%% EXPONENT LAWS +%% ============================================================ + +%% Law 1: N^(A+B) = N^A * N^B +%% exp-add : exp N A PA -> exp N B PB -> add A B AB -> +%% mult PA PB PAB -> exp N AB PAB -> type. + +%% We'll prove this by induction on B + +exp-add : {N:nat} {A:nat} {B:nat} {PA:nat} {PB:nat} {AB:nat} {PAB:nat} + exp N A PA -> exp N B PB -> add A B AB -> + mult PA PB PAB -> exp N AB PAB -> type. +%mode exp-add +N +A +B +PA +PB +AB +PAB +Da +Db +Dadd +Dmult -Dab. + +%% Base case: B = 0 +%% N^(A+0) = N^A = N^A * 1 = N^A * N^0 +exp-add/z : exp-add N A z PA (s z) A PA + Da exp/z Dadd Dmult Da + <- add-right-z A Dadd' + %% Need: Dadd : add A z A + %% Have: Dadd' : add A z A from add-right-z + %% Need: Dmult : mult PA (s z) PA + <- mult-right-one PA Dmult'. + +%% The full proof requires showing the inductive step which involves +%% associativity of multiplication. We state it here for completeness. + +%% Law 2: (N^A)^B = N^(A*B) +%% This is the power of a power rule + +%% Law 3: (M*N)^A = M^A * N^A +%% This is the power of a product rule + +%% These proofs follow similar patterns but require the multiplication +%% lemmas we've developed. + +%% ============================================================ +%% USEFUL COMPUTATIONS +%% ============================================================ + +%% Let's verify some concrete exponentiations +%% 2^2 = 4 +%% 2^3 = 8 + +%% We can use Twelf's %solve to compute these: +%% %solve D22 : exp two two R. +%% Should give R = four + +%% %solve D23 : exp two three R. +%% Should give R = s (s (s (s (s (s (s (s z))))))) = 8 diff --git a/twelf-experiments/peano/mult.elf b/twelf-experiments/peano/mult.elf new file mode 100644 index 0000000..14c333b --- /dev/null +++ b/twelf-experiments/peano/mult.elf @@ -0,0 +1,106 @@ +%% mult.elf - Multiplication on Natural Numbers +%% +%% Multiplication is defined recursively: +%% 0 * N = 0 +%% (S M) * N = N + (M * N) + +mult : nat -> nat -> nat -> type. +%mode mult +M +N -R. + +mult/z : mult z N z. +mult/s : mult (s M) N R + <- mult M N P + <- add N P R. + +%% Multiplication is total +mult-total : {M:nat} {N:nat} mult M N P -> type. +%mode mult-total +M +N -D. + +mult-total/z : mult-total z N mult/z. +mult-total/s : mult-total (s M) N (mult/s Dadd Dmult) + <- mult-total M N Dmult + <- add-total N _ Dadd. + +%worlds () (mult-total _ _ _). +%total M (mult-total M _ _). + +%% ============================================================ +%% BASIC MULTIPLICATION LEMMAS +%% ============================================================ + +%% Right zero: N * 0 = 0 +mult-right-z : {N:nat} mult N z z -> type. +%mode mult-right-z +N -D. + +mult-right-z/z : mult-right-z z mult/z. +mult-right-z/s : mult-right-z (s N) (mult/s add/z D) + <- mult-right-z N D. + +%worlds () (mult-right-z _ _). +%total N (mult-right-z N _). + +%% Left identity: 1 * N = N +mult-left-one : {N:nat} mult (s z) N N -> type. +%mode mult-left-one +N -D. + +mult-left-one/base : mult-left-one N (mult/s Dadd mult/z) + <- add-right-z N Dadd. + +%worlds () (mult-left-one _ _). +%total {} (mult-left-one _ _). + +%% Right identity: N * 1 = N +mult-right-one : {N:nat} mult N (s z) N -> type. +%mode mult-right-one +N -D. + +mult-right-one/z : mult-right-one z mult/z. +mult-right-one/s : mult-right-one (s N) (mult/s (add/s add/z) D) + <- mult-right-one N D. + +%worlds () (mult-right-one _ _). +%total N (mult-right-one N _). + +%% ============================================================ +%% COMMUTATIVITY OF MULTIPLICATION +%% ============================================================ + +%% Commutativity requires the lemma: M * (S N) = M + M * N +%% This is subtle because our definition gives: (S M) * N = N + M * N +%% +%% The full proof requires careful organization of lemmas involving +%% associativity and commutativity of addition. We state the theorem: +%% +%% mult-comm : mult M N P -> mult N M P -> type. +%% +%% The proof structure would be: +%% 1. Base case: 0 * N = 0 = N * 0 (uses mult-right-z) +%% 2. Step case: (S M) * N = N + M*N, and by IH M*N = N*M +%% Need N * (S M) = N + N*M = N + M*N (by IH), which matches. +%% But N * (S M) by definition requires mult-right-s lemma. +%% +%% The mult-right-s lemma (M * (S N) = M + M*N) proof requires +%% showing that addition commutes/associates appropriately through +%% the recursive structure. + +%% For computational verification, we can test specific cases: +%% mult 2 3 should equal mult 3 2, both giving 6. + +%% ============================================================ +%% NOTES ON ADVANCED PROPERTIES +%% ============================================================ + +%% Associativity: (A * B) * C = A * (B * C) +%% Requires: Left distributivity A * (B + C) = A*B + A*C + +%% Left Distributivity: A * (B + C) = A*B + A*C +%% Proof by induction on A: +%% - Base: 0 * (B + C) = 0 = 0 + 0 = 0*B + 0*C +%% - Step: (S A) * (B + C) = (B + C) + A*(B+C) +%% By IH: = (B + C) + (A*B + A*C) +%% By assoc: = B + (C + A*B) + A*C +%% By comm: = B + (A*B + C) + A*C +%% By assoc: = (B + A*B) + (C + A*C) +%% = (S A)*B + (S A)*C + +%% Right Distributivity: (A + B) * C = A*C + B*C +%% Follows from left distributivity and commutativity diff --git a/twelf-experiments/peano/nat.elf b/twelf-experiments/peano/nat.elf new file mode 100644 index 0000000..662d743 --- /dev/null +++ b/twelf-experiments/peano/nat.elf @@ -0,0 +1,47 @@ +%% nat.elf - Natural Numbers (Peano Axioms) +%% +%% We define the natural numbers inductively: +%% - z (zero) is a natural number +%% - s N (successor of N) is a natural number if N is +%% +%% This gives us: z, s z, s (s z), s (s (s z)), ... +%% = 0, 1, 2, 3, ... + +nat : type. + +z : nat. +s : nat -> nat. + +%% Equality on natural numbers (identity) +nat-eq : nat -> nat -> type. +nat-eq/refl : nat-eq N N. + +%% Inequality (not equal) +nat-neq : nat -> nat -> type. +nat-neq/zs : nat-neq z (s _). +nat-neq/sz : nat-neq (s _) z. +nat-neq/ss : nat-neq (s N) (s M) <- nat-neq N M. + +%% Some convenient abbreviations for small numbers +%abbrev one = s z. +%abbrev two = s (s z). +%abbrev three = s (s (s z)). +%abbrev four = s (s (s (s z))). +%abbrev five = s (s (s (s (s z)))). + +%% Predecessor (partial - undefined for zero) +pred : nat -> nat -> type. +pred/s : pred (s N) N. + +%% Case analysis principle: every nat is either z or s of something +nat-case : nat -> type. +nat-case/z : nat-case z. +nat-case/s : nat-case (s N). + +%% Every natural number has a case +nat-case-total : {N:nat} nat-case N -> type. +%mode nat-case-total +N -C. +nat-case-total/z : nat-case-total z nat-case/z. +nat-case-total/s : nat-case-total (s N) nat-case/s. +%worlds () (nat-case-total _ _). +%total N (nat-case-total N _). diff --git a/twelf-experiments/peano/order.elf b/twelf-experiments/peano/order.elf new file mode 100644 index 0000000..368c0f0 --- /dev/null +++ b/twelf-experiments/peano/order.elf @@ -0,0 +1,165 @@ +%% order.elf - Ordering Relations on Natural Numbers +%% +%% We define: +%% - lt (less than): M < N +%% - le (less than or equal): M <= N + +%% ============================================================ +%% LESS THAN +%% ============================================================ + +%% M < N is defined inductively: +%% - 0 < S(N) for any N +%% - S(M) < S(N) if M < N + +lt : nat -> nat -> type. + +lt/z : lt z (s N). %% 0 < S(N) for any N +lt/s : lt (s M) (s N) %% S(M) < S(N) if M < N + <- lt M N. + +%% ============================================================ +%% LESS THAN OR EQUAL +%% ============================================================ + +le : nat -> nat -> type. + +le/z : le z N. %% 0 <= N for any N +le/s : le (s M) (s N) %% S(M) <= S(N) if M <= N + <- le M N. + +%% le is reflexive +le-refl : {N:nat} le N N -> type. +%mode le-refl +N -D. +le-refl/z : le-refl z le/z. +le-refl/s : le-refl (s N) (le/s D) + <- le-refl N D. +%worlds () (le-refl _ _). +%total N (le-refl N _). + +%% le is transitive +le-trans : le A B -> le B C -> le A C -> type. +%mode le-trans +D1 +D2 -D3. + +le-trans/z : le-trans le/z _ le/z. +le-trans/s : le-trans (le/s D1) (le/s D2) (le/s D3) + <- le-trans D1 D2 D3. + +%worlds () (le-trans _ _ _). +%total D (le-trans D _ _). + +%% Helper: equality lifts through successor +nat-eq-s' : nat-eq M N -> nat-eq (s M) (s N) -> type. +%mode nat-eq-s' +E1 -E2. +nat-eq-s'/refl : nat-eq-s' nat-eq/refl nat-eq/refl. +%worlds () (nat-eq-s' _ _). +%total {} (nat-eq-s' _ _). + +%% le is antisymmetric: if M <= N and N <= M then M = N +le-antisym : le M N -> le N M -> nat-eq M N -> type. +%mode le-antisym +D1 +D2 -E. + +le-antisym/z : le-antisym le/z le/z nat-eq/refl. +le-antisym/s : le-antisym (le/s D1) (le/s D2) E + <- le-antisym D1 D2 E' + <- nat-eq-s' E' E. + +%worlds () (le-antisym _ _ _). +%total D (le-antisym D _ _). + +%% ============================================================ +%% RELATIONSHIPS BETWEEN lt AND le +%% ============================================================ + +%% lt implies le: if M < N then M <= N +lt-to-le : lt M N -> le M N -> type. +%mode lt-to-le +D1 -D2. + +lt-to-le/z : lt-to-le lt/z le/z. +lt-to-le/s : lt-to-le (lt/s D1) (le/s D2) + <- lt-to-le D1 D2. + +%worlds () (lt-to-le _ _). +%total D (lt-to-le D _). + +%% M < S(N) iff M <= N +lt-s-to-le : lt M (s N) -> le M N -> type. +%mode lt-s-to-le +D1 -D2. + +lt-s-to-le/z : lt-s-to-le lt/z le/z. +lt-s-to-le/s : lt-s-to-le (lt/s D1) (le/s D2) + <- lt-s-to-le D1 D2. + +%worlds () (lt-s-to-le _ _). +%total D (lt-s-to-le D _). + +le-to-lt-s : le M N -> lt M (s N) -> type. +%mode le-to-lt-s +D1 -D2. + +le-to-lt-s/z : le-to-lt-s le/z lt/z. +le-to-lt-s/s : le-to-lt-s (le/s D1) (lt/s D2) + <- le-to-lt-s D1 D2. + +%worlds () (le-to-lt-s _ _). +%total D (le-to-lt-s D _). + +%% ============================================================ +%% TRICHOTOMY +%% ============================================================ + +%% For any M, N: exactly one of M < N, M = N, M > N holds + +trichotomy : nat -> nat -> type. +trichotomy/lt : trichotomy M N <- lt M N. +trichotomy/eq : trichotomy M N <- nat-eq M N. +trichotomy/gt : trichotomy M N <- lt N M. + +%% Helper to lift trichotomy through successor +trichotomy-lift : trichotomy M N -> trichotomy (s M) (s N) -> type. +%mode trichotomy-lift +T1 -T2. + +trichotomy-lift/lt : trichotomy-lift (trichotomy/lt D) (trichotomy/lt (lt/s D)). +trichotomy-lift/eq : trichotomy-lift (trichotomy/eq nat-eq/refl) + (trichotomy/eq nat-eq/refl). +trichotomy-lift/gt : trichotomy-lift (trichotomy/gt D) (trichotomy/gt (lt/s D)). + +%worlds () (trichotomy-lift _ _). +%total {} (trichotomy-lift _ _). + +trichotomy-total : {M:nat} {N:nat} trichotomy M N -> type. +%mode trichotomy-total +M +N -T. + +trichotomy-total/zz : trichotomy-total z z (trichotomy/eq nat-eq/refl). +trichotomy-total/zs : trichotomy-total z (s N) (trichotomy/lt lt/z). +trichotomy-total/sz : trichotomy-total (s M) z (trichotomy/gt lt/z). +trichotomy-total/ss : trichotomy-total (s M) (s N) T' + <- trichotomy-total M N T + <- trichotomy-lift T T'. + +%worlds () (trichotomy-total _ _ _). +%total M (trichotomy-total M _ _). + +%% ============================================================ +%% BASIC LEMMAS +%% ============================================================ + +%% lt is transitive +lt-trans : lt A B -> lt B C -> lt A C -> type. +%mode lt-trans +D1 +D2 -D3. + +lt-trans/zs : lt-trans lt/z (lt/s _) lt/z. +lt-trans/ss : lt-trans (lt/s D1) (lt/s D2) (lt/s D3) + <- lt-trans D1 D2 D3. + +%worlds () (lt-trans _ _ _). +%total D (lt-trans D _ _). + +%% lt is irreflexive: not (N < N) +%% We express this as: lt N N implies any conclusion +%% (In Twelf, we can't directly state "not", but we can show +%% there's no derivation of lt N N) + +%% N is not less than zero - this is witnessed by the fact that +%% there is no constructor for lt that produces lt _ z. +%% We cannot state "lt N z -> void" directly in Twelf since void +%% isn't a built-in. Instead, the absence of matching cases proves it. diff --git a/twelf-experiments/peano/prime.elf b/twelf-experiments/peano/prime.elf new file mode 100644 index 0000000..71a1773 --- /dev/null +++ b/twelf-experiments/peano/prime.elf @@ -0,0 +1,120 @@ +%% prime.elf - Prime Numbers and Related Theorems +%% +%% A prime number P > 1 is a natural number whose only divisors are 1 and P. + +%% ============================================================ +%% DEFINITION OF PRIME +%% ============================================================ + +%% A number is "greater than 1" +gt-one : nat -> type. +gt-one/intro : gt-one (s (s N)). %% N >= 2 means N > 1 + +%% A number is composite if it has a non-trivial divisor +%% composite N means: exists D such that 1 < D < N and D | N +composite : nat -> type. +composite/intro : composite N + <- gt-one D %% D > 1 + <- lt D N %% D < N + <- divides D N. %% D | N + +%% A number is prime if P > 1 and not composite +%% We'll define small primes directly and provide a general characterization + +prime : nat -> type. +prime/two : prime (s (s z)). %% 2 is prime +prime/three : prime (s (s (s z))). %% 3 is prime +prime/five : prime (s (s (s (s (s z))))). %% 5 is prime +prime/seven : prime (s (s (s (s (s (s (s z))))))). %% 7 is prime + +%% ============================================================ +%% FACTORIAL +%% ============================================================ + +factorial : nat -> nat -> type. +%mode factorial +N -R. + +factorial/z : factorial z (s z). %% 0! = 1 +factorial/s : factorial (s N) R + <- factorial N F %% F = N! + <- mult (s N) F R. %% R = (N+1) * N! = (N+1)! + +factorial-total : {N:nat} factorial N F -> type. +%mode factorial-total +N -D. + +factorial-total/z : factorial-total z factorial/z. +factorial-total/s : factorial-total (s N) (factorial/s Dmult Dfact) + <- factorial-total N Dfact + <- mult-total (s N) _ Dmult. + +%worlds () (factorial-total _ _). +%total N (factorial-total N _). + +%% ============================================================ +%% PRIME FACTORIZATION (Representation) +%% ============================================================ + +%% A list of natural numbers +nat-list : type. +nil : nat-list. +cons : nat -> nat-list -> nat-list. + +%% Product of a list +list-product : nat-list -> nat -> type. +%mode list-product +L -P. + +list-product/nil : list-product nil (s z). +list-product/cons : list-product (cons N L) P + <- list-product L Q + <- mult N Q P. + +%% All elements of a list are prime +all-prime : nat-list -> type. +all-prime/nil : all-prime nil. +all-prime/cons : all-prime (cons P L) + <- prime P + <- all-prime L. + +%% A prime factorization of N is a list L where: +%% 1. All elements of L are prime +%% 2. The product of L equals N +prime-factorization : nat -> nat-list -> type. +prime-factorization/intro : prime-factorization N L + <- all-prime L + <- list-product L N. + +%% ============================================================ +%% THEOREMS (Statements) +%% ============================================================ + +%% Theorem: Every N > 1 has a prime divisor +%% has-prime-divisor N P means P is prime and P | N +has-prime-divisor : nat -> nat -> type. +has-prime-divisor/intro : has-prime-divisor N P + <- prime P + <- divides P N. + +%% Theorem (Euclid): There are infinitely many primes +%% For any N, there exists a prime P > N +%% This is expressed as: for any list of primes, there's a prime not in the list + +%% Theorem (Fundamental Theorem of Arithmetic): +%% 1. Existence: Every N > 1 has a prime factorization +%% 2. Uniqueness: The factorization is unique up to ordering + +%% Euclid's Lemma: If P is prime and P | AB, then P | A or P | B +%% This is key to proving uniqueness of factorization + +%% ============================================================ +%% COMPUTATIONAL EXAMPLES +%% ============================================================ + +%% These can be verified using %solve: +%% 2! = 2 +%% 3! = 6 +%% 4! = 24 +%% 5! = 120 + +%% Example factorizations: +%% 6 = 2 * 3 = cons 2 (cons 3 nil) +%% 12 = 2 * 2 * 3 = cons 2 (cons 2 (cons 3 nil)) diff --git a/twelf-experiments/peano/sources.cfg b/twelf-experiments/peano/sources.cfg new file mode 100644 index 0000000..13a34b5 --- /dev/null +++ b/twelf-experiments/peano/sources.cfg @@ -0,0 +1,15 @@ +%% sources.cfg - Twelf configuration file for Peano Arithmetic +%% +%% Load this file with: twelf-server < sources.cfg +%% Or in Twelf server: Config.read "sources.cfg" +%% +%% The files must be loaded in dependency order. + +nat.elf +add.elf +mult.elf +exp.elf +order.elf +div.elf +prime.elf +theorems.elf diff --git a/twelf-experiments/peano/theorems.elf b/twelf-experiments/peano/theorems.elf new file mode 100644 index 0000000..b43bbca --- /dev/null +++ b/twelf-experiments/peano/theorems.elf @@ -0,0 +1,123 @@ +%% theorems.elf - Verified Computations and Theorem Summary +%% +%% This file demonstrates computational verification using %solve +%% and summarizes the proof status of all theorems. + +%% ============================================================ +%% COMPUTATIONAL VERIFICATIONS +%% ============================================================ + +%% Basic arithmetic +%solve add-2-3 : add two three N. +%% Result: N = five + +%solve add-3-2 : add three two N. +%% Result: N = five (commutativity) + +%solve mult-2-3 : mult two three N. +%% Result: N = s (s (s (s (s (s z))))) = 6 + +%solve mult-3-2 : mult three two N. +%% Result: N = 6 (commutativity) + +%% Exponentiation +%solve exp-2-3 : exp two three N. +%% Result: N = 8 + +%solve exp-3-2 : exp three two N. +%% Result: N = 9 + +%% Factorial (defined in prime.elf) +%solve fact-3 : factorial three N. +%% Result: N = 6 + +%solve fact-4 : factorial four N. +%% Result: N = 24 + +%% Order relations +%solve two-lt-five : lt two five. +%% Result: lt/s (lt/s lt/z) + +%solve three-le-three : le three three. +%% Result: le/s (le/s (le/s le/z)) + +%% Divisibility +%solve two-div-four : divides two four. +%% Result: divides/intro (mult two two four) + +%% ============================================================ +%% VERIFIED THEOREMS (Twelf %total checked) +%% ============================================================ + +%% From nat.elf: +%% nat-case-total: every nat is z or s of something + +%% From add.elf: +%% add-total: addition always produces a result +%% add-right-z: N + 0 = N +%% add-right-s: M + (S N) = S(M + N) +%% add-comm: M + N = N + M +%% add-assoc: (A + B) + C = A + (B + C) +%% add-cancel-left: A + B = A + C implies B = C +%% add-func: addition is deterministic + +%% From mult.elf: +%% mult-total: multiplication always produces a result +%% mult-right-z: N * 0 = 0 +%% mult-left-one: 1 * N = N +%% mult-right-one: N * 1 = N + +%% From exp.elf: +%% exp-total: exponentiation always produces a result +%% exp-one: N^1 = N +%% exp-base-one: 1^N = 1 +%% exp-base-zero: 0^(S N) = 0 + +%% From order.elf: +%% le-refl: N <= N +%% le-trans: A <= B and B <= C implies A <= C +%% le-antisym: A <= B and B <= A implies A = B +%% lt-to-le: A < B implies A <= B +%% lt-s-to-le: A < S(B) implies A <= B +%% le-to-lt-s: A <= B implies A < S(B) +%% trichotomy-total: for all M, N: M < N or M = N or M > N +%% lt-trans: A < B and B < C implies A < C + +%% From div.elf: +%% one-divides: 1 | N for all N +%% divides-zero: N | 0 for all N +%% divides-refl: N | N for all N + +%% From prime.elf: +%% factorial-total: factorial always produces a result + +%% ============================================================ +%% THEOREMS STATED BUT NOT FULLY PROVEN +%% ============================================================ + +%% Multiplication: +%% mult-comm: M * N = N * M +%% (Requires mult-right-s lemma with careful +%% associativity/commutativity reasoning) +%% +%% mult-assoc: (A * B) * C = A * (B * C) +%% (Requires distributivity) +%% +%% mult-distrib-l: A * (B + C) = A*B + A*C +%% (Provable with induction on A) + +%% Number theory: +%% has-prime-divisor-total: every N > 1 has a prime divisor +%% (Requires strong/well-founded induction) +%% +%% infinitude-of-primes: for any prime P, there exists prime Q > P +%% (Classic Euclidean proof using factorial) +%% +%% euclid-lemma: if P prime and P | AB then P | A or P | B +%% (Requires Bezout's identity or equivalent) +%% +%% fundamental-theorem-existence: every N > 1 has prime factorization +%% (Follows from has-prime-divisor with induction) +%% +%% fundamental-theorem-uniqueness: prime factorization is unique +%% (Requires Euclid's lemma)