content: lambda calculus

This commit is contained in:
Maciej Jur 2024-09-08 15:38:21 +02:00
parent bf3341850b
commit 95e060567e
Signed by: kamov
GPG key ID: 191CBFF5F72ECAFD
10 changed files with 557 additions and 848 deletions

453
Cargo.lock generated
View file

@ -29,12 +29,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "aligned-vec"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.18" version = "0.2.18"
@ -105,70 +99,18 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
[[package]]
name = "arg_enum_proc_macro"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]] [[package]]
name = "arraydeque" name = "arraydeque"
version = "0.5.1" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "av1-grain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf"
dependencies = [
"anyhow",
"arrayvec",
"log",
"nom",
"num-rational",
"v_frame",
]
[[package]]
name = "avif-serialize"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2"
dependencies = [
"arrayvec",
]
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.22.1" version = "0.22.1"
@ -206,12 +148,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bitstream-io"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499"
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -221,12 +157,6 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "built"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.16.0" version = "3.16.0"
@ -245,12 +175,6 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.6.0" version = "1.6.0"
@ -271,21 +195,6 @@ name = "cc"
version = "1.0.96" version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
dependencies = [
"jobserver",
"libc",
"once_cell",
]
[[package]]
name = "cfg-expr"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
dependencies = [
"smallvec",
"target-lexicon",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -956,43 +865,22 @@ dependencies = [
[[package]] [[package]]
name = "image" name = "image"
version = "0.25.2" version = "0.24.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"byteorder-lite", "byteorder",
"color_quant", "color_quant",
"exr", "exr",
"gif", "gif",
"image-webp", "jpeg-decoder",
"num-traits", "num-traits",
"png", "png",
"qoi", "qoi",
"ravif",
"rayon",
"rgb",
"tiff", "tiff",
"zune-core",
"zune-jpeg",
] ]
[[package]]
name = "image-webp"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904"
dependencies = [
"byteorder-lite",
"quick-error",
]
[[package]]
name = "imgref"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "2.2.6"
@ -1024,17 +912,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "interpolate_name"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.0" version = "1.70.0"
@ -1050,35 +927,20 @@ dependencies = [
"either", "either",
] ]
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.10" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "jobserver"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.3.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
dependencies = [
"rayon",
]
[[package]] [[package]]
name = "js-sys" name = "js-sys"
@ -1132,7 +994,7 @@ checksum = "4bdbc7a1823f188f56ac9486993536b70a2686a58d47095dcc10507a7d242bf5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"derive_builder", "derive_builder",
"itertools 0.10.5", "itertools",
"quick-js", "quick-js",
"thiserror", "thiserror",
] ]
@ -1184,17 +1046,6 @@ version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libfuzzer-sys"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
dependencies = [
"arbitrary",
"cc",
"once_cell",
]
[[package]] [[package]]
name = "libquickjs-sys" name = "libquickjs-sys"
version = "0.9.0" version = "0.9.0"
@ -1221,36 +1072,12 @@ version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "loop9"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
dependencies = [
"imgref",
]
[[package]]
name = "maybe-rayon"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.1" version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.4" version = "0.7.4"
@ -1273,28 +1100,6 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "noop_proc_macro"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]] [[package]]
name = "notify" name = "notify"
version = "6.1.1" version = "6.1.1"
@ -1335,47 +1140,6 @@ dependencies = [
"tree-sitter", "tree-sitter",
] ]
[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-derive"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.18"
@ -1451,12 +1215,6 @@ dependencies = [
"siphasher", "siphasher",
] ]
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]] [[package]]
name = "png" name = "png"
version = "0.17.13" version = "0.17.13"
@ -1520,25 +1278,6 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "profiling"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
dependencies = [
"quote",
"syn 2.0.53",
]
[[package]] [[package]]
name = "pulldown-cmark" name = "pulldown-cmark"
version = "0.12.0" version = "0.12.0"
@ -1567,12 +1306,6 @@ dependencies = [
"bytemuck", "bytemuck",
] ]
[[package]]
name = "quick-error"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]] [[package]]
name = "quick-js" name = "quick-js"
version = "0.4.1" version = "0.4.1"
@ -1632,55 +1365,6 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "rav1e"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9"
dependencies = [
"arbitrary",
"arg_enum_proc_macro",
"arrayvec",
"av1-grain",
"bitstream-io",
"built",
"cfg-if",
"interpolate_name",
"itertools 0.12.1",
"libc",
"libfuzzer-sys",
"log",
"maybe-rayon",
"new_debug_unreachable",
"noop_proc_macro",
"num-derive",
"num-traits",
"once_cell",
"paste",
"profiling",
"rand",
"rand_chacha",
"simd_helpers",
"system-deps",
"thiserror",
"v_frame",
"wasm-bindgen",
]
[[package]]
name = "ravif"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5797d09f9bd33604689e87e8380df4951d4912f01b63f71205e2abd4ae25e6b6"
dependencies = [
"avif-serialize",
"imgref",
"loop9",
"quick-error",
"rav1e",
"rgb",
]
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.10.0" version = "1.10.0"
@ -1739,15 +1423,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rgb"
version = "0.8.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade4539f42266ded9e755c605bdddf546242b2c961b03b06a7375260788a0523"
dependencies = [
"bytemuck",
]
[[package]] [[package]]
name = "rstml" name = "rstml"
version = "0.11.2" version = "0.11.2"
@ -1820,15 +1495,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.9.33" version = "0.9.33"
@ -1870,15 +1536,6 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simd_helpers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"
dependencies = [
"quote",
]
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "0.3.11" version = "0.3.11"
@ -1968,25 +1625,6 @@ dependencies = [
"syn 2.0.53", "syn 2.0.53",
] ]
[[package]]
name = "system-deps"
version = "6.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
dependencies = [
"cfg-expr",
"heck 0.5.0",
"pkg-config",
"toml",
"version-compare",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.59" version = "1.0.59"
@ -2042,40 +1680,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]] [[package]]
name = "tree-sitter" name = "tree-sitter"
version = "0.22.6" version = "0.22.6"
@ -2344,23 +1948,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "v_frame"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b"
dependencies = [
"aligned-vec",
"num-traits",
"wasm-bindgen",
]
[[package]]
name = "version-compare"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"
@ -2615,15 +2202,6 @@ version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "winnow"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "yaml-rust2" name = "yaml-rust2"
version = "0.8.1" version = "0.8.1"
@ -2655,12 +2233,6 @@ dependencies = [
"syn 2.0.53", "syn 2.0.53",
] ]
[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
[[package]] [[package]]
name = "zune-inflate" name = "zune-inflate"
version = "0.2.54" version = "0.2.54"
@ -2669,12 +2241,3 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
dependencies = [ dependencies = [
"simd-adler32", "simd-adler32",
] ]
[[package]]
name = "zune-jpeg"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768"
dependencies = [
"zune-core",
]

View file

@ -0,0 +1,10 @@
@book{DBLP:books/daglib/0005958,
author = {Benjamin C. Pierce},
title = {Types and programming languages},
publisher = {{MIT} Press},
year = {2002},
isbn = {978-0-262-16209-8},
timestamp = {Thu, 03 Feb 2011 10:51:35 +0100},
biburl = {https://dblp.org/rec/books/daglib/0005958.bib},
bibsource = {dblp computer science bibliography, https://dblp.org}
}

View file

@ -0,0 +1,85 @@
---
title: Lambda calculus is the DNA of all computation
date: 2024-09-07T20:32:00.281Z
desc: >
Lambda calculus can be used to express any computation, but what does it entail? As it turns out first class functions are the single most powerful abstraction.
---
In lambda calculus the entire grammar of the language comprises of just three kinds of expressions
1. variables
2. lambda abstraction
3. application
The grammar can be formulated recursively as
```
t ::=
x // variable
λx.t // lambda abstraction
t t // application
```
In lambda calculus functions accept only a single argument, but they can be nested, this is referred to as currying in the literature. For example, we can have a simple function that just returns its argument $\lambda x. x$ which is generally known as the identity function.
Any language that has first class functions with closures can be used to simulate lambda calculus. As an example I will use my own custom toy language.
```
// variable declaration
let a = 10;
// function declaration (id)
let f x = x;
// anonymous function (id)
let g = fn x -> x;
// function application
f g 1
```
The result of evaluating `f g 1` is `1`, because `f g``g` and `g 1``1`.
As we can see the language can be used to express every single term we have in lambda calculus. Can these terms be used to express any computation? As it turns out yes, in fact we can encode data type using just functions. These encodings are called [Church encodings](https://en.wikipedia.org/wiki/Church_encoding) in the literature.
Let's start with booleans, they can be defined as follows:
$$
\begin{align}
\text{tru} = \lambda \text{t}.\: \lambda \text{f}.\: \text{t}; \\
\text{fls} = \lambda \text{t}.\: \lambda \text{f}.\: \text{f};
\end{align}
$$
```
let tru t f = t;
let fls t f = f;
```
And then we can defined a function that will work just like `if ... then ... else ...` in general purpose programming languages.
$$\text{test} = \lambda \text{l}.\: \lambda \text{m}.\: \lambda \text{n}.\: \text{l}\, \text{m}\, \text{n};$$
```
let test l m n = l m n;
```
Let's also defined the `and` combinator which checks if two values are true.
$$\text{and} = \lambda \text{b}.\: \lambda \text{c}.\: \text{b}\, \text{c}\, \text{fls};$$
```
let and_ b c = b c fls;
```
Let's see if this works! Feel free to play around with the code...
<pre class="flox-eval">
let tru t f = t;
let fls t f = f;
let test l m n = l m n;
let and_ b c = b c fls;
test (and_ tru tru) "both true!" "nope"
</pre>

36
js/flox/lambda.ts Normal file
View file

@ -0,0 +1,36 @@
import { EditorState } from "@codemirror/state";
import { EditorView, keymap, lineNumbers } from "@codemirror/view";
import { defaultKeymap } from "@codemirror/commands";
import { init, evaluate } from "./wasm";
function instantiate(element: HTMLElement): EditorView {
const divEditor = document.createElement("div");
const divOutput = document.createElement("pre");
const initState = element.innerText.trim();
element.innerText = "";
element.appendChild(divEditor);
element.appendChild(divOutput);
divEditor.className = "editor";
divOutput.className = "output";
init.then((_) => (divOutput.innerText = evaluate(initState)));
const state = EditorState.create({
doc: initState,
extensions: [
keymap.of(defaultKeymap),
lineNumbers(),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
divOutput.innerText = evaluate(update.state.doc.toString());
}
}),
],
});
return new EditorView({ state, parent: divEditor });
}
for (const el of document.getElementsByClassName("flox-eval")) {
const editor = instantiate(el as HTMLElement);
}

View file

@ -1,7 +1,7 @@
import { EditorState } from '@codemirror/state'; import { EditorState } from "@codemirror/state";
import { EditorView, keymap, lineNumbers } from '@codemirror/view'; import { EditorView, keymap, lineNumbers } from "@codemirror/view";
import { defaultKeymap } from '@codemirror/commands'; import { defaultKeymap } from "@codemirror/commands";
import * as wasm from './pkg/flox_wasm'; import { evaluate } from "./wasm";
const doc = ` const doc = `
let n1 = 2; let n1 = 2;
@ -15,27 +15,17 @@ let add a b = a + b;
|> fn n -> n * -1 |> fn n -> n * -1
`; `;
const htmlEditor = document.getElementById('editor')!; const htmlEditor = document.getElementById("editor")!;
const htmlOutput = document.getElementById('output')!; const htmlOutput = document.getElementById("output")!;
const htmlRun = document.getElementById('run')!; const htmlRun = document.getElementById("run")!;
const state = EditorState.create({ const state = EditorState.create({
doc, doc,
extensions: [ extensions: [keymap.of(defaultKeymap), lineNumbers()],
keymap.of(defaultKeymap),
lineNumbers()
],
}); });
const view = new EditorView({ state, parent: htmlEditor }); const view = new EditorView({ state, parent: htmlEditor });
WebAssembly.compileStreaming(fetch('flox_wasm_bg.wasm')).then((asm) => wasm.initSync(asm)); htmlRun.addEventListener("click", () => {
htmlOutput.textContent = evaluate(view.state.doc.toString());
function run(code: string) {
return wasm.eval_expression(code);
}
htmlRun.addEventListener('click', () => {
const code = view.state.doc.toString();
htmlOutput.textContent = run(code);
}); });

10
js/flox/wasm.ts Normal file
View file

@ -0,0 +1,10 @@
import * as wasm from "./pkg/flox_wasm";
const PATH = "/static/flox_wasm_bg.wasm";
const INIT = WebAssembly.compileStreaming(fetch(PATH)).then(wasm.initSync);
export const init = INIT;
export function evaluate(source: string): string {
return wasm.eval_expression(source);
}

View file

@ -8,54 +8,56 @@ use serde::Deserialize;
/// Represents a simple post. /// Represents a simple post.
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub(crate) struct Post { pub(crate) struct Post {
pub(crate) title: String, pub(crate) title: String,
#[serde(with = "super::isodate")] #[serde(with = "super::isodate")]
pub(crate) date: DateTime<Utc>, pub(crate) date: DateTime<Utc>,
pub(crate) desc: Option<String>, pub(crate) desc: Option<String>,
} }
impl Content for Post { impl Content for Post {
fn parse_content( fn parse_content(
content: &str, content: &str,
sack: &Sack, sack: &Sack,
path: &Utf8Path, path: &Utf8Path,
library: Option<&Library>, library: Option<&Library>,
) -> (String, Outline, Bibliography) { ) -> (String, Outline, Bibliography) {
crate::text::md::parse(content, sack, path, library) crate::text::md::parse(content, sack, path, library)
} }
fn as_html( fn as_html(
&self, &self,
parsed: &str, parsed: &str,
sack: &Sack, sack: &Sack,
outline: Outline, outline: Outline,
bibliography: Bibliography, bibliography: Bibliography,
) -> String { ) -> String {
post(self, parsed, sack, outline, bibliography).render().into() post(self, parsed, sack, outline, bibliography)
} .render()
.into()
}
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> { fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
Some(Linkable::Date(LinkDate { Some(Linkable::Date(LinkDate {
link: Link { link: Link {
path, path,
name: self.title.to_owned(), name: self.title.to_owned(),
desc: self.desc.to_owned(), desc: self.desc.to_owned(),
}, },
date: self.date.to_owned(), date: self.date.to_owned(),
})) }))
} }
} }
pub fn post<'s, 'p, 'html>( pub fn post<'s, 'p, 'html>(
metadata: &'p Post, metadata: &'p Post,
parsed: &'p str, parsed: &'p str,
sack: &'s Sack, sack: &'s Sack,
outline: Outline, outline: Outline,
bibliography: Bibliography, bibliography: Bibliography,
) -> impl Renderable + 'html ) -> impl Renderable + 'html
where where
's: 'html, 's: 'html,
'p: 'html, 'p: 'html,
{ {
let main = maud_move!( let main = maud_move!(
main { main {
@ -63,46 +65,48 @@ where
} }
); );
crate::html::page(sack, main, metadata.title.clone()) crate::html::page(sack, main, metadata.title.clone())
} }
pub fn article<'p, 's, 'html>( pub fn article<'p, 's, 'html>(
title: &'p str, title: &'p str,
parsed: &'p str, parsed: &'p str,
_: &'s Sack, _: &'s Sack,
outline: Outline, outline: Outline,
bibliography: Bibliography, bibliography: Bibliography,
) -> impl Renderable + 'html ) -> impl Renderable + 'html
where where
's: 'html, 's: 'html,
'p: 'html, 'p: 'html,
{ {
maud_move!( maud_move!(
div .wiki-main { div .wiki-main {
// Slide in/out for mobile // Slide in/out for mobile
input #wiki-aside-shown type="checkbox" hidden; input #wiki-aside-shown type="checkbox" hidden;
aside .wiki-aside { aside .wiki-aside {
// Slide button // Slide button
label .wiki-aside__slider for="wiki-aside-shown" { label .wiki-aside__slider for="wiki-aside-shown" {
img .wiki-icon src="/static/svg/double-arrow.svg" width="24" height="24"; img .wiki-icon src="/static/svg/double-arrow.svg" width="24" height="24";
} }
(crate::html::misc::show_outline(outline)) (crate::html::misc::show_outline(outline))
} }
article .wiki-article /*class:list={classlist)*/ { article .wiki-article /*class:list={classlist)*/ {
header class="markdown" { header class="markdown" {
h1 #top { (title) } h1 #top { (title) }
} }
section .wiki-article__markdown.markdown { section .wiki-article__markdown.markdown {
(Raw(parsed)) (Raw(parsed))
} }
@if let Some(bib) = bibliography.0 { @if let Some(bib) = bibliography.0 {
(crate::html::misc::show_bibliography(bib)) (crate::html::misc::show_bibliography(bib))
} }
}
} script type="module" {(Raw(r#"import "lambda";"#))}
) }
}
)
} }

View file

@ -32,6 +32,7 @@ fn main() {
.js("photos", "./js/vanilla/photos.js") .js("photos", "./js/vanilla/photos.js")
.js("reveal", "./js/vanilla/reveal.js") .js("reveal", "./js/vanilla/reveal.js")
.js("editor", "./js/flox/main.ts") .js("editor", "./js/flox/main.ts")
.js("lambda", "./js/flox/lambda.ts")
.add_virtual( .add_virtual(
|sack| crate::html::map(sack).render().to_owned().into(), |sack| crate::html::map(sack).render().to_owned().into(),
"map/index.html".into(), "map/index.html".into(),

View file

@ -3,10 +3,10 @@ use std::collections::HashMap;
use camino::{Utf8Path, Utf8PathBuf}; use camino::{Utf8Path, Utf8PathBuf};
use hauchiwa::{Bibliography, Outline, Sack}; use hauchiwa::{Bibliography, Outline, Sack};
use hayagriva::{ use hayagriva::{
archive::ArchivedStyle, archive::ArchivedStyle,
citationberg::{IndependentStyle, Locale, Style}, citationberg::{IndependentStyle, Locale, Style},
BibliographyDriver, BibliographyRequest, BufWriteFormat, CitationItem, CitationRequest, BibliographyDriver, BibliographyRequest, BufWriteFormat, CitationItem, CitationRequest,
Library, Library,
}; };
use hypertext::Renderable; use hypertext::Renderable;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -16,370 +16,369 @@ use regex::Regex;
use crate::ts; use crate::ts;
static OPTS: Lazy<Options> = Lazy::new(|| { static OPTS: Lazy<Options> = Lazy::new(|| {
Options::empty() Options::empty()
.union(Options::ENABLE_MATH) .union(Options::ENABLE_MATH)
.union(Options::ENABLE_TABLES) .union(Options::ENABLE_TABLES)
.union(Options::ENABLE_TASKLISTS) .union(Options::ENABLE_TASKLISTS)
.union(Options::ENABLE_STRIKETHROUGH) .union(Options::ENABLE_STRIKETHROUGH)
.union(Options::ENABLE_SMART_PUNCTUATION) .union(Options::ENABLE_SMART_PUNCTUATION)
}); });
static KATEX_I: Lazy<katex::Opts> = Lazy::new(|| { static KATEX_I: Lazy<katex::Opts> = Lazy::new(|| {
katex::opts::Opts::builder() katex::opts::Opts::builder()
.output_type(katex::OutputType::Mathml) .output_type(katex::OutputType::Mathml)
.build() .build()
.unwrap() .unwrap()
}); });
static KATEX_B: Lazy<katex::Opts> = Lazy::new(|| { static KATEX_B: Lazy<katex::Opts> = Lazy::new(|| {
katex::opts::Opts::builder() katex::opts::Opts::builder()
.output_type(katex::OutputType::Mathml) .output_type(katex::OutputType::Mathml)
.display_mode(true) .display_mode(true)
.build() .build()
.unwrap() .unwrap()
}); });
static LOCALE: Lazy<Vec<Locale>> = Lazy::new(hayagriva::archive::locales); static LOCALE: Lazy<Vec<Locale>> = Lazy::new(hayagriva::archive::locales);
static STYLE: Lazy<IndependentStyle> = static STYLE: Lazy<IndependentStyle> =
Lazy::new(|| match ArchivedStyle::InstituteOfPhysicsNumeric.get() { Lazy::new(
Style::Independent(style) => style, || match ArchivedStyle::InstituteOfElectricalAndElectronicsEngineers.get() {
Style::Dependent(_) => unreachable!(), Style::Independent(style) => style,
}); Style::Dependent(_) => unreachable!(),
},
);
pub fn parse( pub fn parse(
content: &str, content: &str,
sack: &Sack, sack: &Sack,
path: &Utf8Path, path: &Utf8Path,
library: Option<&Library>, library: Option<&Library>,
) -> (String, Outline, Bibliography) { ) -> (String, Outline, Bibliography) {
let (outline, stream) = { let (outline, stream) = {
let stream = Parser::new_ext(content, *OPTS); let stream = Parser::new_ext(content, *OPTS);
let mut stream: Vec<_> = TextMergeStream::new(stream).collect(); let mut stream: Vec<_> = TextMergeStream::new(stream).collect();
let outline = set_heading_ids(&mut stream); let outline = set_heading_ids(&mut stream);
(outline, stream) (outline, stream)
}; };
let stream = stream let stream = stream
.into_iter() .into_iter()
.map(make_math) .map(make_math)
.map(make_emoji) .map(make_emoji)
.map(swap_hashed_image(path, sack)) .map(swap_hashed_image(path, sack))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let stream = make_code(stream) let stream = make_code(stream)
.into_iter() .into_iter()
.flat_map(make_ruby) .flat_map(make_ruby)
.flat_map(make_cite) .flat_map(make_cite)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let (stream, bib) = match library { let (stream, bib) = match library {
Some(lib) => make_bib(stream, lib), Some(lib) => make_bib(stream, lib),
None => (stream, None), None => (stream, None),
}; };
let mut parsed = String::new(); let mut parsed = String::new();
pulldown_cmark::html::push_html(&mut parsed, stream.into_iter()); pulldown_cmark::html::push_html(&mut parsed, stream.into_iter());
(parsed, outline, Bibliography(bib)) (parsed, outline, Bibliography(bib))
} }
fn make_bib<'a, 'b>( fn make_bib<'a, 'b>(
stream: Vec<Event<'a>>, stream: Vec<Event<'a>>,
lib: &'b Library, lib: &'b Library,
) -> (Vec<Event<'a>>, Option<Vec<String>>) { ) -> (Vec<Event<'a>>, Option<Vec<String>>) {
let mut driver = BibliographyDriver::new(); let mut driver = BibliographyDriver::new();
for event in stream.iter() { for event in stream.iter() {
match event { match event {
Event::InlineMath(ref text) => match lib.get(text) { Event::InlineMath(ref text) => match lib.get(text) {
Some(entry) => driver.citation(CitationRequest::from_items( Some(entry) => driver.citation(CitationRequest::from_items(
vec![CitationItem::with_entry(entry)], vec![CitationItem::with_entry(entry)],
&STYLE, &STYLE,
&LOCALE, &LOCALE,
)), )),
None => (), None => (),
}, },
_ => (), _ => (),
} }
} }
// add fake citation to make all entries show up // add fake citation to make all entries show up
driver.citation(CitationRequest::from_items( driver.citation(CitationRequest::from_items(
lib.iter().map(CitationItem::with_entry).collect(), lib.iter().map(CitationItem::with_entry).collect(),
&STYLE, &STYLE,
&LOCALE, &LOCALE,
)); ));
let res = driver.finish(BibliographyRequest { let res = driver.finish(BibliographyRequest {
style: &STYLE, style: &STYLE,
locale: None, locale: None,
locale_files: &LOCALE, locale_files: &LOCALE,
}); });
let mut n = 0; let mut n = 0;
let stream = stream let stream = stream
.into_iter() .into_iter()
.map(|event| match event { .map(|event| match event {
Event::InlineMath(name) => { Event::InlineMath(name) => {
let mut buffer = String::from("<cite>"); let mut buffer = String::from("<cite>");
match res.citations.get(n) { match res.citations.get(n) {
Some(rf) => rf Some(rf) => rf
.citation .citation
.write_buf(&mut buffer, BufWriteFormat::Html) .write_buf(&mut buffer, BufWriteFormat::Html)
.unwrap(), .unwrap(),
None => buffer.push_str(&name), None => buffer.push_str(&name),
}; };
buffer.push_str("</cite>"); buffer.push_str("</cite>");
n += 1; n += 1;
Event::InlineHtml(buffer.into()) Event::InlineHtml(buffer.into())
} }
_ => event, _ => event,
}) })
.collect(); .collect();
let bib = res.bibliography.map(|bib| { let bib = res.bibliography.map(|bib| {
bib.items bib.items
.iter() .iter()
.map(|x| { .map(|x| {
let mut buffer = String::new(); let mut buffer = String::new();
x.content x.content
.write_buf(&mut buffer, BufWriteFormat::Html) .write_buf(&mut buffer, BufWriteFormat::Html)
.unwrap(); .unwrap();
buffer buffer
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
}); });
(stream, bib) (stream, bib)
} }
static RE_CITE: Lazy<Regex> = Lazy::new(|| Regex::new(r":cite\[([^\]]+)\]").unwrap()); static RE_CITE: Lazy<Regex> = Lazy::new(|| Regex::new(r":cite\[([^\]]+)\]").unwrap());
#[derive(Debug)] #[derive(Debug)]
enum Annotated_<'a> { enum Annotated_<'a> {
Text(&'a str), Text(&'a str),
Cite(&'a str), Cite(&'a str),
} }
fn annotate_(input: &str) -> Vec<Annotated_> { fn annotate_(input: &str) -> Vec<Annotated_> {
let mut parts: Vec<Annotated_> = Vec::new(); let mut parts: Vec<Annotated_> = Vec::new();
let mut last_index = 0; let mut last_index = 0;
for cap in RE_CITE.captures_iter(input) { for cap in RE_CITE.captures_iter(input) {
let cite = cap.get(1).unwrap().as_str(); let cite = cap.get(1).unwrap().as_str();
let index = cap.get(0).unwrap().start(); let index = cap.get(0).unwrap().start();
if index > last_index { if index > last_index {
parts.push(Annotated_::Text(&input[last_index..index])); parts.push(Annotated_::Text(&input[last_index..index]));
} }
parts.push(Annotated_::Cite(cite)); parts.push(Annotated_::Cite(cite));
last_index = cap.get(0).unwrap().end(); last_index = cap.get(0).unwrap().end();
} }
if last_index < input.len() { if last_index < input.len() {
parts.push(Annotated_::Text(&input[last_index..])); parts.push(Annotated_::Text(&input[last_index..]));
} }
parts parts
} }
fn make_cite(event: Event) -> Vec<Event> { fn make_cite(event: Event) -> Vec<Event> {
match event { match event {
Event::Text(ref text) => annotate_(text) Event::Text(ref text) => annotate_(text)
.into_iter() .into_iter()
.map(|e| match e { .map(|e| match e {
Annotated_::Text(text) => Event::Text(text.to_owned().into()), Annotated_::Text(text) => Event::Text(text.to_owned().into()),
Annotated_::Cite(cite) => Event::InlineMath(cite.to_owned().into()), Annotated_::Cite(cite) => Event::InlineMath(cite.to_owned().into()),
}) })
.collect(), .collect(),
_ => vec![event], _ => vec![event],
} }
} }
fn set_heading_ids(events: &mut [Event]) -> Outline { fn set_heading_ids(events: &mut [Event]) -> Outline {
let mut cnt = HashMap::<String, i32>::new(); let mut cnt = HashMap::<String, i32>::new();
let mut out = Vec::new(); let mut out = Vec::new();
let mut buf = String::new(); let mut buf = String::new();
let mut ptr = None; let mut ptr = None;
for event in events { for event in events {
match event { match event {
Event::Start(ref mut tag @ Tag::Heading { .. }) => { Event::Start(ref mut tag @ Tag::Heading { .. }) => {
ptr = Some(tag); ptr = Some(tag);
} }
Event::Text(ref text) if ptr.is_some() => buf.push_str(text), Event::Text(ref text) if ptr.is_some() => buf.push_str(text),
Event::End(TagEnd::Heading(..)) => { Event::End(TagEnd::Heading(..)) => {
let txt = std::mem::take(&mut buf); let txt = std::mem::take(&mut buf);
let url = txt.to_lowercase().replace(' ', "-"); let url = txt.to_lowercase().replace(' ', "-");
let url = match cnt.get_mut(&url) { let url = match cnt.get_mut(&url) {
Some(ptr) => { Some(ptr) => {
*ptr += 1; *ptr += 1;
format!("{url}-{ptr}") format!("{url}-{ptr}")
} }
None => { None => {
cnt.insert(url.clone(), 0); cnt.insert(url.clone(), 0);
url url
} }
}; };
match ptr.take().unwrap() { match ptr.take().unwrap() {
Tag::Heading { ref mut id, .. } => *id = Some(url.clone().into()), Tag::Heading { ref mut id, .. } => *id = Some(url.clone().into()),
_ => unreachable!(), _ => unreachable!(),
} }
out.push((txt, url)); out.push((txt, url));
} }
_ => (), _ => (),
} }
} }
Outline(out) Outline(out)
} }
fn make_math(event: Event) -> Event { fn make_math(event: Event) -> Event {
match event { match event {
Event::InlineMath(math) => { Event::InlineMath(math) => {
Event::InlineHtml(katex::render_with_opts(&math, &*KATEX_I).unwrap().into()) Event::InlineHtml(katex::render_with_opts(&math, &*KATEX_I).unwrap().into())
} }
Event::DisplayMath(math) => { Event::DisplayMath(math) => {
Event::Html(katex::render_with_opts(&math, &*KATEX_B).unwrap().into()) Event::Html(katex::render_with_opts(&math, &*KATEX_B).unwrap().into())
} }
_ => event, _ => event,
} }
} }
fn make_code(es: Vec<Event>) -> Vec<Event> { fn make_code(es: Vec<Event>) -> Vec<Event> {
let mut buff = Vec::new(); let mut buff = Vec::new();
let mut lang = None; let mut lang = None;
let mut code = String::new(); let mut code = String::new();
for event in es { for event in es {
match event { match event {
Event::Start(Tag::CodeBlock(kind)) => match kind { Event::Start(Tag::CodeBlock(kind)) => match kind {
CodeBlockKind::Indented => (), CodeBlockKind::Indented => (),
CodeBlockKind::Fenced(name) => lang = Some(name), CodeBlockKind::Fenced(name) => lang = Some(name),
}, },
Event::End(TagEnd::CodeBlock) => { Event::End(TagEnd::CodeBlock) => {
let lang = lang.take().unwrap_or("".into()); let lang = lang.take().unwrap_or("".into());
let html = ts::highlight(&lang, &code).render().as_str().to_owned(); let html = ts::highlight(&lang, &code).render().as_str().to_owned();
buff.push(Event::Html(html.into())); buff.push(Event::Html(html.into()));
code.clear(); code.clear();
} }
Event::Text(text) => match lang { Event::Text(text) => match lang {
None => buff.push(Event::Text(text)), None => buff.push(Event::Text(text)),
Some(_) => code.push_str(&text), Some(_) => code.push_str(&text),
}, },
_ => buff.push(event), _ => buff.push(event),
} }
} }
buff buff
} }
static RE_RUBY: Lazy<Regex> = Lazy::new(|| Regex::new(r"\[([^\]]+)\]\{([^}]+)\}").unwrap()); static RE_RUBY: Lazy<Regex> = Lazy::new(|| Regex::new(r"\[([^\]]+)\]\{([^}]+)\}").unwrap());
#[derive(Debug)] #[derive(Debug)]
enum Annotated<'a> { enum Annotated<'a> {
Text(&'a str), Text(&'a str),
Ruby(&'a str, &'a str), Ruby(&'a str, &'a str),
} }
fn annotate(input: &str) -> Vec<Annotated> { fn annotate(input: &str) -> Vec<Annotated> {
let mut parts: Vec<Annotated> = Vec::new(); let mut parts: Vec<Annotated> = Vec::new();
let mut last_index = 0; let mut last_index = 0;
for cap in RE_RUBY.captures_iter(input) { for cap in RE_RUBY.captures_iter(input) {
let text = cap.get(1).unwrap().as_str(); let text = cap.get(1).unwrap().as_str();
let ruby = cap.get(2).unwrap().as_str(); let ruby = cap.get(2).unwrap().as_str();
let index = cap.get(0).unwrap().start(); let index = cap.get(0).unwrap().start();
if index > last_index { if index > last_index {
parts.push(Annotated::Text(&input[last_index..index])); parts.push(Annotated::Text(&input[last_index..index]));
} }
parts.push(Annotated::Ruby(text, ruby)); parts.push(Annotated::Ruby(text, ruby));
last_index = cap.get(0).unwrap().end(); last_index = cap.get(0).unwrap().end();
} }
if last_index < input.len() { if last_index < input.len() {
parts.push(Annotated::Text(&input[last_index..])); parts.push(Annotated::Text(&input[last_index..]));
} }
parts parts
} }
fn make_ruby(event: Event) -> Vec<Event> { fn make_ruby(event: Event) -> Vec<Event> {
match event { match event {
Event::Text(ref text) => annotate(text) Event::Text(ref text) => annotate(text)
.into_iter() .into_iter()
.map(|el| match el { .map(|el| match el {
Annotated::Text(text) => Event::Text(text.to_owned().into()), Annotated::Text(text) => Event::Text(text.to_owned().into()),
Annotated::Ruby(t, f) => Event::InlineHtml( Annotated::Ruby(t, f) => Event::InlineHtml(
format!("<ruby>{t}<rp>(</rp><rt>{f}</rt><rp>)</rp></ruby>").into(), format!("<ruby>{t}<rp>(</rp><rt>{f}</rt><rp>)</rp></ruby>").into(),
), ),
}) })
.collect(), .collect(),
_ => vec![event], _ => vec![event],
} }
} }
fn make_emoji(event: Event) -> Event { fn make_emoji(event: Event) -> Event {
match event { match event {
Event::Text(ref text) => { Event::Text(ref text) => {
let mut buf = None; let mut buf = None;
let mut top = 0; let mut top = 0;
let mut old = 0; let mut old = 0;
for (idx, _) in text.match_indices(':') { for (idx, _) in text.match_indices(':') {
let key = &text[old..idx]; let key = &text[old..idx];
if let Some(emoji) = emojis::get_by_shortcode(key) { if let Some(emoji) = emojis::get_by_shortcode(key) {
let buf = buf.get_or_insert_with(|| String::with_capacity(text.len())); let buf = buf.get_or_insert_with(|| String::with_capacity(text.len()));
buf.push_str(&text[top..old - 1]); buf.push_str(&text[top..old - 1]);
buf.push_str(emoji.as_str()); buf.push_str(emoji.as_str());
top = idx + 1; top = idx + 1;
} }
old = idx + 1; old = idx + 1;
} }
if let Some(ref mut buf) = buf { if let Some(ref mut buf) = buf {
buf.push_str(&text[top..]); buf.push_str(&text[top..]);
} }
match buf { match buf {
None => event, None => event,
Some(buf) => Event::Text(buf.into()), Some(buf) => Event::Text(buf.into()),
} }
} }
_ => event, _ => event,
} }
} }
fn swap_hashed_image<'a>( fn swap_hashed_image<'a>(dir: &'a Utf8Path, sack: &'a Sack) -> impl Fn(Event) -> Event + 'a {
dir: &'a Utf8Path, move |event| match event {
sack: &'a Sack, Event::Start(start) => match start {
) -> impl Fn(Event) -> Event + 'a { Tag::Image {
move |event| match event { dest_url,
Event::Start(start) => match start { link_type,
Tag::Image { title,
dest_url, id,
link_type, } => {
title, let rel = dir.join(dest_url.as_ref());
id, let img = sack.get_image(&rel);
} => { let hashed = img.map(|path| path.as_str().to_owned().into());
let rel = dir.join(dest_url.as_ref()); Event::Start(Tag::Image {
let img = sack.get_image(&rel); link_type,
let hashed = img.map(|path| path.as_str().to_owned().into()); dest_url: hashed.unwrap_or(dest_url),
Event::Start(Tag::Image { title,
link_type, id,
dest_url: hashed.unwrap_or(dest_url), })
title, }
id, _ => Event::Start(start),
}) },
} _ => event,
_ => Event::Start(start), }
},
_ => event,
}
} }

View file

@ -1,32 +1,43 @@
.flox-playground { .flox-playground {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
grid-template-rows: max(24rem, 0.5vh); grid-template-rows: max(24rem, 0.5vh);
gap: 1em; gap: 1em;
margin-block: 0.5em; margin-block: 0.5em;
padding: 1em;
.editor, #output {
height: calc(100% - 4em);
overflow-y: auto;
border: 1px dashed black;
border-radius: 0.5em;
background-color: white;
}
.editor {
position: relative;
#run {
position: absolute;
right: 0.5em;
bottom: 0.5em;
padding: 0.25em 0.5em;
}
}
#output {
padding: 1em; padding: 1em;
}
.editor,
#output {
height: calc(100% - 4em);
overflow-y: auto;
border: 1px dashed black;
border-radius: 0.5em;
background-color: white;
}
.editor {
position: relative;
#run {
position: absolute;
right: 0.5em;
bottom: 0.5em;
padding: 0.25em 0.5em;
}
}
#output {
padding: 1em;
}
}
.flox-eval {
border-radius: 0.5em;
border: 1px solid black;
overflow: auto;
> .output {
padding: 0.25em 0.5em;
border-top: 1px solid black;
}
} }