From c3d634a24ef0c966f90c4dc5d90fe7fec213db4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20M=C3=A5rdbrink?= Date: Sun, 30 Nov 2025 15:48:45 +0100 Subject: [PATCH] Add demo --- .gitignore | 1 + README.md | 4 +- .../gleam_community@colour.cache | Bin 57501 -> 0 bytes .../gleam_community@colour.cache_inline | Bin 8 -> 0 bytes .../gleam_community@colour.cache_meta | Bin 5305 -> 0 bytes ...gleam_community@colour@accessibility.cache | Bin 7219 -> 0 bytes ...ommunity@colour@accessibility.cache_inline | Bin 8 -> 0 bytes ..._community@colour@accessibility.cache_meta | Bin 876 -> 0 bytes .../gleam_community_colour/gleam.mjs | 1 - .../gleam_community/colour.mjs | 1444 -------- .../gleam_community/colour/accessibility.mjs | 146 - .../gleam_community@colour.erl | 1199 ------ .../gleam_community@colour@accessibility.erl | 203 -- .../_gleam_artefacts/gleam@json.cache | Bin 18027 -> 0 bytes .../_gleam_artefacts/gleam@json.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@json.cache_meta | Bin 1554 -> 0 bytes build/dev/javascript/gleam_json/gleam.mjs | 1 - .../dev/javascript/gleam_json/gleam/json.mjs | 325 -- .../dev/javascript/gleam_json/gleam@json.erl | 304 -- .../javascript/gleam_json/gleam_json_ffi.erl | 66 - .../javascript/gleam_json/gleam_json_ffi.mjs | 201 -- .../_gleam_artefacts/gleam@bit_array.cache | Bin 14783 -> 0 bytes .../gleam@bit_array.cache_inline | Bin 8 -> 0 bytes .../gleam@bit_array.cache_meta | Bin 1253 -> 0 bytes .../_gleam_artefacts/gleam@bool.cache | Bin 8858 -> 0 bytes .../_gleam_artefacts/gleam@bool.cache_inline | Bin 1449 -> 0 bytes .../_gleam_artefacts/gleam@bool.cache_meta | Bin 1317 -> 0 bytes .../_gleam_artefacts/gleam@bytes_tree.cache | Bin 13269 -> 0 bytes .../gleam@bytes_tree.cache_inline | Bin 8 -> 0 bytes .../gleam@bytes_tree.cache_meta | Bin 903 -> 0 bytes .../_gleam_artefacts/gleam@dict.cache | Bin 24410 -> 0 bytes .../_gleam_artefacts/gleam@dict.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@dict.cache_meta | Bin 2273 -> 0 bytes .../_gleam_artefacts/gleam@dynamic.cache | Bin 7137 -> 0 bytes .../gleam@dynamic.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@dynamic.cache_meta | Bin 479 -> 0 bytes .../gleam@dynamic@decode.cache | Bin 58909 -> 0 bytes .../gleam@dynamic@decode.cache_inline | Bin 8 -> 0 bytes .../gleam@dynamic@decode.cache_meta | Bin 4482 -> 0 bytes .../_gleam_artefacts/gleam@float.cache | Bin 23692 -> 0 bytes .../_gleam_artefacts/gleam@float.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@float.cache_meta | Bin 2724 -> 0 bytes .../_gleam_artefacts/gleam@function.cache | Bin 1104 -> 0 bytes .../gleam@function.cache_inline | Bin 8 -> 0 bytes .../gleam@function.cache_meta | Bin 113 -> 0 bytes .../_gleam_artefacts/gleam@int.cache | Bin 29916 -> 0 bytes .../_gleam_artefacts/gleam@int.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@int.cache_meta | Bin 3419 -> 0 bytes .../_gleam_artefacts/gleam@io.cache | Bin 2697 -> 0 bytes .../_gleam_artefacts/gleam@io.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@io.cache_meta | Bin 289 -> 0 bytes .../_gleam_artefacts/gleam@list.cache | Bin 88736 -> 0 bytes .../_gleam_artefacts/gleam@list.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@list.cache_meta | Bin 9862 -> 0 bytes .../_gleam_artefacts/gleam@option.cache | Bin 13699 -> 0 bytes .../gleam@option.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@option.cache_meta | Bin 1485 -> 0 bytes .../_gleam_artefacts/gleam@order.cache | Bin 5915 -> 0 bytes .../_gleam_artefacts/gleam@order.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@order.cache_meta | Bin 677 -> 0 bytes .../_gleam_artefacts/gleam@pair.cache | Bin 2776 -> 0 bytes .../_gleam_artefacts/gleam@pair.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@pair.cache_meta | Bin 403 -> 0 bytes .../_gleam_artefacts/gleam@result.cache | Bin 15524 -> 0 bytes .../gleam@result.cache_inline | Bin 3168 -> 0 bytes .../_gleam_artefacts/gleam@result.cache_meta | Bin 1891 -> 0 bytes .../_gleam_artefacts/gleam@set.cache | Bin 16946 -> 0 bytes .../_gleam_artefacts/gleam@set.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@set.cache_meta | Bin 1761 -> 0 bytes .../_gleam_artefacts/gleam@string.cache | Bin 38365 -> 0 bytes .../gleam@string.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@string.cache_meta | Bin 4057 -> 0 bytes .../_gleam_artefacts/gleam@string_tree.cache | Bin 14554 -> 0 bytes .../gleam@string_tree.cache_inline | Bin 8 -> 0 bytes .../gleam@string_tree.cache_meta | Bin 911 -> 0 bytes .../_gleam_artefacts/gleam@uri.cache | Bin 32735 -> 0 bytes .../_gleam_artefacts/gleam@uri.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleam@uri.cache_meta | Bin 3273 -> 0 bytes build/dev/javascript/gleam_stdlib/dict.mjs | 993 ----- build/dev/javascript/gleam_stdlib/gleam.mjs | 1 - .../gleam_stdlib/gleam/bit_array.mjs | 285 -- .../javascript/gleam_stdlib/gleam/bool.mjs | 313 -- .../gleam_stdlib/gleam/bytes_tree.mjs | 225 -- .../javascript/gleam_stdlib/gleam/dict.mjs | 534 --- .../javascript/gleam_stdlib/gleam/dynamic.mjs | 35 - .../gleam_stdlib/gleam/dynamic/decode.mjs | 947 ----- .../javascript/gleam_stdlib/gleam/float.mjs | 553 --- .../gleam_stdlib/gleam/function.mjs | 17 - .../dev/javascript/gleam_stdlib/gleam/int.mjs | 816 ----- .../dev/javascript/gleam_stdlib/gleam/io.mjs | 8 - .../javascript/gleam_stdlib/gleam/list.mjs | 3209 ----------------- .../javascript/gleam_stdlib/gleam/option.mjs | 419 --- .../javascript/gleam_stdlib/gleam/order.mjs | 178 - .../javascript/gleam_stdlib/gleam/pair.mjs | 102 - .../javascript/gleam_stdlib/gleam/result.mjs | 494 --- .../dev/javascript/gleam_stdlib/gleam/set.mjs | 412 --- .../javascript/gleam_stdlib/gleam/string.mjs | 723 ---- .../gleam_stdlib/gleam/string_tree.mjs | 133 - .../dev/javascript/gleam_stdlib/gleam/uri.mjs | 1147 ------ .../gleam_stdlib/gleam@bit_array.erl | 347 -- .../javascript/gleam_stdlib/gleam@bool.erl | 352 -- .../gleam_stdlib/gleam@bytes_tree.erl | 211 -- .../javascript/gleam_stdlib/gleam@dict.erl | 561 --- .../javascript/gleam_stdlib/gleam@dynamic.erl | 106 - .../gleam_stdlib/gleam@dynamic@decode.erl | 1088 ------ .../javascript/gleam_stdlib/gleam@float.erl | 744 ---- .../gleam_stdlib/gleam@function.erl | 30 - .../dev/javascript/gleam_stdlib/gleam@int.erl | 986 ----- .../dev/javascript/gleam_stdlib/gleam@io.erl | 80 - .../javascript/gleam_stdlib/gleam@list.erl | 2873 --------------- .../javascript/gleam_stdlib/gleam@option.erl | 413 --- .../javascript/gleam_stdlib/gleam@order.erl | 200 - .../javascript/gleam_stdlib/gleam@pair.erl | 110 - .../javascript/gleam_stdlib/gleam@result.erl | 550 --- .../dev/javascript/gleam_stdlib/gleam@set.erl | 429 --- .../javascript/gleam_stdlib/gleam@string.erl | 1012 ------ .../gleam_stdlib/gleam@string_tree.erl | 207 -- .../dev/javascript/gleam_stdlib/gleam@uri.erl | 1044 ------ .../javascript/gleam_stdlib/gleam_stdlib.erl | 534 --- .../javascript/gleam_stdlib/gleam_stdlib.mjs | 1048 ------ .../gleam@time@calendar.cache | Bin 21304 -> 0 bytes .../gleam@time@calendar.cache_inline | Bin 8 -> 0 bytes .../gleam@time@calendar.cache_meta | Bin 1524 -> 0 bytes .../gleam@time@duration.cache | Bin 15819 -> 0 bytes .../gleam@time@duration.cache_inline | Bin 8 -> 0 bytes .../gleam@time@duration.cache_meta | Bin 1347 -> 0 bytes .../gleam@time@timestamp.cache | Bin 46587 -> 0 bytes .../gleam@time@timestamp.cache_inline | Bin 8 -> 0 bytes .../gleam@time@timestamp.cache_meta | Bin 3911 -> 0 bytes build/dev/javascript/gleam_time/gleam.mjs | 1 - .../gleam_time/gleam/time/calendar.mjs | 391 -- .../gleam_time/gleam/time/duration.mjs | 382 -- .../gleam_time/gleam/time/timestamp.mjs | 1215 ------- .../gleam_time/gleam@time@calendar.erl | 468 --- .../gleam_time/gleam@time@duration.erl | 381 -- .../gleam_time/gleam@time@timestamp.erl | 1188 ------ .../javascript/gleam_time/gleam_time_ffi.erl | 12 - .../javascript/gleam_time/gleam_time_ffi.mjs | 11 - build/dev/javascript/gleam_version | 1 - .../gleeunit/_gleam_artefacts/gleeunit.cache | Bin 8472 -> 0 bytes .../_gleam_artefacts/gleeunit.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/gleeunit.cache_meta | Bin 479 -> 0 bytes .../gleeunit@internal@gleam_panic.cache | Bin 14778 -> 0 bytes ...gleeunit@internal@gleam_panic.cache_inline | Bin 8 -> 0 bytes .../gleeunit@internal@gleam_panic.cache_meta | Bin 278 -> 0 bytes .../gleeunit@internal@reporting.cache | Bin 14281 -> 0 bytes .../gleeunit@internal@reporting.cache_inline | Bin 8 -> 0 bytes .../gleeunit@internal@reporting.cache_meta | Bin 1277 -> 0 bytes .../_gleam_artefacts/gleeunit@should.cache | Bin 3853 -> 0 bytes .../gleeunit@should.cache_inline | Bin 8 -> 0 bytes .../gleeunit@should.cache_meta | Bin 397 -> 0 bytes build/dev/javascript/gleeunit/gleam.mjs | 1 - build/dev/javascript/gleeunit/gleeunit.erl | 89 - build/dev/javascript/gleeunit/gleeunit.mjs | 62 - .../gleeunit/internal/gleam_panic.mjs | 180 - .../internal/gleeunit_gleam_panic_ffi.erl | 49 - .../internal/gleeunit_gleam_panic_ffi.mjs | 91 - .../gleeunit/gleeunit/internal/reporting.mjs | 256 -- .../javascript/gleeunit/gleeunit/should.mjs | 135 - .../gleeunit@internal@gleam_panic.erl | 56 - .../gleeunit/gleeunit@internal@reporting.erl | 343 -- .../javascript/gleeunit/gleeunit@should.erl | 153 - .../dev/javascript/gleeunit/gleeunit_ffi.erl | 21 - .../dev/javascript/gleeunit/gleeunit_ffi.mjs | 100 - .../javascript/gleeunit/gleeunit_progress.erl | 72 - .../paint/_gleam_artefacts/paint.cache | Bin 18173 -> 0 bytes .../paint/_gleam_artefacts/paint.cache_inline | Bin 8 -> 0 bytes .../paint/_gleam_artefacts/paint.cache_meta | Bin 969 -> 0 bytes .../paint/_gleam_artefacts/paint@canvas.cache | Bin 20428 -> 0 bytes .../paint@canvas.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/paint@canvas.cache_meta | Bin 2142 -> 0 bytes .../paint/_gleam_artefacts/paint@encode.cache | Bin 10664 -> 0 bytes .../paint@encode.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/paint@encode.cache_meta | Bin 1250 -> 0 bytes .../paint/_gleam_artefacts/paint@event.cache | Bin 9101 -> 0 bytes .../_gleam_artefacts/paint@event.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/paint@event.cache_meta | Bin 253 -> 0 bytes .../paint@internal@impl_canvas.cache | Bin 16937 -> 0 bytes .../paint@internal@impl_canvas.cache_inline | Bin 8 -> 0 bytes .../paint@internal@impl_canvas.cache_meta | Bin 525 -> 0 bytes .../paint@internal@types.cache | Bin 14729 -> 0 bytes .../paint@internal@types.cache_inline | Bin 8 -> 0 bytes .../paint@internal@types.cache_meta | Bin 283 -> 0 bytes build/dev/javascript/paint/gleam.mjs | 1 - .../javascript/paint/impl_canvas_bindings.mjs | 271 -- build/dev/javascript/paint/numbers_ffi.mjs | 3 - build/dev/javascript/paint/paint.mjs | 246 -- build/dev/javascript/paint/paint/canvas.mjs | 655 ---- build/dev/javascript/paint/paint/encode.mjs | 506 --- build/dev/javascript/paint/paint/event.mjs | 163 - .../paint/paint/internal/impl_canvas.mjs | 65 - .../javascript/paint/paint/internal/types.mjs | 217 -- build/dev/javascript/prelude.mjs | 1575 -------- .../stellar_prune/_gleam_artefacts/game.cache | Bin 14636 -> 0 bytes .../_gleam_artefacts/game.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/game.cache_meta | Bin 1262 -> 0 bytes .../_gleam_artefacts/game.cache_warnings | Bin 8 -> 0 bytes .../stellar_prune/_gleam_artefacts/hud.cache | Bin 9498 -> 0 bytes .../_gleam_artefacts/hud.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/hud.cache_meta | Bin 491 -> 0 bytes .../_gleam_artefacts/hud.cache_warnings | Bin 8 -> 0 bytes .../_gleam_artefacts/math@math.cache | Bin 2990 -> 0 bytes .../_gleam_artefacts/math@math.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/math@math.cache_meta | Bin 165 -> 0 bytes .../_gleam_artefacts/math@math.cache_warnings | Bin 8 -> 0 bytes .../_gleam_artefacts/physics.cache | Bin 5550 -> 0 bytes .../_gleam_artefacts/physics.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/physics.cache_meta | Bin 149 -> 0 bytes .../_gleam_artefacts/physics.cache_warnings | Bin 8 -> 0 bytes .../_gleam_artefacts/rendering.cache | Bin 4103 -> 0 bytes .../_gleam_artefacts/rendering.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/rendering.cache_meta | Bin 643 -> 0 bytes .../_gleam_artefacts/rendering.cache_warnings | Bin 8 -> 0 bytes .../_gleam_artefacts/target.cache | Bin 10406 -> 0 bytes .../_gleam_artefacts/target.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/target.cache_meta | Bin 679 -> 0 bytes .../_gleam_artefacts/target.cache_warnings | Bin 8 -> 0 bytes .../_gleam_artefacts/types.cache | Bin 5139 -> 0 bytes .../_gleam_artefacts/types.cache_inline | Bin 8 -> 0 bytes .../_gleam_artefacts/types.cache_meta | Bin 193 -> 0 bytes .../_gleam_artefacts/types.cache_warnings | Bin 8 -> 0 bytes .../javascript/stellar_prune/browser_ffi.mjs | 40 - build/dev/javascript/stellar_prune/game.mjs | 325 -- build/dev/javascript/stellar_prune/gleam.mjs | 1 - build/dev/javascript/stellar_prune/hud.mjs | 153 - .../javascript/stellar_prune/math/math.mjs | 3 - .../stellar_prune/math/math_ffi.mjs | 35 - .../dev/javascript/stellar_prune/physics.mjs | 63 - .../javascript/stellar_prune/rendering.mjs | 155 - build/dev/javascript/stellar_prune/target.mjs | 194 - build/dev/javascript/stellar_prune/types.mjs | 66 - build/gleam-dev-erlang.lock | 0 build/gleam-dev-javascript.lock | 0 build/gleam-lsp-erlang.lock | 0 build/gleam-lsp-javascript.lock | 0 build/gleam-prod-erlang.lock | 0 build/gleam-prod-javascript.lock | 0 build/packages/gleam.lock | 0 build/packages/gleam_community_colour/LICENCE | 190 - .../packages/gleam_community_colour/README.md | 36 - .../gleam_community_colour/gleam.toml | 13 - .../include/gleam_community@colour_Hsla.hrl | 1 - .../include/gleam_community@colour_Rgba.hrl | 1 - .../src/gleam_community/colour.gleam | 1214 ------- .../colour/accessibility.gleam | 173 - .../src/gleam_community@colour.erl | 1199 ------ .../gleam_community@colour@accessibility.erl | 203 -- .../src/gleam_community_colour.app.src | 10 - build/packages/gleam_json/LICENCE | 191 - build/packages/gleam_json/README.md | 47 - build/packages/gleam_json/gleam.toml | 18 - .../packages/gleam_json/src/gleam/json.gleam | 316 -- build/packages/gleam_json/src/gleam@json.erl | 304 -- .../gleam_json/src/gleam_json.app.src | 9 - .../gleam_json/src/gleam_json_ffi.erl | 66 - .../gleam_json/src/gleam_json_ffi.mjs | 201 -- build/packages/gleam_stdlib/LICENCE | 191 - build/packages/gleam_stdlib/README.md | 34 - build/packages/gleam_stdlib/gleam.toml | 14 - .../gleam@dynamic@decode_DecodeError.hrl | 5 - .../include/gleam@dynamic@decode_Decoder.hrl | 4 - .../gleam_stdlib/include/gleam@set_Set.hrl | 1 - .../gleam_stdlib/include/gleam@uri_Uri.hrl | 9 - build/packages/gleam_stdlib/src/dict.mjs | 993 ----- .../gleam_stdlib/src/gleam/bit_array.gleam | 280 -- .../gleam_stdlib/src/gleam/bool.gleam | 316 -- .../gleam_stdlib/src/gleam/bytes_tree.gleam | 190 - .../gleam_stdlib/src/gleam/dict.gleam | 548 --- .../gleam_stdlib/src/gleam/dynamic.gleam | 100 - .../src/gleam/dynamic/decode.gleam | 1061 ------ .../gleam_stdlib/src/gleam/float.gleam | 661 ---- .../gleam_stdlib/src/gleam/function.gleam | 15 - .../packages/gleam_stdlib/src/gleam/int.gleam | 828 ----- .../packages/gleam_stdlib/src/gleam/io.gleam | 59 - .../gleam_stdlib/src/gleam/list.gleam | 2426 ------------- .../gleam_stdlib/src/gleam/option.gleam | 358 -- .../gleam_stdlib/src/gleam/order.gleam | 156 - .../gleam_stdlib/src/gleam/pair.gleam | 85 - .../gleam_stdlib/src/gleam/result.gleam | 453 --- .../packages/gleam_stdlib/src/gleam/set.gleam | 407 --- .../gleam_stdlib/src/gleam/string.gleam | 900 ----- .../gleam_stdlib/src/gleam/string_tree.gleam | 208 -- .../packages/gleam_stdlib/src/gleam/uri.gleam | 770 ---- .../gleam_stdlib/src/gleam@bit_array.erl | 347 -- .../packages/gleam_stdlib/src/gleam@bool.erl | 352 -- .../gleam_stdlib/src/gleam@bytes_tree.erl | 211 -- .../packages/gleam_stdlib/src/gleam@dict.erl | 561 --- .../gleam_stdlib/src/gleam@dynamic.erl | 106 - .../gleam_stdlib/src/gleam@dynamic@decode.erl | 1088 ------ .../packages/gleam_stdlib/src/gleam@float.erl | 744 ---- .../gleam_stdlib/src/gleam@function.erl | 30 - build/packages/gleam_stdlib/src/gleam@int.erl | 986 ----- build/packages/gleam_stdlib/src/gleam@io.erl | 80 - .../packages/gleam_stdlib/src/gleam@list.erl | 2873 --------------- .../gleam_stdlib/src/gleam@option.erl | 413 --- .../packages/gleam_stdlib/src/gleam@order.erl | 200 - .../packages/gleam_stdlib/src/gleam@pair.erl | 110 - .../gleam_stdlib/src/gleam@result.erl | 550 --- build/packages/gleam_stdlib/src/gleam@set.erl | 429 --- .../gleam_stdlib/src/gleam@string.erl | 1012 ------ .../gleam_stdlib/src/gleam@string_tree.erl | 207 -- build/packages/gleam_stdlib/src/gleam@uri.erl | 1044 ------ .../gleam_stdlib/src/gleam_stdlib.app.src | 31 - .../gleam_stdlib/src/gleam_stdlib.erl | 534 --- .../gleam_stdlib/src/gleam_stdlib.mjs | 1048 ------ build/packages/gleam_time/README.md | 101 - build/packages/gleam_time/gleam.toml | 19 - .../include/gleam@time@calendar_Date.hrl | 5 - .../include/gleam@time@calendar_TimeOfDay.hrl | 6 - .../include/gleam@time@duration_Duration.hrl | 1 - .../gleam@time@timestamp_Timestamp.hrl | 1 - .../gleam_time/src/gleam/time/calendar.gleam | 346 -- .../gleam_time/src/gleam/time/duration.gleam | 297 -- .../gleam_time/src/gleam/time/timestamp.gleam | 899 ----- .../gleam_time/src/gleam@time@calendar.erl | 468 --- .../gleam_time/src/gleam@time@duration.erl | 381 -- .../gleam_time/src/gleam@time@timestamp.erl | 1188 ------ .../gleam_time/src/gleam_time.app.src | 12 - .../gleam_time/src/gleam_time_ffi.erl | 12 - .../gleam_time/src/gleam_time_ffi.mjs | 11 - build/packages/gleeunit/LICENCE | 191 - build/packages/gleeunit/README.md | 44 - build/packages/gleeunit/gleam.toml | 16 - .../gleeunit@internal@gleam_panic_Assert.hrl | 6 - ...nternal@gleam_panic_AssertedExpression.hrl | 5 - ...it@internal@gleam_panic_BinaryOperator.hrl | 5 - ...eeunit@internal@gleam_panic_Expression.hrl | 1 - ...unit@internal@gleam_panic_FunctionCall.hrl | 3 - ...eeunit@internal@gleam_panic_GleamPanic.hrl | 8 - ...leeunit@internal@gleam_panic_LetAssert.hrl | 7 - .../gleeunit@internal@gleam_panic_Literal.hrl | 1 - ...t@internal@gleam_panic_OtherExpression.hrl | 3 - .../gleeunit@internal@reporting_State.hrl | 1 - build/packages/gleeunit/src/gleeunit.app.src | 16 - build/packages/gleeunit/src/gleeunit.erl | 89 - build/packages/gleeunit/src/gleeunit.gleam | 86 - .../src/gleeunit/internal/gleam_panic.gleam | 49 - .../internal/gleeunit_gleam_panic_ffi.erl | 49 - .../internal/gleeunit_gleam_panic_ffi.mjs | 91 - .../src/gleeunit/internal/reporting.gleam | 240 -- .../gleeunit/src/gleeunit/should.gleam | 72 - .../src/gleeunit@internal@gleam_panic.erl | 56 - .../src/gleeunit@internal@reporting.erl | 343 -- .../packages/gleeunit/src/gleeunit@should.erl | 153 - build/packages/gleeunit/src/gleeunit_ffi.erl | 21 - build/packages/gleeunit/src/gleeunit_ffi.mjs | 100 - .../gleeunit/src/gleeunit_progress.erl | 72 - build/packages/packages.toml | 7 - build/packages/paint/LICENSE.txt | 21 - build/packages/paint/README.md | 34 - build/packages/paint/gleam.toml | 23 - .../paint/src/impl_canvas_bindings.mjs | 271 -- build/packages/paint/src/numbers_ffi.mjs | 3 - build/packages/paint/src/paint.gleam | 201 -- build/packages/paint/src/paint/canvas.gleam | 461 --- build/packages/paint/src/paint/encode.gleam | 260 -- build/packages/paint/src/paint/event.gleam | 50 - .../src/paint/internal/impl_canvas.gleam | 118 - .../paint/src/paint/internal/types.gleam | 48 - demo.gif | Bin 0 -> 359063 bytes 360 files changed, 4 insertions(+), 73947 deletions(-) create mode 100644 .gitignore delete mode 100644 build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache delete mode 100644 build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_inline delete mode 100644 build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta delete mode 100644 build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache delete mode 100644 build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_inline delete mode 100644 build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta delete mode 100644 build/dev/javascript/gleam_community_colour/gleam.mjs delete mode 100644 build/dev/javascript/gleam_community_colour/gleam_community/colour.mjs delete mode 100644 build/dev/javascript/gleam_community_colour/gleam_community/colour/accessibility.mjs delete mode 100644 build/dev/javascript/gleam_community_colour/gleam_community@colour.erl delete mode 100644 build/dev/javascript/gleam_community_colour/gleam_community@colour@accessibility.erl delete mode 100644 build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache delete mode 100644 build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_inline delete mode 100644 build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_meta delete mode 100644 build/dev/javascript/gleam_json/gleam.mjs delete mode 100644 build/dev/javascript/gleam_json/gleam/json.mjs delete mode 100644 build/dev/javascript/gleam_json/gleam@json.erl delete mode 100644 build/dev/javascript/gleam_json/gleam_json_ffi.erl delete mode 100644 build/dev/javascript/gleam_json/gleam_json_ffi.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_inline delete mode 100644 build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta delete mode 100644 build/dev/javascript/gleam_stdlib/dict.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/bool.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/dict.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/float.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/function.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/int.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/io.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/list.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/option.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/order.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/pair.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/result.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/set.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/string.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam/uri.mjs delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@bit_array.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@bool.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@dict.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@dynamic.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@float.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@function.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@int.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@io.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@list.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@option.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@order.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@pair.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@result.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@set.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@string.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@string_tree.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam@uri.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam_stdlib.erl delete mode 100644 build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache_inline delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache_meta delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@duration.cache delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@duration.cache_inline delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@duration.cache_meta delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@timestamp.cache delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@timestamp.cache_inline delete mode 100644 build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@timestamp.cache_meta delete mode 100644 build/dev/javascript/gleam_time/gleam.mjs delete mode 100644 build/dev/javascript/gleam_time/gleam/time/calendar.mjs delete mode 100644 build/dev/javascript/gleam_time/gleam/time/duration.mjs delete mode 100644 build/dev/javascript/gleam_time/gleam/time/timestamp.mjs delete mode 100644 build/dev/javascript/gleam_time/gleam@time@calendar.erl delete mode 100644 build/dev/javascript/gleam_time/gleam@time@duration.erl delete mode 100644 build/dev/javascript/gleam_time/gleam@time@timestamp.erl delete mode 100644 build/dev/javascript/gleam_time/gleam_time_ffi.erl delete mode 100644 build/dev/javascript/gleam_time/gleam_time_ffi.mjs delete mode 100644 build/dev/javascript/gleam_version delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_inline delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_meta delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_inline delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_inline delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache_inline delete mode 100644 build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta delete mode 100644 build/dev/javascript/gleeunit/gleam.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit.erl delete mode 100644 build/dev/javascript/gleeunit/gleeunit.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl delete mode 100644 build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit/internal/reporting.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit/should.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit@internal@gleam_panic.erl delete mode 100644 build/dev/javascript/gleeunit/gleeunit@internal@reporting.erl delete mode 100644 build/dev/javascript/gleeunit/gleeunit@should.erl delete mode 100644 build/dev/javascript/gleeunit/gleeunit_ffi.erl delete mode 100644 build/dev/javascript/gleeunit/gleeunit_ffi.mjs delete mode 100644 build/dev/javascript/gleeunit/gleeunit_progress.erl delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint.cache delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint.cache_inline delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint.cache_meta delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@canvas.cache delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@canvas.cache_inline delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@canvas.cache_meta delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache_inline delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache_meta delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@event.cache delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@event.cache_inline delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@event.cache_meta delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache_inline delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache_meta delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache_inline delete mode 100644 build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache_meta delete mode 100644 build/dev/javascript/paint/gleam.mjs delete mode 100644 build/dev/javascript/paint/impl_canvas_bindings.mjs delete mode 100644 build/dev/javascript/paint/numbers_ffi.mjs delete mode 100644 build/dev/javascript/paint/paint.mjs delete mode 100644 build/dev/javascript/paint/paint/canvas.mjs delete mode 100644 build/dev/javascript/paint/paint/encode.mjs delete mode 100644 build/dev/javascript/paint/paint/event.mjs delete mode 100644 build/dev/javascript/paint/paint/internal/impl_canvas.mjs delete mode 100644 build/dev/javascript/paint/paint/internal/types.mjs delete mode 100644 build/dev/javascript/prelude.mjs delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/math@math.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/math@math.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/math@math.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/math@math.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/physics.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/physics.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/physics.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/physics.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/target.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/target.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/target.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/target.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_inline delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_meta delete mode 100644 build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_warnings delete mode 100644 build/dev/javascript/stellar_prune/browser_ffi.mjs delete mode 100644 build/dev/javascript/stellar_prune/game.mjs delete mode 100644 build/dev/javascript/stellar_prune/gleam.mjs delete mode 100644 build/dev/javascript/stellar_prune/hud.mjs delete mode 100644 build/dev/javascript/stellar_prune/math/math.mjs delete mode 100644 build/dev/javascript/stellar_prune/math/math_ffi.mjs delete mode 100644 build/dev/javascript/stellar_prune/physics.mjs delete mode 100644 build/dev/javascript/stellar_prune/rendering.mjs delete mode 100644 build/dev/javascript/stellar_prune/target.mjs delete mode 100644 build/dev/javascript/stellar_prune/types.mjs delete mode 100644 build/gleam-dev-erlang.lock delete mode 100644 build/gleam-dev-javascript.lock delete mode 100644 build/gleam-lsp-erlang.lock delete mode 100644 build/gleam-lsp-javascript.lock delete mode 100644 build/gleam-prod-erlang.lock delete mode 100644 build/gleam-prod-javascript.lock delete mode 100644 build/packages/gleam.lock delete mode 100644 build/packages/gleam_community_colour/LICENCE delete mode 100644 build/packages/gleam_community_colour/README.md delete mode 100644 build/packages/gleam_community_colour/gleam.toml delete mode 100644 build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl delete mode 100644 build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl delete mode 100644 build/packages/gleam_community_colour/src/gleam_community/colour.gleam delete mode 100644 build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam delete mode 100644 build/packages/gleam_community_colour/src/gleam_community@colour.erl delete mode 100644 build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl delete mode 100644 build/packages/gleam_community_colour/src/gleam_community_colour.app.src delete mode 100644 build/packages/gleam_json/LICENCE delete mode 100644 build/packages/gleam_json/README.md delete mode 100644 build/packages/gleam_json/gleam.toml delete mode 100644 build/packages/gleam_json/src/gleam/json.gleam delete mode 100644 build/packages/gleam_json/src/gleam@json.erl delete mode 100644 build/packages/gleam_json/src/gleam_json.app.src delete mode 100644 build/packages/gleam_json/src/gleam_json_ffi.erl delete mode 100644 build/packages/gleam_json/src/gleam_json_ffi.mjs delete mode 100644 build/packages/gleam_stdlib/LICENCE delete mode 100644 build/packages/gleam_stdlib/README.md delete mode 100644 build/packages/gleam_stdlib/gleam.toml delete mode 100644 build/packages/gleam_stdlib/include/gleam@dynamic@decode_DecodeError.hrl delete mode 100644 build/packages/gleam_stdlib/include/gleam@dynamic@decode_Decoder.hrl delete mode 100644 build/packages/gleam_stdlib/include/gleam@set_Set.hrl delete mode 100644 build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl delete mode 100644 build/packages/gleam_stdlib/src/dict.mjs delete mode 100644 build/packages/gleam_stdlib/src/gleam/bit_array.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/bool.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/bytes_tree.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/dict.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/dynamic.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/dynamic/decode.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/float.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/function.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/int.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/io.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/list.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/option.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/order.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/pair.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/result.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/set.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/string.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/string_tree.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam/uri.gleam delete mode 100644 build/packages/gleam_stdlib/src/gleam@bit_array.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@bool.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@bytes_tree.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@dict.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@dynamic.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@dynamic@decode.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@float.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@function.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@int.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@io.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@list.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@option.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@order.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@pair.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@result.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@set.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@string.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@string_tree.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam@uri.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam_stdlib.app.src delete mode 100644 build/packages/gleam_stdlib/src/gleam_stdlib.erl delete mode 100644 build/packages/gleam_stdlib/src/gleam_stdlib.mjs delete mode 100644 build/packages/gleam_time/README.md delete mode 100644 build/packages/gleam_time/gleam.toml delete mode 100644 build/packages/gleam_time/include/gleam@time@calendar_Date.hrl delete mode 100644 build/packages/gleam_time/include/gleam@time@calendar_TimeOfDay.hrl delete mode 100644 build/packages/gleam_time/include/gleam@time@duration_Duration.hrl delete mode 100644 build/packages/gleam_time/include/gleam@time@timestamp_Timestamp.hrl delete mode 100644 build/packages/gleam_time/src/gleam/time/calendar.gleam delete mode 100644 build/packages/gleam_time/src/gleam/time/duration.gleam delete mode 100644 build/packages/gleam_time/src/gleam/time/timestamp.gleam delete mode 100644 build/packages/gleam_time/src/gleam@time@calendar.erl delete mode 100644 build/packages/gleam_time/src/gleam@time@duration.erl delete mode 100644 build/packages/gleam_time/src/gleam@time@timestamp.erl delete mode 100644 build/packages/gleam_time/src/gleam_time.app.src delete mode 100644 build/packages/gleam_time/src/gleam_time_ffi.erl delete mode 100644 build/packages/gleam_time/src/gleam_time_ffi.mjs delete mode 100644 build/packages/gleeunit/LICENCE delete mode 100644 build/packages/gleeunit/README.md delete mode 100644 build/packages/gleeunit/gleam.toml delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Assert.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_AssertedExpression.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_BinaryOperator.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_FunctionCall.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_GleamPanic.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_LetAssert.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@gleam_panic_OtherExpression.hrl delete mode 100644 build/packages/gleeunit/include/gleeunit@internal@reporting_State.hrl delete mode 100644 build/packages/gleeunit/src/gleeunit.app.src delete mode 100644 build/packages/gleeunit/src/gleeunit.erl delete mode 100644 build/packages/gleeunit/src/gleeunit.gleam delete mode 100644 build/packages/gleeunit/src/gleeunit/internal/gleam_panic.gleam delete mode 100644 build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.erl delete mode 100644 build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs delete mode 100644 build/packages/gleeunit/src/gleeunit/internal/reporting.gleam delete mode 100644 build/packages/gleeunit/src/gleeunit/should.gleam delete mode 100644 build/packages/gleeunit/src/gleeunit@internal@gleam_panic.erl delete mode 100644 build/packages/gleeunit/src/gleeunit@internal@reporting.erl delete mode 100644 build/packages/gleeunit/src/gleeunit@should.erl delete mode 100644 build/packages/gleeunit/src/gleeunit_ffi.erl delete mode 100644 build/packages/gleeunit/src/gleeunit_ffi.mjs delete mode 100644 build/packages/gleeunit/src/gleeunit_progress.erl delete mode 100644 build/packages/packages.toml delete mode 100644 build/packages/paint/LICENSE.txt delete mode 100644 build/packages/paint/README.md delete mode 100644 build/packages/paint/gleam.toml delete mode 100644 build/packages/paint/src/impl_canvas_bindings.mjs delete mode 100644 build/packages/paint/src/numbers_ffi.mjs delete mode 100644 build/packages/paint/src/paint.gleam delete mode 100644 build/packages/paint/src/paint/canvas.gleam delete mode 100644 build/packages/paint/src/paint/encode.gleam delete mode 100644 build/packages/paint/src/paint/event.gleam delete mode 100644 build/packages/paint/src/paint/internal/impl_canvas.gleam delete mode 100644 build/packages/paint/src/paint/internal/types.gleam create mode 100644 demo.gif diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build diff --git a/README.md b/README.md index e63a703..676d334 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -# Stellar prune +# Stellar prune A clicking game where you prune stars and diamonds from the cosmos. Built with Gleam for the gleam game jam of 2025. +![Demo](demo.gif) + ## How to Play - Click on stars and diamonds as jump up - Avoid the volatile rockets! diff --git a/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache b/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache deleted file mode 100644 index 1c43dda1f4027ad9d115aa8be94f3335d5f57a90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57501 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 G{0IQFuAxf+ diff --git a/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_inline b/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta b/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta deleted file mode 100644 index 963c8c5c31d2da6b5395770be8dcb95f6336bed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5305 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 diff --git a/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache b/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache deleted file mode 100644 index 5a927a8e56a5b0c9ea30b81dfab4050358860ee4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7219 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 Wh|!o)kWCQcXJ~&7$#`8+V^ILsWf3F* diff --git a/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_inline b/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta b/build/dev/javascript/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta deleted file mode 100644 index b367370b45434ce2f0ce1afc6f750bba0928f7c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 876 zcmbQrl99mx1&qv41~-&W&q+T1MJgw=xa1-`1H&VB1_m)? znfT=V+}zT<%#up|?!#=yWJ&%nUo#K6Fi z&%nU2fPsNwDFXuoNX=#j28Q1Z3=C?F3=DaU3=GAL3=B<-3=Ah385qtpGB8|aWMFu~ z$iVQHk%2*iiGe|uiGiVziGkq=69a=7GXp~^GXuj0W(J0L%nS^lnHd;7Sr{1VSQr?Z zSr{0uvM?|xvobK0ure?lU}azsW@BJTV`E?_Wn*BdVq;+FVq;+FXJcTPz{bGvkd1-C zgq?xGoSlIolbwMfhn;~Tmz{xOFFOMRC~QEX0P-V02Lpou2LnR_2LnSQ2LnSN2Lr=h z4hDwT91ILO2#7A^*c9b60y$G8|6o^dfSyy9YD_|C<^z{SnLpwG>~V9L$FV9U+G;KR+p5WvmA zP{z%`aG#rjL5zoiL79hvA&!TEp_7M!VHytu!$KYghNV0V3>SGA7!-IJ7<_pd82oq{ z81i`;7$)#CFl^*yVA#aV!0?Bcf#Dx71H*riJRbwYQa%QTm3#~g+xZw6uJbW4+~#9o zc)`cO@SBf;!HJ)N!GoWHA%LHOA)cRsA(@|np_8A1;S)atgQfrjgP8yWL!kfz!yEwy zhLr*g3|j;k7L&J zi7+ty7hz!F7iD135M^L+7G+@Y6=h&36=h&pDaycbSCoO_o+twYhZq9`uNVV^ych$6 gA{4WL5-$S-!#)uRgPC!H0E|`317is=L0C+T0G_^p0{{R3 diff --git a/build/dev/javascript/gleam_community_colour/gleam.mjs b/build/dev/javascript/gleam_community_colour/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/build/dev/javascript/gleam_community_colour/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/build/dev/javascript/gleam_community_colour/gleam_community/colour.mjs b/build/dev/javascript/gleam_community_colour/gleam_community/colour.mjs deleted file mode 100644 index 164bd50..0000000 --- a/build/dev/javascript/gleam_community_colour/gleam_community/colour.mjs +++ /dev/null @@ -1,1444 +0,0 @@ -import * as $json from "../../gleam_json/gleam/json.mjs"; -import * as $decode from "../../gleam_stdlib/gleam/dynamic/decode.mjs"; -import * as $float from "../../gleam_stdlib/gleam/float.mjs"; -import * as $int from "../../gleam_stdlib/gleam/int.mjs"; -import * as $list from "../../gleam_stdlib/gleam/list.mjs"; -import * as $result from "../../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../../gleam_stdlib/gleam/string.mjs"; -import { Ok, Error, toList, CustomType as $CustomType, makeError, divideFloat } from "../gleam.mjs"; - -const FILEPATH = "src/gleam_community/colour.gleam"; - -class Rgba extends $CustomType { - constructor(r, g, b, a) { - super(); - this.r = r; - this.g = g; - this.b = b; - this.a = a; - } -} - -class Hsla extends $CustomType { - constructor(h, s, l, a) { - super(); - this.h = h; - this.s = s; - this.l = l; - this.a = a; - } -} - -function valid_colour_value(c) { - let $ = (c > 1.0) || (c < 0.0); - if ($) { - return new Error(undefined); - } else { - return new Ok(c); - } -} - -function hue_to_rgb(hue, m1, m2) { - let _block; - if (hue < 0.0) { - _block = hue + 1.0; - } else if (hue > 1.0) { - _block = hue - 1.0; - } else { - _block = hue; - } - let h = _block; - let h_t_6 = h * 6.0; - let h_t_2 = h * 2.0; - let h_t_3 = h * 3.0; - if (h_t_6 < 1.0) { - return m1 + (((m2 - m1) * h) * 6.0); - } else if (h_t_2 < 1.0) { - return m2; - } else if (h_t_3 < 2.0) { - return m1 + (((m2 - m1) * ((2.0 / 3.0) - h)) * 6.0); - } else { - return m1; - } -} - -function hex_string_to_int(hex_string) { - let _block; - if (hex_string.startsWith("#")) { - let hex_number = hex_string.slice(1); - _block = hex_number; - } else if (hex_string.startsWith("0x")) { - let hex_number = hex_string.slice(2); - _block = hex_number; - } else { - _block = hex_string; - } - let hex = _block; - let _pipe = hex; - let _pipe$1 = $string.lowercase(_pipe); - let _pipe$2 = $string.to_graphemes(_pipe$1); - let _pipe$3 = $list.reverse(_pipe$2); - return $list.index_fold( - _pipe$3, - new Ok(0), - (total, char, index) => { - if (total instanceof Ok) { - let v = total[0]; - return $result.try$( - (() => { - if (char === "a") { - return new Ok(10); - } else if (char === "b") { - return new Ok(11); - } else if (char === "c") { - return new Ok(12); - } else if (char === "d") { - return new Ok(13); - } else if (char === "e") { - return new Ok(14); - } else if (char === "f") { - return new Ok(15); - } else { - return $int.parse(char); - } - })(), - (num) => { - return $result.try$( - $int.power(16, $int.to_float(index)), - (base) => { - return new Ok(v + $float.round($int.to_float(num) * base)); - }, - ); - }, - ); - } else { - return total; - } - }, - ); -} - -function hsla_to_rgba(h, s, l, a) { - let _block; - let $ = l <= 0.5; - if ($) { - _block = l * (s + 1.0); - } else { - _block = (l + s) - (l * s); - } - let m2 = _block; - let m1 = (l * 2.0) - m2; - let r = hue_to_rgb(h + (1.0 / 3.0), m1, m2); - let g = hue_to_rgb(h, m1, m2); - let b = hue_to_rgb(h - (1.0 / 3.0), m1, m2); - return [r, g, b, a]; -} - -function rgba_to_hsla(r, g, b, a) { - let min_colour = $float.min(r, $float.min(g, b)); - let max_colour = $float.max(r, $float.max(g, b)); - let _block; - let $ = true; - if (max_colour === r) { - _block = $float.divide(g - b, max_colour - min_colour); - } else if (max_colour === g) { - let _pipe = $float.divide(b - r, max_colour - min_colour); - _block = $result.try$(_pipe, (d) => { return new Ok(2.0 + d); }); - } else { - let _pipe = $float.divide(r - g, max_colour - min_colour); - _block = $result.try$(_pipe, (d) => { return new Ok(4.0 + d); }); - } - let h1 = _block; - let _block$1; - if (h1 instanceof Ok) { - let v = h1[0]; - _block$1 = new Ok(v * (1.0 / 6.0)); - } else { - _block$1 = h1; - } - let h2 = _block$1; - let _block$2; - if (h2 instanceof Ok) { - let v = h2[0]; - if (v < 0.0) { - _block$2 = v + 1.0; - } else { - let v$1 = h2[0]; - _block$2 = v$1; - } - } else { - _block$2 = 0.0; - } - let h3 = _block$2; - let l = (min_colour + max_colour) / 2.0; - let _block$3; - let $1 = true; - if (min_colour === max_colour) { - _block$3 = 0.0; - } else if (l < 0.5) { - _block$3 = divideFloat((max_colour - min_colour), (max_colour + min_colour)); - } else { - _block$3 = divideFloat( - (max_colour - min_colour), - ((2.0 - max_colour) - min_colour) - ); - } - let s = _block$3; - return [h3, s, l, a]; -} - -/** - * Returns a `Result(Colour)` created from the given 8 bit RGB values. - * - * Returns `Error(Nil)` if the supplied RGB values are greater than 255 or less than 0. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb255(255, 0, 0) - * } - * ``` - *
- * - * - */ -export function from_rgb255(red, green, blue) { - return $result.try$( - (() => { - let _pipe = red; - let _pipe$1 = $int.to_float(_pipe); - let _pipe$2 = $float.divide(_pipe$1, 255.0); - return $result.try$(_pipe$2, valid_colour_value); - })(), - (r) => { - return $result.try$( - (() => { - let _pipe = green; - let _pipe$1 = $int.to_float(_pipe); - let _pipe$2 = $float.divide(_pipe$1, 255.0); - return $result.try$(_pipe$2, valid_colour_value); - })(), - (g) => { - return $result.try$( - (() => { - let _pipe = blue; - let _pipe$1 = $int.to_float(_pipe); - let _pipe$2 = $float.divide(_pipe$1, 255.0); - return $result.try$(_pipe$2, valid_colour_value); - })(), - (b) => { return new Ok(new Rgba(r, g, b, 1.0)); }, - ); - }, - ); - }, - ); -} - -/** - * Returns `Result(Colour)` created from the given RGB values. - * - * If the supplied RGB values are greater than 1.0 or less than 0.0 returns `Error(Nil)` - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb(1.0, 0.0, 0.0) - * } - * ``` - *
- * - * - */ -export function from_rgb(red, green, blue) { - return $result.try$( - valid_colour_value(red), - (r) => { - return $result.try$( - valid_colour_value(green), - (g) => { - return $result.try$( - valid_colour_value(blue), - (b) => { return new Ok(new Rgba(r, g, b, 1.0)); }, - ); - }, - ); - }, - ); -} - -/** - * Returns `Result(Colour)` created from the given RGBA values. - * - * Returns `Error(Nil)` if the supplied RGBA values are greater than 1.0 or less than 0.0. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red_half_opacity) = from_rbga(1.0, 0.0, 0.0, 0.5) - * } - * ``` - *
- * - * - */ -export function from_rgba(red, green, blue, alpha) { - return $result.try$( - valid_colour_value(red), - (r) => { - return $result.try$( - valid_colour_value(green), - (g) => { - return $result.try$( - valid_colour_value(blue), - (b) => { - return $result.try$( - valid_colour_value(alpha), - (a) => { return new Ok(new Rgba(r, g, b, a)); }, - ); - }, - ); - }, - ); - }, - ); -} - -/** - * Returns `Result(Colour)` created from the given HSLA values. - * - * Returns `Error(Nil)`f the supplied HSLA values are greater than 1.0 or less than 0.0. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red_half_opacity) = from_hsla(0.0, 1.0, 0.5, 0.5) - * } - * ``` - *
- * - * - */ -export function from_hsla(hue, saturation, lightness, alpha) { - return $result.try$( - valid_colour_value(hue), - (h) => { - return $result.try$( - valid_colour_value(saturation), - (s) => { - return $result.try$( - valid_colour_value(lightness), - (l) => { - return $result.try$( - valid_colour_value(alpha), - (a) => { return new Ok(new Hsla(h, s, l, a)); }, - ); - }, - ); - }, - ); - }, - ); -} - -/** - * Returns `Result(Colour)` created from the given HSL values. - * - * Returns `Error(Nil)` if the supplied HSL values are greater than 1.0 or less than 0.0. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_hsla(0.0, 1.0, 0.5) - * } - * ``` - *
- * - * - */ -export function from_hsl(hue, saturation, lightness) { - return from_hsla(hue, saturation, lightness, 1.0); -} - -/** - * Returns a `Result(Colour)` created from the given hex `Int`. - * - * Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffff or less than 0x0. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb_hex(0xff0000) - * } - * ``` - *
- * - * - */ -export function from_rgb_hex(hex) { - let $ = (hex > 0xffffff) || (hex < 0); - if ($) { - return new Error(undefined); - } else { - let _block; - let _pipe = $int.bitwise_shift_right(hex, 16); - _block = $int.bitwise_and(_pipe, 0xff); - let r = _block; - let _block$1; - let _pipe$1 = $int.bitwise_shift_right(hex, 8); - _block$1 = $int.bitwise_and(_pipe$1, 0xff); - let g = _block$1; - let b = $int.bitwise_and(hex, 0xff); - return from_rgb255(r, g, b); - } -} - -/** - * Returns a `Result(Colour)` created from the given RGB hex `String`. - * - * Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `"#ffffff" or less than `"#0"` - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb_hex_string("#ff0000") - * } - * ``` - *
- * - * - */ -export function from_rgb_hex_string(hex_string) { - return $result.try$( - hex_string_to_int(hex_string), - (hex_int) => { return from_rgb_hex(hex_int); }, - ); -} - -/** - * Returns a `Result(Colour)` created from the given hex `Int`. - * - * Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffffff or less than 0x0. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red_half_opacity) = from_rgba_hex(0xff00007f) - * } - * ``` - *
- * - * - */ -export function from_rgba_hex(hex) { - let $ = (hex > 0xffffffff) || (hex < 0); - if ($) { - return new Error(undefined); - } else { - let _block; - let _pipe = $int.bitwise_shift_right(hex, 24); - let _pipe$1 = $int.bitwise_and(_pipe, 0xff); - let _pipe$2 = $int.to_float(_pipe$1); - _block = $float.divide(_pipe$2, 255.0); - let $1 = _block; - let r; - if ($1 instanceof Ok) { - r = $1[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour", - 590, - "from_rgba_hex", - "Pattern match failed, no pattern matched the value.", - { - value: $1, - start: 17111, - end: 17260, - pattern_start: 17122, - pattern_end: 17127 - } - ) - } - let _block$1; - let _pipe$3 = $int.bitwise_shift_right(hex, 16); - let _pipe$4 = $int.bitwise_and(_pipe$3, 0xff); - let _pipe$5 = $int.to_float(_pipe$4); - _block$1 = $float.divide(_pipe$5, 255.0); - let $2 = _block$1; - let g; - if ($2 instanceof Ok) { - g = $2[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour", - 596, - "from_rgba_hex", - "Pattern match failed, no pattern matched the value.", - { - value: $2, - start: 17332, - end: 17481, - pattern_start: 17343, - pattern_end: 17348 - } - ) - } - let _block$2; - let _pipe$6 = $int.bitwise_shift_right(hex, 8); - let _pipe$7 = $int.bitwise_and(_pipe$6, 0xff); - let _pipe$8 = $int.to_float(_pipe$7); - _block$2 = $float.divide(_pipe$8, 255.0); - let $3 = _block$2; - let b; - if ($3 instanceof Ok) { - b = $3[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour", - 602, - "from_rgba_hex", - "Pattern match failed, no pattern matched the value.", - { - value: $3, - start: 17553, - end: 17701, - pattern_start: 17564, - pattern_end: 17569 - } - ) - } - let _block$3; - let _pipe$9 = $int.bitwise_and(hex, 0xff); - let _pipe$10 = $int.to_float(_pipe$9); - _block$3 = $float.divide(_pipe$10, 255.0); - let $4 = _block$3; - let a; - if ($4 instanceof Ok) { - a = $4[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour", - 608, - "from_rgba_hex", - "Pattern match failed, no pattern matched the value.", - { - value: $4, - start: 17773, - end: 17883, - pattern_start: 17784, - pattern_end: 17789 - } - ) - } - return from_rgba(r, g, b, a); - } -} - -/** - * Returns a `Result(Colour)` created from the given RGBA hex `String`. - * - * Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `"#ffffffff" or less than `"#0"` - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red_half_opacity) = from_rgba_hex_string("#ff00007f") - * } - * ``` - *
- * - * - */ -export function from_rgba_hex_string(hex_string) { - return $result.try$( - hex_string_to_int(hex_string), - (hex_int) => { return from_rgba_hex(hex_int); }, - ); -} - -/** - * Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s - * R, G, B, and A values respectively. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb255(255, 0, 0) - * let #(r, g, b, a) = to_rgba(red) - * } - * ``` - *
- * - * - */ -export function to_rgba(colour) { - if (colour instanceof Rgba) { - let r = colour.r; - let g = colour.g; - let b = colour.b; - let a = colour.a; - return [r, g, b, a]; - } else { - let h = colour.h; - let s = colour.s; - let l = colour.l; - let a = colour.a; - return hsla_to_rgba(h, s, l, a); - } -} - -/** - * Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s - * H, S, L, and A values respectively. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb255(255, 0, 0) - * let #(h, s, l, a) = to_hsla(red) - * } - * ``` - *
- * - * - */ -export function to_hsla(colour) { - if (colour instanceof Rgba) { - let r = colour.r; - let g = colour.g; - let b = colour.b; - let a = colour.a; - return rgba_to_hsla(r, g, b, a); - } else { - let h = colour.h; - let s = colour.s; - let l = colour.l; - let a = colour.a; - return [h, s, l, a]; - } -} - -/** - * Returns an rgba formatted CSS `String` created from the given `Colour`. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgb255(255, 0, 0) - * let css_red = to_css_rgba_string(red) - * } - * ``` - *
- * - * - */ -export function to_css_rgba_string(colour) { - let $ = to_rgba(colour); - let r; - let g; - let b; - let a; - r = $[0]; - g = $[1]; - b = $[2]; - a = $[3]; - let percent = (x) => { - let _block; - let _pipe = x; - let _pipe$1 = $float.multiply(_pipe, 10_000.0); - let _pipe$2 = $float.round(_pipe$1); - let _pipe$3 = $int.to_float(_pipe$2); - _block = $float.divide(_pipe$3, 100.0); - let $1 = _block; - let p; - if ($1 instanceof Ok) { - p = $1[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour", - 706, - "to_css_rgba_string", - "Pattern match failed, no pattern matched the value.", - { - value: $1, - start: 20510, - end: 20646, - pattern_start: 20521, - pattern_end: 20526 - } - ) - } - return p; - }; - let round_to = (x) => { - let _block; - let _pipe = x; - let _pipe$1 = $float.multiply(_pipe, 1000.0); - let _pipe$2 = $float.round(_pipe$1); - let _pipe$3 = $int.to_float(_pipe$2); - _block = $float.divide(_pipe$3, 1000.0); - let $1 = _block; - let r$1; - if ($1 instanceof Ok) { - r$1 = $1[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour", - 718, - "to_css_rgba_string", - "Pattern match failed, no pattern matched the value.", - { - value: $1, - start: 20768, - end: 20903, - pattern_start: 20779, - pattern_end: 20784 - } - ) - } - return r$1; - }; - return $string.join( - toList([ - "rgba(", - $float.to_string(percent(r)) + "%,", - $float.to_string(percent(g)) + "%,", - $float.to_string(percent(b)) + "%,", - $float.to_string(round_to(a)), - ")", - ]), - "", - ); -} - -/** - * Returns an hex `Int` created from the given `Colour`. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0) - * let red_hex_int = to_rgba_hex(red) - * } - * ``` - *
- * - * - */ -export function to_rgba_hex(colour) { - let $ = to_rgba(colour); - let r; - let g; - let b; - let a; - r = $[0]; - g = $[1]; - b = $[2]; - a = $[3]; - let _block; - let _pipe = r * 255.0; - let _pipe$1 = $float.round(_pipe); - _block = $int.bitwise_shift_left(_pipe$1, 24); - let red$1 = _block; - let _block$1; - let _pipe$2 = g * 255.0; - let _pipe$3 = $float.round(_pipe$2); - _block$1 = $int.bitwise_shift_left(_pipe$3, 16); - let green$1 = _block$1; - let _block$2; - let _pipe$4 = b * 255.0; - let _pipe$5 = $float.round(_pipe$4); - _block$2 = $int.bitwise_shift_left(_pipe$5, 8); - let blue$1 = _block$2; - let _block$3; - let _pipe$6 = a * 255.0; - _block$3 = $float.round(_pipe$6); - let alpha = _block$3; - return ((red$1 + green$1) + blue$1) + alpha; -} - -/** - * Returns an rgba hex formatted `String` created from the given `Colour`. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0) - * let red_hex = to_rgba_hex_string(red) - * } - * ``` - *
- * - * - */ -export function to_rgba_hex_string(colour) { - let _block; - let _pipe = to_rgba_hex(colour); - _block = $int.to_base16(_pipe); - let hex_string = _block; - let $ = $string.length(hex_string); - if ($ === 8) { - return hex_string; - } else { - let l = $; - return $string.repeat("0", 8 - l) + hex_string; - } -} - -/** - * Returns a rgb hex `Int` created from the given `Colour`. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgba(255, 0, 0) - * let red_hex_int = to_rgb_hex(red) - * } - * ``` - *
- * - * - */ -export function to_rgb_hex(colour) { - let $ = to_rgba(colour); - let r; - let g; - let b; - r = $[0]; - g = $[1]; - b = $[2]; - let _block; - let _pipe = r * 255.0; - let _pipe$1 = $float.round(_pipe); - _block = $int.bitwise_shift_left(_pipe$1, 16); - let red$1 = _block; - let _block$1; - let _pipe$2 = g * 255.0; - let _pipe$3 = $float.round(_pipe$2); - _block$1 = $int.bitwise_shift_left(_pipe$3, 8); - let green$1 = _block$1; - let _block$2; - let _pipe$4 = b * 255.0; - _block$2 = $float.round(_pipe$4); - let blue$1 = _block$2; - return (red$1 + green$1) + blue$1; -} - -/** - * Returns an rgb hex formatted `String` created from the given `Colour`. - * - *
- * Example: - * - * ```gleam - * fn example() { - * assert Ok(red) = from_rgba(255, 0, 0) - * let red_hex = to_rgb_hex_string(red) - * } - * ``` - *
- * - * - */ -export function to_rgb_hex_string(colour) { - let _block; - let _pipe = to_rgb_hex(colour); - _block = $int.to_base16(_pipe); - let hex_string = _block; - let $ = $string.length(hex_string); - if ($ === 6) { - return hex_string; - } else { - let l = $; - return $string.repeat("0", 6 - l) + hex_string; - } -} - -function encode_rgba(r, g, b, a) { - return $json.object( - toList([ - ["r", $json.float(r)], - ["g", $json.float(g)], - ["b", $json.float(b)], - ["a", $json.float(a)], - ]), - ); -} - -function encode_hsla(h, s, l, a) { - return $json.object( - toList([ - ["h", $json.float(h)], - ["s", $json.float(s)], - ["l", $json.float(l)], - ["a", $json.float(a)], - ]), - ); -} - -/** - * Encodes a `Colour` value as a Gleam [`Json`](https://hexdocs.pm/gleam_json/gleam/json.html#Json) - * value. You'll need this if you want to send a `Colour` value over the network - * in a HTTP request or response, for example. - * - * - */ -export function encode(colour) { - if (colour instanceof Rgba) { - let r = colour.r; - let g = colour.g; - let b = colour.b; - let a = colour.a; - return encode_rgba(r, g, b, a); - } else { - let h = colour.h; - let s = colour.s; - let l = colour.l; - let a = colour.a; - return encode_hsla(h, s, l, a); - } -} - -function rgba_decoder() { - return $decode.field( - "r", - $decode.float, - (r) => { - return $decode.field( - "g", - $decode.float, - (g) => { - return $decode.field( - "b", - $decode.float, - (b) => { - return $decode.field( - "a", - $decode.float, - (a) => { return $decode.success(new Rgba(r, g, b, a)); }, - ); - }, - ); - }, - ); - }, - ); -} - -function hsla_decoder() { - return $decode.field( - "h", - $decode.float, - (h) => { - return $decode.field( - "s", - $decode.float, - (s) => { - return $decode.field( - "l", - $decode.float, - (l) => { - return $decode.field( - "a", - $decode.float, - (a) => { return $decode.success(new Hsla(h, s, l, a)); }, - ); - }, - ); - }, - ); - }, - ); -} - -/** - * Attempt to decode some [`Dynamic`](https://hexdocs.pm/gleam_stdlib/gleam/dynamic.html#Dynamic) - * value into a `Colour`. Most often you'll use this to decode some JSON. - * - * - */ -export function decoder() { - return $decode.one_of(rgba_decoder(), toList([hsla_decoder()])); -} - -/** - * A `Colour` reprsenting the colour RGBA(239, 41, 41, 1.0) - */ -export const light_red = /* @__PURE__ */ new Rgba( - 0.9372549019607843, - 0.1607843137254902, - 0.1607843137254902, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(204, 0, 0, 1.0) - */ -export const red = /* @__PURE__ */ new Rgba(0.8, 0.0, 0.0, 1.0); - -/** - * A `Colour` reprsenting the colour RGBA(164, 0, 0, 1.0) - */ -export const dark_red = /* @__PURE__ */ new Rgba( - 0.6431372549019608, - 0.0, - 0.0, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(252, 175, 62, 1.0) - */ -export const light_orange = /* @__PURE__ */ new Rgba( - 0.9882352941176471, - 0.6862745098039216, - 0.24313725490196078, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(245, 121, 0, 1.0) - */ -export const orange = /* @__PURE__ */ new Rgba( - 0.9607843137254902, - 0.4745098039215686, - 0.0, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(206, 92, 0, 1.0) - */ -export const dark_orange = /* @__PURE__ */ new Rgba( - 0.807843137254902, - 0.3607843137254902, - 0.0, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(255, 233, 79, 1.0) - */ -export const light_yellow = /* @__PURE__ */ new Rgba( - 1.0, - 0.9137254901960784, - 0.30980392156862746, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(237, 212, 0, 1.0) - */ -export const yellow = /* @__PURE__ */ new Rgba( - 0.9294117647058824, - 0.8313725490196079, - 0.0, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(196, 160, 0, 1.0) - */ -export const dark_yellow = /* @__PURE__ */ new Rgba( - 0.7686274509803922, - 0.6274509803921569, - 0.0, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(138, 226, 52, 1.0) - */ -export const light_green = /* @__PURE__ */ new Rgba( - 0.5411764705882353, - 0.8862745098039215, - 0.20392156862745098, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(115, 210, 22, 1.0) - */ -export const green = /* @__PURE__ */ new Rgba( - 0.45098039215686275, - 0.8235294117647058, - 0.08627450980392157, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(78, 154, 6, 1.0) - */ -export const dark_green = /* @__PURE__ */ new Rgba( - 0.3058823529411765, - 0.6039215686274509, - 0.023529411764705882, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(114, 159, 207, 1.0) - */ -export const light_blue = /* @__PURE__ */ new Rgba( - 0.4470588235294118, - 0.6235294117647059, - 0.8117647058823529, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(52, 101, 164, 1.0) - */ -export const blue = /* @__PURE__ */ new Rgba( - 0.20392156862745098, - 0.396078431372549, - 0.6431372549019608, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(32, 74, 135, 1.0) - */ -export const dark_blue = /* @__PURE__ */ new Rgba( - 0.12549019607843137, - 0.2901960784313726, - 0.5294117647058824, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(173, 127, 168, 1.0) - */ -export const light_purple = /* @__PURE__ */ new Rgba( - 0.6784313725490196, - 0.4980392156862745, - 0.6588235294117647, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(117, 80, 123, 1.0) - */ -export const purple = /* @__PURE__ */ new Rgba( - 0.4588235294117647, - 0.3137254901960784, - 0.4823529411764706, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(92, 53, 102, 1.0) - */ -export const dark_purple = /* @__PURE__ */ new Rgba( - 0.3607843137254902, - 0.20784313725490197, - 0.4, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(233, 185, 110, 1.0) - */ -export const light_brown = /* @__PURE__ */ new Rgba( - 0.9137254901960784, - 0.7254901960784313, - 0.43137254901960786, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(193, 125, 17, 1.0) - */ -export const brown = /* @__PURE__ */ new Rgba( - 0.7568627450980392, - 0.49019607843137253, - 0.06666666666666667, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(143, 89, 2, 1.0) - */ -export const dark_brown = /* @__PURE__ */ new Rgba( - 0.5607843137254902, - 0.34901960784313724, - 0.00784313725490196, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(0, 0, 0, 1.0) - */ -export const black = /* @__PURE__ */ new Rgba(0.0, 0.0, 0.0, 1.0); - -/** - * A `Colour` reprsenting the colour RGBA(255, 255, 255, 1.0) - */ -export const white = /* @__PURE__ */ new Rgba(1.0, 1.0, 1.0, 1.0); - -/** - * A `Colour` reprsenting the colour RGBA(238, 238, 236, 1.0) - */ -export const light_grey = /* @__PURE__ */ new Rgba( - 0.9333333333333333, - 0.9333333333333333, - 0.9254901960784314, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(211, 215, 207, 1.0) - */ -export const grey = /* @__PURE__ */ new Rgba( - 0.8274509803921568, - 0.8431372549019608, - 0.8117647058823529, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(186, 189, 182, 1.0) - */ -export const dark_grey = /* @__PURE__ */ new Rgba( - 0.7294117647058823, - 0.7411764705882353, - 0.7137254901960784, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(238, 238, 236, 1.0) - */ -export const light_gray = /* @__PURE__ */ new Rgba( - 0.9333333333333333, - 0.9333333333333333, - 0.9254901960784314, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(211, 215, 207, 1.0) - */ -export const gray = /* @__PURE__ */ new Rgba( - 0.8274509803921568, - 0.8431372549019608, - 0.8117647058823529, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(186, 189, 182, 1.0) - */ -export const dark_gray = /* @__PURE__ */ new Rgba( - 0.7294117647058823, - 0.7411764705882353, - 0.7137254901960784, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(136, 138, 133, 1.0) - */ -export const light_charcoal = /* @__PURE__ */ new Rgba( - 0.5333333333333333, - 0.5411764705882353, - 0.5215686274509804, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(85, 87, 83, 1.0) - */ -export const charcoal = /* @__PURE__ */ new Rgba( - 0.3333333333333333, - 0.3411764705882353, - 0.3254901960784314, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(46, 52, 54, 1.0) - */ -export const dark_charcoal = /* @__PURE__ */ new Rgba( - 0.1803921568627451, - 0.20392156862745098, - 0.21176470588235294, - 1.0, -); - -/** - * A `Colour` reprsenting the colour RGBA(255, 175, 243, 1.0) - */ -export const pink = /* @__PURE__ */ new Rgba( - 1.0, - 0.6862745098039216, - 0.9529411764705882, - 1.0, -); diff --git a/build/dev/javascript/gleam_community_colour/gleam_community/colour/accessibility.mjs b/build/dev/javascript/gleam_community_colour/gleam_community/colour/accessibility.mjs deleted file mode 100644 index 0c56e21..0000000 --- a/build/dev/javascript/gleam_community_colour/gleam_community/colour/accessibility.mjs +++ /dev/null @@ -1,146 +0,0 @@ -import * as $float from "../../../gleam_stdlib/gleam/float.mjs"; -import * as $list from "../../../gleam_stdlib/gleam/list.mjs"; -import { Ok, makeError, divideFloat } from "../../gleam.mjs"; -import * as $colour from "../../gleam_community/colour.mjs"; - -const FILEPATH = "src/gleam_community/colour/accessibility.gleam"; - -function intensity(colour_value) { - let $ = true; - if (colour_value <= 0.03928) { - return colour_value / 12.92; - } else { - let $1 = $float.power((colour_value + 0.055) / 1.055, 2.4); - let i; - if ($1 instanceof Ok) { - i = $1[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam_community/colour/accessibility", - 62, - "intensity", - "Pattern match failed, no pattern matched the value.", - { - value: $1, - start: 2399, - end: 2470, - pattern_start: 2410, - pattern_end: 2415 - } - ) - } - return i; - } -} - -/** - * Returns the relative brightness of the given `Colour` as a `Float` between - * 0.0, and 1.0 with 0.0 being the darkest possible colour and 1.0 being the lightest. - * - *
- * Example: - * - * ```gleam - * fn example() { - * luminance(colour.white) // 1.0 - * } - * ``` - *
- * - * - */ -export function luminance(colour) { - let $ = $colour.to_rgba(colour); - let r; - let g; - let b; - r = $[0]; - g = $[1]; - b = $[2]; - let r_intensity = intensity(r); - let g_intensity = intensity(g); - let b_intensity = intensity(b); - return ((0.2126 * r_intensity) + (0.7152 * g_intensity)) + (0.0722 * b_intensity); -} - -/** - * Returns the contrast between two `Colour` values as a `Float` between 1.0, - * and 21.0 with 1.0 being no contrast and, 21.0 being the highest possible contrast. - * - *
- * Example: - * - * ```gleam - * fn example() { - * contrast_ratio(between: colour.white, and: colour.black) // 21.0 - * } - * ``` - *
- * - * - */ -export function contrast_ratio(colour_a, colour_b) { - let luminance_a = luminance(colour_a) + 0.05; - let luminance_b = luminance(colour_b) + 0.05; - let $ = luminance_a > luminance_b; - if ($) { - return divideFloat(luminance_a, luminance_b); - } else { - return divideFloat(luminance_b, luminance_a); - } -} - -/** - * Returns the `Colour` with the highest contrast between the base `Colour`, - * and and the other provided `Colour` values. - * - *
- * Example: - * - * ```gleam - * fn example() { - * maximum_contrast( - * colour.yellow, - * [colour.white, colour.dark_blue, colour.green], - * ) - * } - * ``` - *
- * - * - */ -export function maximum_contrast(base, colours) { - let _pipe = colours; - let _pipe$1 = $list.sort( - _pipe, - (colour_a, colour_b) => { - let contrast_a = contrast_ratio(base, colour_a); - let contrast_b = contrast_ratio(base, colour_b); - return $float.compare(contrast_b, contrast_a); - }, - ); - return $list.first(_pipe$1); -} diff --git a/build/dev/javascript/gleam_community_colour/gleam_community@colour.erl b/build/dev/javascript/gleam_community_colour/gleam_community@colour.erl deleted file mode 100644 index faee070..0000000 --- a/build/dev/javascript/gleam_community_colour/gleam_community@colour.erl +++ /dev/null @@ -1,1199 +0,0 @@ --module(gleam_community@colour). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/gleam_community/colour.gleam"). --export([from_rgb255/3, from_rgb/3, from_rgba/4, from_hsla/4, from_hsl/3, from_rgb_hex/1, from_rgb_hex_string/1, from_rgba_hex/1, from_rgba_hex_string/1, to_rgba/1, to_hsla/1, to_css_rgba_string/1, to_rgba_hex/1, to_rgba_hex_string/1, to_rgb_hex/1, to_rgb_hex_string/1, encode/1, decoder/0]). --export_type([colour/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - "\n" - " - **Types**\n" - " - [`Colour`](#Colour)\n" - " - [`Color`](#Color)\n" - " - **Constructors**\n" - " - [`from_rgb255`](#from_rgb255)\n" - " - [`from_rgb`](#from_rgb)\n" - " - [`from_rgba`](#from_rgba)\n" - " - [`from_hsl`](#from_hsl)\n" - " - [`from_hsla`](#from_hsla)\n" - " - [`from_rgb_hex`](#from_rgb_hex)\n" - " - [`from_rgba_hex`](#from_rgba_hex)\n" - " - [`from_rgb_hex_string`](#from_rgb_hex_string)\n" - " - [`from_rgba_hex_string`](#from_rgba_hex_string)\n" - " - **Conversions**\n" - " - [`to_rgba`](#to_rgba)\n" - " - [`to_hsla`](#hsla)\n" - " - [`to_css_rgba_string`](#to_css_rgba_string)\n" - " - [`to_rgba_hex_string`](#to_rgba_hex_string)\n" - " - [`to_rgb_hex_string`](#to_rgb_hex_string)\n" - " - [`to_rgba_hex`](#to_rgba_hex)\n" - " - [`to_rgb_hex`](#to_rgb_hex)\n" - " - **JSON**\n" - " - [`encode`](#encode)\n" - " - [`decoder`](#decoder)\n" - " - **Colours**\n" - " - [`light_red`](#light_red)\n" - " - [`red`](#red)\n" - " - [`dark_red`](#dark_red)\n" - " - [`light_orange`](#light_orange)\n" - " - [`orange`](#orange)\n" - " - [`dark_orange`](#dark_orange)\n" - " - [`light_yellow`](#light_yellow)\n" - " - [`yellow`](#yellow)\n" - " - [`dark_yellow`](#dark_yellow)\n" - " - [`light_green`](#light_green)\n" - " - [`green`](#green)\n" - " - [`dark_green`](#dark_green)\n" - " - [`light_blue`](#light_blue)\n" - " - [`blue`](#blue)\n" - " - [`dark_blue`](#dark_blue)\n" - " - [`light_purple`](#light_purple)\n" - " - [`purple`](#purple)\n" - " - [`dark_purple`](#dark_purple)\n" - " - [`light_brown`](#light_brown)\n" - " - [`brown`](#brown)\n" - " - [`dark_brown`](#dark_brown)\n" - " - [`black`](#black)\n" - " - [`white`](#white)\n" - " - [`light_grey`](#light_grey)\n" - " - [`grey`](#grey)\n" - " - [`dark_grey`](#dark_grey)\n" - " - [`light_gray`](#light_gray)\n" - " - [`gray`](#gray)\n" - " - [`dark_gray`](#dark_gray)\n" - " - [`light_charcoal`](#light_charcoal)\n" - " - [`charcoal`](#charcoal)\n" - " - [`dark_charcoal`](#dark_charcoal)\n" - " - [`pink`](#pink)\n" - "\n" - " ---\n" - "\n" - " This package was heavily inspired by the `elm-color` module.\n" - " The original source code can be found\n" - " here.\n" - "\n" - "
\n" - " The license of that package is produced below:\n" - "\n" - "\n" - " > MIT License\n" - "\n" - " > Copyright 2018 Aaron VonderHaar\n" - "\n" - " > Redistribution and use in source and binary forms, with or without modification,\n" - " are permitted provided that the following conditions are met:\n" - "\n" - " 1. Redistributions of source code must retain the above copyright notice,\n" - " this list of conditions and the following disclaimer.\n" - "\n" - " 2. Redistributions in binary form must reproduce the above copyright notice,\n" - " this list of conditions and the following disclaimer in the documentation\n" - " and/or other materials provided with the distribution.\n" - "\n" - " 3. Neither the name of the copyright holder nor the names of its contributors\n" - " may be used to endorse or promote products derived from this software without\n" - " specific prior written permission.\n" - "\n" - " > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n" - " ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" - " OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\n" - " THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n" - " EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n" - " OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" - " THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" - " ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" - "\n" - " > The above copyright notice and this permission notice shall be included in all\n" - " copies or substantial portions of the Software.\n" - "
\n" - "\n" -). - --opaque colour() :: {rgba, float(), float(), float(), float()} | - {hsla, float(), float(), float(), float()}. - --file("src/gleam_community/colour.gleam", 155). --spec valid_colour_value(float()) -> {ok, float()} | {error, nil}. -valid_colour_value(C) -> - case (C > 1.0) orelse (C < +0.0) of - true -> - {error, nil}; - - false -> - {ok, C} - end. - --file("src/gleam_community/colour.gleam", 162). --spec hue_to_rgb(float(), float(), float()) -> float(). -hue_to_rgb(Hue, M1, M2) -> - H = case Hue of - _ when Hue < +0.0 -> - Hue + 1.0; - - _ when Hue > 1.0 -> - Hue - 1.0; - - _ -> - Hue - end, - H_t_6 = H * 6.0, - H_t_2 = H * 2.0, - H_t_3 = H * 3.0, - case H of - _ when H_t_6 < 1.0 -> - M1 + (((M2 - M1) * H) * 6.0); - - _ when H_t_2 < 1.0 -> - M2; - - _ when H_t_3 < 2.0 -> - M1 + (((M2 - M1) * ((2.0 / 3.0) - H)) * 6.0); - - _ -> - M1 - end. - --file("src/gleam_community/colour.gleam", 181). --spec hex_string_to_int(binary()) -> {ok, integer()} | {error, nil}. -hex_string_to_int(Hex_string) -> - Hex = case Hex_string of - <<"#"/utf8, Hex_number/binary>> -> - Hex_number; - - <<"0x"/utf8, Hex_number@1/binary>> -> - Hex_number@1; - - _ -> - Hex_string - end, - _pipe = Hex, - _pipe@1 = string:lowercase(_pipe), - _pipe@2 = gleam@string:to_graphemes(_pipe@1), - _pipe@3 = lists:reverse(_pipe@2), - gleam@list:index_fold( - _pipe@3, - {ok, 0}, - fun(Total, Char, Index) -> case Total of - {error, nil} -> - {error, nil}; - - {ok, V} -> - gleam@result:'try'(case Char of - <<"a"/utf8>> -> - {ok, 10}; - - <<"b"/utf8>> -> - {ok, 11}; - - <<"c"/utf8>> -> - {ok, 12}; - - <<"d"/utf8>> -> - {ok, 13}; - - <<"e"/utf8>> -> - {ok, 14}; - - <<"f"/utf8>> -> - {ok, 15}; - - _ -> - gleam_stdlib:parse_int(Char) - end, fun(Num) -> - gleam@result:'try'( - gleam@int:power(16, erlang:float(Index)), - fun(Base) -> - {ok, - V + erlang:round( - erlang:float(Num) * Base - )} - end - ) - end) - end end - ). - --file("src/gleam_community/colour.gleam", 212). --spec hsla_to_rgba(float(), float(), float(), float()) -> {float(), - float(), - float(), - float()}. -hsla_to_rgba(H, S, L, A) -> - M2 = case L =< 0.5 of - true -> - L * (S + 1.0); - - false -> - (L + S) - (L * S) - end, - M1 = (L * 2.0) - M2, - R = hue_to_rgb(H + (1.0 / 3.0), M1, M2), - G = hue_to_rgb(H, M1, M2), - B = hue_to_rgb(H - (1.0 / 3.0), M1, M2), - {R, G, B, A}. - --file("src/gleam_community/colour.gleam", 232). --spec rgba_to_hsla(float(), float(), float(), float()) -> {float(), - float(), - float(), - float()}. -rgba_to_hsla(R, G, B, A) -> - Min_colour = gleam@float:min(R, gleam@float:min(G, B)), - Max_colour = gleam@float:max(R, gleam@float:max(G, B)), - H1 = case true of - _ when Max_colour =:= R -> - gleam@float:divide(G - B, Max_colour - Min_colour); - - _ when Max_colour =:= G -> - _pipe = gleam@float:divide(B - R, Max_colour - Min_colour), - gleam@result:'try'(_pipe, fun(D) -> {ok, 2.0 + D} end); - - _ -> - _pipe@1 = gleam@float:divide(R - G, Max_colour - Min_colour), - gleam@result:'try'(_pipe@1, fun(D@1) -> {ok, 4.0 + D@1} end) - end, - H2 = case H1 of - {ok, V} -> - {ok, V * (1.0 / 6.0)}; - - _ -> - H1 - end, - H3 = case H2 of - {ok, V@1} when V@1 < +0.0 -> - V@1 + 1.0; - - {ok, V@2} -> - V@2; - - _ -> - +0.0 - end, - L = (Min_colour + Max_colour) / 2.0, - S = case true of - _ when Min_colour =:= Max_colour -> - +0.0; - - _ when L < 0.5 -> - case (Max_colour + Min_colour) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> (Max_colour - Min_colour) / Gleam@denominator - end; - - _ -> - case ((2.0 - Max_colour) - Min_colour) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> (Max_colour - Min_colour) / Gleam@denominator@1 - end - end, - {H3, S, L, A}. - --file("src/gleam_community/colour.gleam", 300). -?DOC( - " Returns a `Result(Colour)` created from the given 8 bit RGB values.\n" - "\n" - " Returns `Error(Nil)` if the supplied RGB values are greater than 255 or less than 0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb255(integer(), integer(), integer()) -> {ok, colour()} | - {error, nil}. -from_rgb255(Red, Green, Blue) -> - gleam@result:'try'( - begin - _pipe = Red, - _pipe@1 = erlang:float(_pipe), - _pipe@2 = gleam@float:divide(_pipe@1, 255.0), - gleam@result:'try'(_pipe@2, fun valid_colour_value/1) - end, - fun(R) -> - gleam@result:'try'( - begin - _pipe@3 = Green, - _pipe@4 = erlang:float(_pipe@3), - _pipe@5 = gleam@float:divide(_pipe@4, 255.0), - gleam@result:'try'(_pipe@5, fun valid_colour_value/1) - end, - fun(G) -> - gleam@result:'try'( - begin - _pipe@6 = Blue, - _pipe@7 = erlang:float(_pipe@6), - _pipe@8 = gleam@float:divide(_pipe@7, 255.0), - gleam@result:'try'( - _pipe@8, - fun valid_colour_value/1 - ) - end, - fun(B) -> {ok, {rgba, R, G, B, 1.0}} end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 348). -?DOC( - " Returns `Result(Colour)` created from the given RGB values.\n" - "\n" - " If the supplied RGB values are greater than 1.0 or less than 0.0 returns `Error(Nil)`\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb(1.0, 0.0, 0.0)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb(float(), float(), float()) -> {ok, colour()} | {error, nil}. -from_rgb(Red, Green, Blue) -> - gleam@result:'try'( - valid_colour_value(Red), - fun(R) -> - gleam@result:'try'( - valid_colour_value(Green), - fun(G) -> - gleam@result:'try'( - valid_colour_value(Blue), - fun(B) -> {ok, {rgba, R, G, B, 1.0}} end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 383). -?DOC( - " Returns `Result(Colour)` created from the given RGBA values.\n" - "\n" - " Returns `Error(Nil)` if the supplied RGBA values are greater than 1.0 or less than 0.0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_rbga(1.0, 0.0, 0.0, 0.5)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgba(float(), float(), float(), float()) -> {ok, colour()} | - {error, nil}. -from_rgba(Red, Green, Blue, Alpha) -> - gleam@result:'try'( - valid_colour_value(Red), - fun(R) -> - gleam@result:'try'( - valid_colour_value(Green), - fun(G) -> - gleam@result:'try'( - valid_colour_value(Blue), - fun(B) -> - gleam@result:'try'( - valid_colour_value(Alpha), - fun(A) -> {ok, {rgba, R, G, B, A}} end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 420). -?DOC( - " Returns `Result(Colour)` created from the given HSLA values.\n" - "\n" - " Returns `Error(Nil)`f the supplied HSLA values are greater than 1.0 or less than 0.0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_hsla(0.0, 1.0, 0.5, 0.5)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_hsla(float(), float(), float(), float()) -> {ok, colour()} | - {error, nil}. -from_hsla(Hue, Saturation, Lightness, Alpha) -> - gleam@result:'try'( - valid_colour_value(Hue), - fun(H) -> - gleam@result:'try'( - valid_colour_value(Saturation), - fun(S) -> - gleam@result:'try'( - valid_colour_value(Lightness), - fun(L) -> - gleam@result:'try'( - valid_colour_value(Alpha), - fun(A) -> {ok, {hsla, H, S, L, A}} end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 457). -?DOC( - " Returns `Result(Colour)` created from the given HSL values.\n" - "\n" - " Returns `Error(Nil)` if the supplied HSL values are greater than 1.0 or less than 0.0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_hsla(0.0, 1.0, 0.5)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_hsl(float(), float(), float()) -> {ok, colour()} | {error, nil}. -from_hsl(Hue, Saturation, Lightness) -> - from_hsla(Hue, Saturation, Lightness, 1.0). - --file("src/gleam_community/colour.gleam", 488). -?DOC( - " Returns a `Result(Colour)` created from the given hex `Int`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffff or less than 0x0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb_hex(0xff0000)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb_hex(integer()) -> {ok, colour()} | {error, nil}. -from_rgb_hex(Hex) -> - case (Hex > 16#ffffff) orelse (Hex < 0) of - true -> - {error, nil}; - - false -> - R = begin - _pipe = erlang:'bsr'(Hex, 16), - erlang:'band'(_pipe, 16#ff) - end, - G = begin - _pipe@1 = erlang:'bsr'(Hex, 8), - erlang:'band'(_pipe@1, 16#ff) - end, - B = erlang:'band'(Hex, 16#ff), - from_rgb255(R, G, B) - end. - --file("src/gleam_community/colour.gleam", 527). -?DOC( - " Returns a `Result(Colour)` created from the given RGB hex `String`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `\"#ffffff\" or less than `\"#0\"`\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb_hex_string(\"#ff0000\")\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb_hex_string(binary()) -> {ok, colour()} | {error, nil}. -from_rgb_hex_string(Hex_string) -> - gleam@result:'try'( - hex_string_to_int(Hex_string), - fun(Hex_int) -> from_rgb_hex(Hex_int) end - ). - --file("src/gleam_community/colour.gleam", 585). -?DOC( - " Returns a `Result(Colour)` created from the given hex `Int`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffffff or less than 0x0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_rgba_hex(0xff00007f)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgba_hex(integer()) -> {ok, colour()} | {error, nil}. -from_rgba_hex(Hex) -> - case (Hex > 16#ffffffff) orelse (Hex < 0) of - true -> - {error, nil}; - - false -> - R@1 = case begin - _pipe = erlang:'bsr'(Hex, 24), - _pipe@1 = erlang:'band'(_pipe, 16#ff), - _pipe@2 = erlang:float(_pipe@1), - gleam@float:divide(_pipe@2, 255.0) - end of - {ok, R} -> R; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 590, - value => _assert_fail, - start => 17111, - 'end' => 17260, - pattern_start => 17122, - pattern_end => 17127}) - end, - G@1 = case begin - _pipe@3 = erlang:'bsr'(Hex, 16), - _pipe@4 = erlang:'band'(_pipe@3, 16#ff), - _pipe@5 = erlang:float(_pipe@4), - gleam@float:divide(_pipe@5, 255.0) - end of - {ok, G} -> G; - _assert_fail@1 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 596, - value => _assert_fail@1, - start => 17332, - 'end' => 17481, - pattern_start => 17343, - pattern_end => 17348}) - end, - B@1 = case begin - _pipe@6 = erlang:'bsr'(Hex, 8), - _pipe@7 = erlang:'band'(_pipe@6, 16#ff), - _pipe@8 = erlang:float(_pipe@7), - gleam@float:divide(_pipe@8, 255.0) - end of - {ok, B} -> B; - _assert_fail@2 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 602, - value => _assert_fail@2, - start => 17553, - 'end' => 17701, - pattern_start => 17564, - pattern_end => 17569}) - end, - A@1 = case begin - _pipe@9 = erlang:'band'(Hex, 16#ff), - _pipe@10 = erlang:float(_pipe@9), - gleam@float:divide(_pipe@10, 255.0) - end of - {ok, A} -> A; - _assert_fail@3 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 608, - value => _assert_fail@3, - start => 17773, - 'end' => 17883, - pattern_start => 17784, - pattern_end => 17789}) - end, - from_rgba(R@1, G@1, B@1, A@1) - end. - --file("src/gleam_community/colour.gleam", 556). -?DOC( - " Returns a `Result(Colour)` created from the given RGBA hex `String`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `\"#ffffffff\" or less than `\"#0\"`\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_rgba_hex_string(\"#ff00007f\")\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgba_hex_string(binary()) -> {ok, colour()} | {error, nil}. -from_rgba_hex_string(Hex_string) -> - gleam@result:'try'( - hex_string_to_int(Hex_string), - fun(Hex_int) -> from_rgba_hex(Hex_int) end - ). - --file("src/gleam_community/colour.gleam", 642). -?DOC( - " Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s\n" - " R, G, B, and A values respectively.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " let #(r, g, b, a) = to_rgba(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgba(colour()) -> {float(), float(), float(), float()}. -to_rgba(Colour) -> - case Colour of - {rgba, R, G, B, A} -> - {R, G, B, A}; - - {hsla, H, S, L, A@1} -> - hsla_to_rgba(H, S, L, A@1) - end. - --file("src/gleam_community/colour.gleam", 672). -?DOC( - " Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s\n" - " H, S, L, and A values respectively.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " let #(h, s, l, a) = to_hsla(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_hsla(colour()) -> {float(), float(), float(), float()}. -to_hsla(Colour) -> - case Colour of - {hsla, H, S, L, A} -> - {H, S, L, A}; - - {rgba, R, G, B, A@1} -> - rgba_to_hsla(R, G, B, A@1) - end. - --file("src/gleam_community/colour.gleam", 701). -?DOC( - " Returns an rgba formatted CSS `String` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " let css_red = to_css_rgba_string(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_css_rgba_string(colour()) -> binary(). -to_css_rgba_string(Colour) -> - {R, G, B, A} = to_rgba(Colour), - Percent = fun(X) -> - P@1 = case begin - _pipe = X, - _pipe@1 = gleam@float:multiply(_pipe, 10000.0), - _pipe@2 = erlang:round(_pipe@1), - _pipe@3 = erlang:float(_pipe@2), - gleam@float:divide(_pipe@3, 100.0) - end of - {ok, P} -> P; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"to_css_rgba_string"/utf8>>, - line => 706, - value => _assert_fail, - start => 20510, - 'end' => 20646, - pattern_start => 20521, - pattern_end => 20526}) - end, - P@1 - end, - Round_to = fun(X@1) -> - R@2 = case begin - _pipe@4 = X@1, - _pipe@5 = gleam@float:multiply(_pipe@4, 1000.0), - _pipe@6 = erlang:round(_pipe@5), - _pipe@7 = erlang:float(_pipe@6), - gleam@float:divide(_pipe@7, 1000.0) - end of - {ok, R@1} -> R@1; - _assert_fail@1 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"to_css_rgba_string"/utf8>>, - line => 718, - value => _assert_fail@1, - start => 20768, - 'end' => 20903, - pattern_start => 20779, - pattern_end => 20784}) - end, - R@2 - end, - gleam@string:join( - [<<"rgba("/utf8>>, - <<(gleam_stdlib:float_to_string(Percent(R)))/binary, "%,"/utf8>>, - <<(gleam_stdlib:float_to_string(Percent(G)))/binary, "%,"/utf8>>, - <<(gleam_stdlib:float_to_string(Percent(B)))/binary, "%,"/utf8>>, - gleam_stdlib:float_to_string(Round_to(A)), - <<")"/utf8>>], - <<""/utf8>> - ). - --file("src/gleam_community/colour.gleam", 829). -?DOC( - " Returns an hex `Int` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0)\n" - " let red_hex_int = to_rgba_hex(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgba_hex(colour()) -> integer(). -to_rgba_hex(Colour) -> - {R, G, B, A} = to_rgba(Colour), - Red = begin - _pipe = R * 255.0, - _pipe@1 = erlang:round(_pipe), - erlang:'bsl'(_pipe@1, 24) - end, - Green = begin - _pipe@2 = G * 255.0, - _pipe@3 = erlang:round(_pipe@2), - erlang:'bsl'(_pipe@3, 16) - end, - Blue = begin - _pipe@4 = B * 255.0, - _pipe@5 = erlang:round(_pipe@4), - erlang:'bsl'(_pipe@5, 8) - end, - Alpha = begin - _pipe@6 = A * 255.0, - erlang:round(_pipe@6) - end, - ((Red + Green) + Blue) + Alpha. - --file("src/gleam_community/colour.gleam", 763). -?DOC( - " Returns an rgba hex formatted `String` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0)\n" - " let red_hex = to_rgba_hex_string(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgba_hex_string(colour()) -> binary(). -to_rgba_hex_string(Colour) -> - Hex_string = begin - _pipe = to_rgba_hex(Colour), - gleam@int:to_base16(_pipe) - end, - case string:length(Hex_string) of - 8 -> - Hex_string; - - L -> - <<(gleam@string:repeat(<<"0"/utf8>>, 8 - L))/binary, - Hex_string/binary>> - end. - --file("src/gleam_community/colour.gleam", 876). -?DOC( - " Returns a rgb hex `Int` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(255, 0, 0)\n" - " let red_hex_int = to_rgb_hex(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgb_hex(colour()) -> integer(). -to_rgb_hex(Colour) -> - {R, G, B, _} = to_rgba(Colour), - Red = begin - _pipe = R * 255.0, - _pipe@1 = erlang:round(_pipe), - erlang:'bsl'(_pipe@1, 16) - end, - Green = begin - _pipe@2 = G * 255.0, - _pipe@3 = erlang:round(_pipe@2), - erlang:'bsl'(_pipe@3, 8) - end, - Blue = begin - _pipe@4 = B * 255.0, - erlang:round(_pipe@4) - end, - (Red + Green) + Blue. - --file("src/gleam_community/colour.gleam", 796). -?DOC( - " Returns an rgb hex formatted `String` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(255, 0, 0)\n" - " let red_hex = to_rgb_hex_string(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgb_hex_string(colour()) -> binary(). -to_rgb_hex_string(Colour) -> - Hex_string = begin - _pipe = to_rgb_hex(Colour), - gleam@int:to_base16(_pipe) - end, - case string:length(Hex_string) of - 6 -> - Hex_string; - - L -> - <<(gleam@string:repeat(<<"0"/utf8>>, 6 - L))/binary, - Hex_string/binary>> - end. - --file("src/gleam_community/colour.gleam", 918). --spec encode_rgba(float(), float(), float(), float()) -> gleam@json:json(). -encode_rgba(R, G, B, A) -> - gleam@json:object( - [{<<"r"/utf8>>, gleam@json:float(R)}, - {<<"g"/utf8>>, gleam@json:float(G)}, - {<<"b"/utf8>>, gleam@json:float(B)}, - {<<"a"/utf8>>, gleam@json:float(A)}] - ). - --file("src/gleam_community/colour.gleam", 927). --spec encode_hsla(float(), float(), float(), float()) -> gleam@json:json(). -encode_hsla(H, S, L, A) -> - gleam@json:object( - [{<<"h"/utf8>>, gleam@json:float(H)}, - {<<"s"/utf8>>, gleam@json:float(S)}, - {<<"l"/utf8>>, gleam@json:float(L)}, - {<<"a"/utf8>>, gleam@json:float(A)}] - ). - --file("src/gleam_community/colour.gleam", 911). -?DOC( - " Encodes a `Colour` value as a Gleam [`Json`](https://hexdocs.pm/gleam_json/gleam/json.html#Json)\n" - " value. You'll need this if you want to send a `Colour` value over the network\n" - " in a HTTP request or response, for example.\n" - "\n" - " \n" -). --spec encode(colour()) -> gleam@json:json(). -encode(Colour) -> - case Colour of - {rgba, R, G, B, A} -> - encode_rgba(R, G, B, A); - - {hsla, H, S, L, A@1} -> - encode_hsla(H, S, L, A@1) - end. - --file("src/gleam_community/colour.gleam", 952). --spec rgba_decoder() -> gleam@dynamic@decode:decoder(colour()). -rgba_decoder() -> - gleam@dynamic@decode:field( - <<"r"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(R) -> - gleam@dynamic@decode:field( - <<"g"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(G) -> - gleam@dynamic@decode:field( - <<"b"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(B) -> - gleam@dynamic@decode:field( - <<"a"/utf8>>, - {decoder, - fun gleam@dynamic@decode:decode_float/1}, - fun(A) -> - gleam@dynamic@decode:success( - {rgba, R, G, B, A} - ) - end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 961). --spec hsla_decoder() -> gleam@dynamic@decode:decoder(colour()). -hsla_decoder() -> - gleam@dynamic@decode:field( - <<"h"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(H) -> - gleam@dynamic@decode:field( - <<"s"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(S) -> - gleam@dynamic@decode:field( - <<"l"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(L) -> - gleam@dynamic@decode:field( - <<"a"/utf8>>, - {decoder, - fun gleam@dynamic@decode:decode_float/1}, - fun(A) -> - gleam@dynamic@decode:success( - {hsla, H, S, L, A} - ) - end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 948). -?DOC( - " Attempt to decode some [`Dynamic`](https://hexdocs.pm/gleam_stdlib/gleam/dynamic.html#Dynamic)\n" - " value into a `Colour`. Most often you'll use this to decode some JSON.\n" - "\n" - " \n" -). --spec decoder() -> gleam@dynamic@decode:decoder(colour()). -decoder() -> - gleam@dynamic@decode:one_of(rgba_decoder(), [hsla_decoder()]). diff --git a/build/dev/javascript/gleam_community_colour/gleam_community@colour@accessibility.erl b/build/dev/javascript/gleam_community_colour/gleam_community@colour@accessibility.erl deleted file mode 100644 index 35c1d67..0000000 --- a/build/dev/javascript/gleam_community_colour/gleam_community@colour@accessibility.erl +++ /dev/null @@ -1,203 +0,0 @@ --module(gleam_community@colour@accessibility). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/gleam_community/colour/accessibility.gleam"). --export([luminance/1, contrast_ratio/2, maximum_contrast/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " \n" - " - **Accessibility**\n" - " - [`luminance`](#luminance)\n" - " - [`contrast_ratio`](#contrast_ratio)\n" - " - [`maximum_contrast`](#maximum_contrast)\n" - "\n" - " ---\n" - "\n" - " This package was heavily inspired by the `elm-color-extra` module.\n" - " The original source code can be found\n" - " here.\n" - "\n" - "
\n" - " The license of that package is produced below:\n" - " \n" - " \n" - " > MIT License\n" - "\n" - " > Copyright (c) 2016 Andreas Köberle\n" - "\n" - " > Permission is hereby granted, free of charge, to any person obtaining a copy\n" - " of this software and associated documentation files (the \"Software\"), to deal\n" - " in the Software without restriction, including without limitation the rights\n" - " to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" - " copies of the Software, and to permit persons to whom the Software is\n" - " furnished to do so, subject to the following conditions:\n" - "\n" - " > The above copyright notice and this permission notice shall be included in all\n" - " copies or substantial portions of the Software.\n" - "\n" - " > THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" - " IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" - " FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" - " AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" - " LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" - " OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" - " SOFTWARE.\n" - "\n" - "
\n" - "\n" -). - --file("src/gleam_community/colour/accessibility.gleam", 56). --spec intensity(float()) -> float(). -intensity(Colour_value) -> - case true of - _ when Colour_value =< 0.03928 -> - Colour_value / 12.92; - - _ -> - I@1 = case gleam@float:power((Colour_value + 0.055) / 1.055, 2.4) of - {ok, I} -> I; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour/accessibility"/utf8>>, - function => <<"intensity"/utf8>>, - line => 62, - value => _assert_fail, - start => 2399, - 'end' => 2470, - pattern_start => 2410, - pattern_end => 2415}) - end, - I@1 - end. - --file("src/gleam_community/colour/accessibility.gleam", 92). -?DOC( - " Returns the relative brightness of the given `Colour` as a `Float` between\n" - " 0.0, and 1.0 with 0.0 being the darkest possible colour and 1.0 being the lightest.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " luminance(colour.white) // 1.0\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec luminance(gleam_community@colour:colour()) -> float(). -luminance(Colour) -> - {R, G, B, _} = gleam_community@colour:to_rgba(Colour), - R_intensity = intensity(R), - G_intensity = intensity(G), - B_intensity = intensity(B), - ((0.2126 * R_intensity) + (0.7152 * G_intensity)) + (0.0722 * B_intensity). - --file("src/gleam_community/colour/accessibility.gleam", 125). -?DOC( - " Returns the contrast between two `Colour` values as a `Float` between 1.0,\n" - " and 21.0 with 1.0 being no contrast and, 21.0 being the highest possible contrast.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " contrast_ratio(between: colour.white, and: colour.black) // 21.0\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec contrast_ratio( - gleam_community@colour:colour(), - gleam_community@colour:colour() -) -> float(). -contrast_ratio(Colour_a, Colour_b) -> - Luminance_a = luminance(Colour_a) + 0.05, - Luminance_b = luminance(Colour_b) + 0.05, - case Luminance_a > Luminance_b of - true -> - case Luminance_b of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> Luminance_a / Gleam@denominator - end; - - false -> - case Luminance_a of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> Luminance_b / Gleam@denominator@1 - end - end. - --file("src/gleam_community/colour/accessibility.gleam", 161). -?DOC( - " Returns the `Colour` with the highest contrast between the base `Colour`,\n" - " and and the other provided `Colour` values.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " maximum_contrast(\n" - " colour.yellow,\n" - " [colour.white, colour.dark_blue, colour.green],\n" - " )\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec maximum_contrast( - gleam_community@colour:colour(), - list(gleam_community@colour:colour()) -) -> {ok, gleam_community@colour:colour()} | {error, nil}. -maximum_contrast(Base, Colours) -> - _pipe = Colours, - _pipe@1 = gleam@list:sort( - _pipe, - fun(Colour_a, Colour_b) -> - Contrast_a = contrast_ratio(Base, Colour_a), - Contrast_b = contrast_ratio(Base, Colour_b), - gleam@float:compare(Contrast_b, Contrast_a) - end - ), - gleam@list:first(_pipe@1). diff --git a/build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache b/build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache deleted file mode 100644 index a74dd80e3f3cf39c985b61a32ae1999cf41e886b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18027 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 U=FQ9u48~lnf}o~D4o5Ku0L()w3IG5A diff --git a/build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_inline b/build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_meta b/build/dev/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_meta deleted file mode 100644 index 00dd8197b7222766439b5ca90ee6c6f49f62c337..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1554 zcmYelot(h{1&ka}20xTe&q+;RFK%gCL5&;*z4wy!7~zqSVxr3=9mP85kIh zTV$246+h0gWrV6^U|<0G2jpy!vp^02Sp+f=q~{9*1H)Ga1_owE1_l;J1_o(H1_mQW z1_p0N28Ikq28PLu3=C5l85pK9GB7-4WMB|wVqlPDVqnl@Vqnl^VqmahVqnN)Vqj=s zVqoZCVqoZDVqlob#K3TziGkrc69dD0CI*JjOdtyw7!;Tp7*d%T7;>2z7z&vg80wiB z7^W~YFzjGvV7SK2!0?xuf#E+h0|NsK1A_ny1A{CJ1A`F@149@K149W51H)Vv28Nw1 z3=F$j7#Q}jFfd$TVPLq+!ocu}g@Hkgm4U&8m4P9fm4RUbD+9weRtAP0tPBi0Ss55U zu`)2|u`w{{voSE#vN14hVq;*~#>T*KjE#Ze6dMD>bv6bD5q1U!HFgFDJ$42LBX$M` zdv*qfGIj=rY3vLP^Vk^}7O^uhtY>FnxWUfAAjiSLpvJ+#pvA$!V9UY45W>O0P{F~# zFpYzO;UWhE!#55F1{qEU202a!26;{f247AFhAEs34BI&w818d2FmQ7*Fz|CRFbHxn zFbHumFj#RhFxYW1Fm!V1_ozt z28JAN28Kp%28L#C28I@H28LbS3=F@y85rbv7#QSv7#Mtb7#IS07#QaAFfcsfVPN>p z!@%&Lhk=2gmw`c;mw`cnmw_RGmw}<2mw}<4mw};~mw{m?F9X9bUIqp&J_ZJDJ_d#~ zJ_d#?J_d#=J_d$5J_d$vJ_d%hd<+cx_!tp%yz>p@$z>qG;z%WUWf#Iwm1H*Gc28I`c3=C{S z3=CXC3=C323=DEY3=G;r3=Hl<3=Dxn3=EM%3=FYC3=B;|3=C6*7#OArF)&OQVqiET z#K7=hh=D;}n1MkVFre^ z!VC;Mg&7!j3o|h65oTa`A3^zm>7;cI(FbIh;Fo=mUFsO+!FldP}Fqn%mFa(G(FqDWfFia6+V3;Guz;IfO zf#I?k1H*MO1_pj{1_l*z1_m{81_pI;28K{^28KRy28Pq(3=C()85ll_GcbG=XJBBJ zU|`^sU|K$3yspCkhVgA@Y;qZ9*! zo)iN^niK=WJShf-`BDrFuca6mM5P%RB&8V`G^H6Bbfp;>tfUzj`lJ~c)=D!lY?WqU m*eT7xa7>zk;g&Q5!)Iv*1|As(1_>Dkh71`7hAb$Cm3{!JuHx - new UnexpectedEndOfInput(); -export const DecodeError$isUnexpectedEndOfInput = (value) => - value instanceof UnexpectedEndOfInput; - -export class UnexpectedByte extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const DecodeError$UnexpectedByte = ($0) => new UnexpectedByte($0); -export const DecodeError$isUnexpectedByte = (value) => - value instanceof UnexpectedByte; -export const DecodeError$UnexpectedByte$0 = (value) => value[0]; - -export class UnexpectedSequence extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const DecodeError$UnexpectedSequence = ($0) => - new UnexpectedSequence($0); -export const DecodeError$isUnexpectedSequence = (value) => - value instanceof UnexpectedSequence; -export const DecodeError$UnexpectedSequence$0 = (value) => value[0]; - -export class UnableToDecode extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const DecodeError$UnableToDecode = ($0) => new UnableToDecode($0); -export const DecodeError$isUnableToDecode = (value) => - value instanceof UnableToDecode; -export const DecodeError$UnableToDecode$0 = (value) => value[0]; - -function do_parse(json, decoder) { - return $result.try$( - decode_string(json), - (dynamic_value) => { - let _pipe = $decode.run(dynamic_value, decoder); - return $result.map_error( - _pipe, - (var0) => { return new UnableToDecode(var0); }, - ); - }, - ); -} - -/** - * Decode a JSON string into dynamically typed data which can be decoded into - * typed data with the `gleam/dynamic` module. - * - * ## Examples - * - * ```gleam - * > parse("[1,2,3]", decode.list(of: decode.int)) - * Ok([1, 2, 3]) - * ``` - * - * ```gleam - * > parse("[", decode.list(of: decode.int)) - * Error(UnexpectedEndOfInput) - * ``` - * - * ```gleam - * > parse("1", decode.string) - * Error(UnableToDecode([decode.DecodeError("String", "Int", [])])) - * ``` - */ -export function parse(json, decoder) { - return do_parse(json, decoder); -} - -function decode_to_dynamic(json) { - let $ = $bit_array.to_string(json); - if ($ instanceof Ok) { - let string$1 = $[0]; - return decode_string(string$1); - } else { - return new Error(new UnexpectedByte("")); - } -} - -/** - * Decode a JSON bit string into dynamically typed data which can be decoded - * into typed data with the `gleam/dynamic` module. - * - * ## Examples - * - * ```gleam - * > parse_bits(<<"[1,2,3]">>, decode.list(of: decode.int)) - * Ok([1, 2, 3]) - * ``` - * - * ```gleam - * > parse_bits(<<"[">>, decode.list(of: decode.int)) - * Error(UnexpectedEndOfInput) - * ``` - * - * ```gleam - * > parse_bits(<<"1">>, decode.string) - * Error(UnableToDecode([decode.DecodeError("String", "Int", [])])), - * ``` - */ -export function parse_bits(json, decoder) { - return $result.try$( - decode_to_dynamic(json), - (dynamic_value) => { - let _pipe = $decode.run(dynamic_value, decoder); - return $result.map_error( - _pipe, - (var0) => { return new UnableToDecode(var0); }, - ); - }, - ); -} - -/** - * Convert a JSON value into a string. - * - * Where possible prefer the `to_string_tree` function as it is faster than - * this function, and BEAM VM IO is optimised for sending `StringTree` data. - * - * ## Examples - * - * ```gleam - * > to_string(array([1, 2, 3], of: int)) - * "[1,2,3]" - * ``` - */ -export function to_string(json) { - return do_to_string(json); -} - -/** - * Encode a string into JSON, using normal JSON escaping. - * - * ## Examples - * - * ```gleam - * > to_string(string("Hello!")) - * "\"Hello!\"" - * ``` - */ -export function string(input) { - return do_string(input); -} - -/** - * Encode a bool into JSON. - * - * ## Examples - * - * ```gleam - * > to_string(bool(False)) - * "false" - * ``` - */ -export function bool(input) { - return do_bool(input); -} - -/** - * Encode an int into JSON. - * - * ## Examples - * - * ```gleam - * > to_string(int(50)) - * "50" - * ``` - */ -export function int(input) { - return do_int(input); -} - -/** - * Encode a float into JSON. - * - * ## Examples - * - * ```gleam - * > to_string(float(4.7)) - * "4.7" - * ``` - */ -export function float(input) { - return do_float(input); -} - -/** - * The JSON value null. - * - * ## Examples - * - * ```gleam - * > to_string(null()) - * "null" - * ``` - */ -export function null$() { - return do_null(); -} - -/** - * Encode an optional value into JSON, using null if it is the `None` variant. - * - * ## Examples - * - * ```gleam - * > to_string(nullable(Some(50), of: int)) - * "50" - * ``` - * - * ```gleam - * > to_string(nullable(None, of: int)) - * "null" - * ``` - */ -export function nullable(input, inner_type) { - if (input instanceof Some) { - let value = input[0]; - return inner_type(value); - } else { - return null$(); - } -} - -/** - * Encode a list of key-value pairs into a JSON object. - * - * ## Examples - * - * ```gleam - * > to_string(object([ - * #("game", string("Pac-Man")), - * #("score", int(3333360)), - * ])) - * "{\"game\":\"Pac-Mac\",\"score\":3333360}" - * ``` - */ -export function object(entries) { - return do_object(entries); -} - -/** - * Encode a list of JSON values into a JSON array. - * - * ## Examples - * - * ```gleam - * > to_string(preprocessed_array([int(1), float(2.0), string("3")])) - * "[1, 2.0, \"3\"]" - * ``` - */ -export function preprocessed_array(from) { - return do_preprocessed_array(from); -} - -/** - * Encode a list into a JSON array. - * - * ## Examples - * - * ```gleam - * > to_string(array([1, 2, 3], of: int)) - * "[1, 2, 3]" - * ``` - */ -export function array(entries, inner_type) { - let _pipe = entries; - let _pipe$1 = $list.map(_pipe, inner_type); - return preprocessed_array(_pipe$1); -} - -/** - * Encode a Dict into a JSON object using the supplied functions to encode - * the keys and the values respectively. - * - * ## Examples - * - * ```gleam - * > to_string(dict(dict.from_list([ #(3, 3.0), #(4, 4.0)]), int.to_string, float) - * "{\"3\": 3.0, \"4\": 4.0}" - * ``` - */ -export function dict(dict, keys, values) { - return object( - $dict.fold( - dict, - toList([]), - (acc, k, v) => { return listPrepend([keys(k), values(v)], acc); }, - ), - ); -} diff --git a/build/dev/javascript/gleam_json/gleam@json.erl b/build/dev/javascript/gleam_json/gleam@json.erl deleted file mode 100644 index 8a33e49..0000000 --- a/build/dev/javascript/gleam_json/gleam@json.erl +++ /dev/null @@ -1,304 +0,0 @@ --module(gleam@json). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/json.gleam"). --export([parse_bits/2, parse/2, to_string/1, to_string_tree/1, string/1, bool/1, int/1, float/1, null/0, nullable/2, object/1, preprocessed_array/1, array/2, dict/3]). --export_type([json/0, decode_error/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type json() :: any(). - --type decode_error() :: unexpected_end_of_input | - {unexpected_byte, binary()} | - {unexpected_sequence, binary()} | - {unable_to_decode, list(gleam@dynamic@decode:decode_error())}. - --file("src/gleam/json.gleam", 88). -?DOC( - " Decode a JSON bit string into dynamically typed data which can be decoded\n" - " into typed data with the `gleam/dynamic` module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"[1,2,3]\">>, decode.list(of: decode.int))\n" - " Ok([1, 2, 3])\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"[\">>, decode.list(of: decode.int))\n" - " Error(UnexpectedEndOfInput)\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"1\">>, decode.string)\n" - " Error(UnableToDecode([decode.DecodeError(\"String\", \"Int\", [])])),\n" - " ```\n" -). --spec parse_bits(bitstring(), gleam@dynamic@decode:decoder(DNO)) -> {ok, DNO} | - {error, decode_error()}. -parse_bits(Json, Decoder) -> - gleam@result:'try'( - gleam_json_ffi:decode(Json), - fun(Dynamic_value) -> - _pipe = gleam@dynamic@decode:run(Dynamic_value, Decoder), - gleam@result:map_error( - _pipe, - fun(Field@0) -> {unable_to_decode, Field@0} end - ) - end - ). - --file("src/gleam/json.gleam", 47). --spec do_parse(binary(), gleam@dynamic@decode:decoder(DNI)) -> {ok, DNI} | - {error, decode_error()}. -do_parse(Json, Decoder) -> - Bits = gleam_stdlib:identity(Json), - parse_bits(Bits, Decoder). - --file("src/gleam/json.gleam", 39). -?DOC( - " Decode a JSON string into dynamically typed data which can be decoded into\n" - " typed data with the `gleam/dynamic` module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > parse(\"[1,2,3]\", decode.list(of: decode.int))\n" - " Ok([1, 2, 3])\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse(\"[\", decode.list(of: decode.int))\n" - " Error(UnexpectedEndOfInput)\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse(\"1\", decode.string)\n" - " Error(UnableToDecode([decode.DecodeError(\"String\", \"Int\", [])]))\n" - " ```\n" -). --spec parse(binary(), gleam@dynamic@decode:decoder(DNE)) -> {ok, DNE} | - {error, decode_error()}. -parse(Json, Decoder) -> - do_parse(Json, Decoder). - --file("src/gleam/json.gleam", 117). -?DOC( - " Convert a JSON value into a string.\n" - "\n" - " Where possible prefer the `to_string_tree` function as it is faster than\n" - " this function, and BEAM VM IO is optimised for sending `StringTree` data.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(array([1, 2, 3], of: int))\n" - " \"[1,2,3]\"\n" - " ```\n" -). --spec to_string(json()) -> binary(). -to_string(Json) -> - gleam_json_ffi:json_to_string(Json). - --file("src/gleam/json.gleam", 140). -?DOC( - " Convert a JSON value into a string tree.\n" - "\n" - " Where possible prefer this function to the `to_string` function as it is\n" - " slower than this function, and BEAM VM IO is optimised for sending\n" - " `StringTree` data.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string_tree(array([1, 2, 3], of: int))\n" - " string_tree.from_string(\"[1,2,3]\")\n" - " ```\n" -). --spec to_string_tree(json()) -> gleam@string_tree:string_tree(). -to_string_tree(Json) -> - gleam_json_ffi:json_to_iodata(Json). - --file("src/gleam/json.gleam", 151). -?DOC( - " Encode a string into JSON, using normal JSON escaping.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(string(\"Hello!\"))\n" - " \"\\\"Hello!\\\"\"\n" - " ```\n" -). --spec string(binary()) -> json(). -string(Input) -> - gleam_json_ffi:string(Input). - --file("src/gleam/json.gleam", 168). -?DOC( - " Encode a bool into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(bool(False))\n" - " \"false\"\n" - " ```\n" -). --spec bool(boolean()) -> json(). -bool(Input) -> - gleam_json_ffi:bool(Input). - --file("src/gleam/json.gleam", 185). -?DOC( - " Encode an int into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(int(50))\n" - " \"50\"\n" - " ```\n" -). --spec int(integer()) -> json(). -int(Input) -> - gleam_json_ffi:int(Input). - --file("src/gleam/json.gleam", 202). -?DOC( - " Encode a float into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(float(4.7))\n" - " \"4.7\"\n" - " ```\n" -). --spec float(float()) -> json(). -float(Input) -> - gleam_json_ffi:float(Input). - --file("src/gleam/json.gleam", 219). -?DOC( - " The JSON value null.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(null())\n" - " \"null\"\n" - " ```\n" -). --spec null() -> json(). -null() -> - gleam_json_ffi:null(). - --file("src/gleam/json.gleam", 241). -?DOC( - " Encode an optional value into JSON, using null if it is the `None` variant.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(nullable(Some(50), of: int))\n" - " \"50\"\n" - " ```\n" - "\n" - " ```gleam\n" - " > to_string(nullable(None, of: int))\n" - " \"null\"\n" - " ```\n" -). --spec nullable(gleam@option:option(DNU), fun((DNU) -> json())) -> json(). -nullable(Input, Inner_type) -> - case Input of - {some, Value} -> - Inner_type(Value); - - none -> - null() - end. - --file("src/gleam/json.gleam", 260). -?DOC( - " Encode a list of key-value pairs into a JSON object.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(object([\n" - " #(\"game\", string(\"Pac-Man\")),\n" - " #(\"score\", int(3333360)),\n" - " ]))\n" - " \"{\\\"game\\\":\\\"Pac-Mac\\\",\\\"score\\\":3333360}\"\n" - " ```\n" -). --spec object(list({binary(), json()})) -> json(). -object(Entries) -> - gleam_json_ffi:object(Entries). - --file("src/gleam/json.gleam", 292). -?DOC( - " Encode a list of JSON values into a JSON array.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(preprocessed_array([int(1), float(2.0), string(\"3\")]))\n" - " \"[1, 2.0, \\\"3\\\"]\"\n" - " ```\n" -). --spec preprocessed_array(list(json())) -> json(). -preprocessed_array(From) -> - gleam_json_ffi:array(From). - --file("src/gleam/json.gleam", 277). -?DOC( - " Encode a list into a JSON array.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(array([1, 2, 3], of: int))\n" - " \"[1, 2, 3]\"\n" - " ```\n" -). --spec array(list(DNY), fun((DNY) -> json())) -> json(). -array(Entries, Inner_type) -> - _pipe = Entries, - _pipe@1 = gleam@list:map(_pipe, Inner_type), - preprocessed_array(_pipe@1). - --file("src/gleam/json.gleam", 310). -?DOC( - " Encode a Dict into a JSON object using the supplied functions to encode\n" - " the keys and the values respectively.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(dict(dict.from_list([ #(3, 3.0), #(4, 4.0)]), int.to_string, float)\n" - " \"{\\\"3\\\": 3.0, \\\"4\\\": 4.0}\"\n" - " ```\n" -). --spec dict( - gleam@dict:dict(DOC, DOD), - fun((DOC) -> binary()), - fun((DOD) -> json()) -) -> json(). -dict(Dict, Keys, Values) -> - object( - gleam@dict:fold( - Dict, - [], - fun(Acc, K, V) -> [{Keys(K), Values(V)} | Acc] end - ) - ). diff --git a/build/dev/javascript/gleam_json/gleam_json_ffi.erl b/build/dev/javascript/gleam_json/gleam_json_ffi.erl deleted file mode 100644 index 06a26a0..0000000 --- a/build/dev/javascript/gleam_json/gleam_json_ffi.erl +++ /dev/null @@ -1,66 +0,0 @@ --module(gleam_json_ffi). - --export([ - decode/1, json_to_iodata/1, json_to_string/1, int/1, float/1, string/1, - bool/1, null/0, array/1, object/1 -]). - --if(?OTP_RELEASE < 27). --define(bad_version, - error({erlang_otp_27_required, << "Insufficient Erlang/OTP version. - -`gleam_json` uses the Erlang `json` module introduced in Erlang/OTP 27. -You are using Erlang/OTP "/utf8, (integer_to_binary(?OTP_RELEASE))/binary, " -Please upgrade your Erlang install or downgrade to `gleam_json` v1.0.1. -"/utf8>>})). - -decode(_) -> ?bad_version. -json_to_iodata(_) -> ?bad_version. -json_to_string(_) -> ?bad_version. -int(_) -> ?bad_version. -float(_) -> ?bad_version. -string(_) -> ?bad_version. -bool(_) -> ?bad_version. -array(_) -> ?bad_version. -object(_) -> ?bad_version. -null() -> ?bad_version. --else. - -decode(Json) -> - try - {ok, json:decode(Json)} - catch - error:unexpected_end -> {error, unexpected_end_of_input}; - error:{invalid_byte, Byte} -> {error, {unexpected_byte, hex(Byte)}}; - error:{unexpected_sequence, Byte} -> {error, {unexpected_sequence, Byte}} - end. - -hex(I) -> - H = list_to_binary(integer_to_list(I, 16)), - <<"0x"/utf8, H/binary>>. - -json_to_iodata(Json) -> - Json. - -json_to_string(Json) when is_binary(Json) -> - Json; -json_to_string(Json) when is_list(Json) -> - list_to_binary(Json). - -null() -> <<"null">>. -bool(true) -> <<"true">>; -bool(false) -> <<"false">>. -int(X) -> json:encode_integer(X). -float(X) -> json:encode_float(X). -string(X) -> json:encode_binary(X). - -array([]) -> <<"[]">>; -array([First | Rest]) -> [$[, First | array_loop(Rest)]. -array_loop([]) -> "]"; -array_loop([Elem | Rest]) -> [$,, Elem | array_loop(Rest)]. - -object(List) -> encode_object([[$,, string(Key), $: | Value] || {Key, Value} <- List]). -encode_object([]) -> <<"{}">>; -encode_object([[_Comma | Entry] | Rest]) -> ["{", Entry, Rest, "}"]. - --endif. diff --git a/build/dev/javascript/gleam_json/gleam_json_ffi.mjs b/build/dev/javascript/gleam_json/gleam_json_ffi.mjs deleted file mode 100644 index 1d8d3ff..0000000 --- a/build/dev/javascript/gleam_json/gleam_json_ffi.mjs +++ /dev/null @@ -1,201 +0,0 @@ -import { - Result$Ok, - Result$Error, - List$isNonEmpty, - List$NonEmpty$first, - List$NonEmpty$rest, -} from "./gleam.mjs"; -import { - DecodeError$UnexpectedByte, - DecodeError$UnexpectedEndOfInput, -} from "./gleam/json.mjs"; - -export function json_to_string(json) { - return JSON.stringify(json); -} - -export function object(entries) { - return Object.fromEntries(entries); -} - -export function identity(x) { - return x; -} - -export function array(list) { - const array = []; - while (List$isNonEmpty(list)) { - array.push(List$NonEmpty$first(list)); - list = List$NonEmpty$rest(list); - } - return array; -} - -export function do_null() { - return null; -} - -export function decode(string) { - try { - const result = JSON.parse(string); - return Result$Ok(result); - } catch (err) { - return Result$Error(getJsonDecodeError(err, string)); - } -} - -export function getJsonDecodeError(stdErr, json) { - if (isUnexpectedEndOfInput(stdErr)) return DecodeError$UnexpectedEndOfInput(); - return toUnexpectedByteError(stdErr, json); -} - -/** - * Matches unexpected end of input messages in: - * - Chromium (edge, chrome, node) - * - Spidermonkey (firefox) - * - JavascriptCore (safari) - * - * Note that Spidermonkey and JavascriptCore will both incorrectly report some - * UnexpectedByte errors as UnexpectedEndOfInput errors. For example: - * - * @example - * // in JavascriptCore - * JSON.parse('{"a"]: "b"}) - * // => JSON Parse error: Expected ':' before value - * - * JSON.parse('{"a"') - * // => JSON Parse error: Expected ':' before value - * - * // in Chromium (correct) - * JSON.parse('{"a"]: "b"}) - * // => Unexpected token ] in JSON at position 4 - * - * JSON.parse('{"a"') - * // => Unexpected end of JSON input - */ -function isUnexpectedEndOfInput(err) { - const unexpectedEndOfInputRegex = - /((unexpected (end|eof))|(end of data)|(unterminated string)|(json( parse error|\.parse)\: expected '(\:|\}|\])'))/i; - return unexpectedEndOfInputRegex.test(err.message); -} - -/** - * Converts a SyntaxError to an UnexpectedByte error based on the JS runtime. - * - * For Chromium, the unexpected byte and position are reported by the runtime. - * - * For JavascriptCore, only the unexpected byte is reported by the runtime, so - * there is no way to know which position that character is in unless we then - * parse the string again ourselves. So instead, the position is reported as 0. - * - * For Spidermonkey, the position is reported by the runtime as a line and column number - * and the unexpected byte is found using those coordinates. - */ -function toUnexpectedByteError(err, json) { - let converters = [ - v8UnexpectedByteError, - oldV8UnexpectedByteError, - jsCoreUnexpectedByteError, - spidermonkeyUnexpectedByteError, - ]; - - for (let converter of converters) { - let result = converter(err, json); - if (result) return result; - } - - return DecodeError$UnexpectedByte(""); -} - -/** - * Matches unexpected byte messages in: - * - V8 (edge, chrome, node) - * - * Matches the character but not the position as this is no longer reported by - * V8. Boo! - */ -function v8UnexpectedByteError(err) { - const regex = /unexpected token '(.)', ".+" is not valid JSON/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[1]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - V8 (edge, chrome, node) - * - * No longer works in current versions of V8. - * - * Matches the character and its position. - */ -function oldV8UnexpectedByteError(err) { - const regex = /unexpected token (.) in JSON at position (\d+)/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[1]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - Spidermonkey (firefox) - * - * Matches the position in a 2d grid only and not the character. - */ -function spidermonkeyUnexpectedByteError(err, json) { - const regex = - /(unexpected character|expected .*) at line (\d+) column (\d+)/i; - const match = regex.exec(err.message); - if (!match) return null; - const line = Number(match[2]); - const column = Number(match[3]); - const position = getPositionFromMultiline(line, column, json); - const byte = toHex(json[position]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - JavascriptCore (safari) - * - * JavascriptCore only reports what the character is and not its position. - */ -function jsCoreUnexpectedByteError(err) { - const regex = /unexpected (identifier|token) "(.)"/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[2]); - return DecodeError$UnexpectedByte(byte); -} - -function toHex(char) { - return "0x" + char.charCodeAt(0).toString(16).toUpperCase(); -} - -/** - * Gets the position of a character in a flattened (i.e. single line) string - * from a line and column number. Note that the position is 0-indexed and - * the line and column numbers are 1-indexed. - * - * @param {number} line - * @param {number} column - * @param {string} string - */ -function getPositionFromMultiline(line, column, string) { - if (line === 1) return column - 1; - - let currentLn = 1; - let position = 0; - string.split("").find((char, idx) => { - if (char === "\n") currentLn += 1; - if (currentLn === line) { - position = idx + column; - return true; - } - return false; - }); - - return position; -} diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache deleted file mode 100644 index 8c670b6729e63e5dc30192281d78c662a06b72b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14783 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 MoPj|Liecp;0H3<9g#Z8m diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache deleted file mode 100644 index e7446ce83176b2b4ed94233be680c2529c5ff8f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13269 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 F3jp3Gk_!L; diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta deleted file mode 100644 index b00ed3338f56deed1bd8698003758ebf8df5b566..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 903 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache deleted file mode 100644 index bbe4a320d77b4b6a94f000fa42127c24c64c9fa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7137 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta deleted file mode 100644 index 604414bb9ff7d49e8007dc12be5b85abcc9e8382..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2724 zcmZ3jurQqg3K$uo3~nf$o|BrGtDj$#l3EnV%D_;-%D`|zaMGP8n}2Sf#spQvz`&rv zz`&r(z`)?ez`)?oz`!t{fq~&I0|SE{BLhPyBLhPeBLhPTBLhPvBLl;JMg|6cCI*H$ zCI*IVCI*HACI*H*ObiU)nHU)UFflNQGBYqpF*7h^Ff%ahU}j)oXJKH7WMN>K!NR~W zmxY1h4GRN)gCG|JgD4jRgEAKb zLq8V-!#OSnhD%%w46NJ?45Hi&3|ia_4CdSn4Bp%f3@O|U40YTL3~k&D3|-s|3_aWo z487b83>QIac^DWZc^DXico-P=^Drg9p408k+7*-1~Fl-iJVAw9ez;Hx>f#HV$0|SR31A~Ad z1A~Yl1B1381B1CB1A~Vk14FtX14FSO1H)WF28JDi3=F#j85nj8GBErQWMKFs$iToO z#K0gR#K0gc#K530#K2%H#K7Px#K7Pw#K2H2#K6!j#K167h=E~&5Cg*!AqIwJLJSPc zg%}tf3o$S}7h+)eF2um_TZn;yLzsa+IVutEhF2mC48KGe82*VcFmQ`9Fi43qFldM}Fc^q3Fqnuk zFocUTF!YKtFsv12U|1*0!0<+tf#HKF0|SE?0|Sc~1B0L#1A~GX1A~qj1A~be1A~Pa z1B0s=14D=y14Dus14D)w14E7&1H(iy28NAd3=Bua7#Qw|F)%QSGcd4TRv5TnSzkf6xGkfg}KkgUkS z(4xq|uuGAF;jtnE!xKdY25BV*26-h027M(424f`#1_vbuhEOF2hIAzchI}OkhGHcK zh6W`DhUrQS3~Q7a7`7-eFzirbV0f#Xet1>X;s4_5gsxmOlP-S3Ppvu6oM3sTz ziYf!cM^y%f&#DXzUsM?wOw|||+|(Etn$#E=rl>J6%ur)sn5D+RFk6j*;jtP6!xuFM zh97DS4EE{_47KVE42|jx3=`EE7^bQ-Ff3AMU|6rtz;Ifff#I?`1H*N728KWC3=Gy9 z3=AO}3=E+f3=Fe17#QYjFfhE;U|^8YWMGidWMI(IWMDARWMHt>WMBx_WMIhDWMC-N zWMC-OWMF90WMG)9$-uB)lYwEoCIiE6O$LS&nhXq&H5nMbX)-YU(_~;^(qdrX*J5DM z)?#3=(_&z7(_&!o(qdqkqQ$_lREvROw-y7#FD(X!e_9L-4B89~jM@wg#@Y-F=GqJl z?%E6t-r5Wd5!wt4x!Md2_1X*!?b-|s-P#NcGqf2P)@m~_9MWcBIHk?Na88?nfm?@x zK}?5%K}Uyy!9jFzD(sFc|7GFxcrbFoftbFhuAwFf{5iF!bv(Fih8FV3@7Tz_3D> zfnkp>1H&m@28K(z3=G#m4GBF422MQ&25vnD1|B^I1_M0?1`|C7hHO0shShou4D0n6 z820NiFdWunV7Q>i!0=p;f#Itj1H)fE1_nlb1_nNT1_l*<1_lj%28J+w28L9928LXH z28Kd?28KF)28QYS3=B*485q{;Gcat_XJB}s&%p3fpMl}EJ_ExWeFg?00|o{$0|o|P z0|tg(0|thP1`G@f4Hy`f8Za_;4+abjY=#UBT!st` zmWB)r?uHBu{)P+;!G;VB35E;|HHHifU4{${lMERcrWrCYEH-3d*l) z!!1Jw22LXe1|cH`1`#6$22mphhGZiKhWSPe42z8z7&aR*Fl;wsU^rsLz;NA&f#IbQ z1H(rn28ORj3=B-h3=Epa3=G!B3=Gc33=HnZ3=AR03=HYU3=B2K3=A#C3=AE{3=C6^ z85mX?GcfEkW?(pG%)oHUn1SK1F$05?2?Il-2?N7&69$GiCJYRMrVI=!rVI?$rVI>W zrVI>GrVI=*rVI?RrVI>qrVI?5Oc@x?n=&w5FlAtnHDh4VF=JpbFk@hFFk@hFF=Jo| zG-F^$Gh<+=Fk@h7Fk@h7F=JquXvV;>%#4BIm>C1ZIWq=^OJ)oV_stj>zM3&Gh?_Go a$eS}TD4R1dxR^6ARG2d`%!6WB3ljh{EuIYk diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache deleted file mode 100644 index 466438342bfdd97a6c00ac69c583c60c8c92a48c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta deleted file mode 100644 index 87308288f7d793cd31810581b01ed45406ec23a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3419 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache deleted file mode 100644 index fb831f1c97ecd3a5ca63a15030e9c25af49518b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2697 zcmXq*%M`%K!@wY@>m``VE|}^r%*)O$sG23r$!;F(z`@95sJMwq_y7l!@KFwS;e#A( z&IdS{|EK4qCg$pA<})xbK-lrcB@Fy2IhjfS^+StOi;DF#I7`#>bM*^Si;DB}5_3{g z%k+y&Qgd<=i{cB4O7l|nlS(slQuGTFld}`kQ;YS%CdL<+fXvV@E=q<7=x65Z$%CaF zm>dO|1Z9&P6QYvgN5aPK~ZL2NqlM%1A9?^QJ@49 zTi^yp&Oi=EMnOg{1|~*E1_nV<_rL%qHU{QE7A7_ZMnO?4K~WEXO3`E%?LEfbQdU}v} zW`xGP9(!(9F={|DFdFY>y352UCl5AcAfnYM@B|~HpsbhR2}VQNPppDR7y~O983QLU zG79D}LYxKhFj{nqVU12`T!G>`CJl9`vTkf@NCS`N;4CHV>^ z8L0}Xc`4Yk8(Jj6vL-mP@a8&<$SQ)k8y;Ec;SP_sBJ9!jKRG|II6o&97EcU}#u2PF ztc-H?;GCC}HxLo$6u1YH_x3Ov%AR5o+`$-_!3Zu^1!EXt4ug1{s0c&LeN>4ta9rWd zSm1ocz<^XlIzikFk1Uv1;E{x@aD+z^drp2j1EVo3i!uwNoCA|150jv%QlJPUlc1$m zpamn7V5wDL2_qAzrea_aWR(|WWOig>7UWbCFbj%m z2}*)1L{TFMgFmFGG?jtDfmz-yF{c>JvJXlvF3l-nU=ZXq7i1J>VRQs(loFJb2i2sW zMuNWbg05W5{@Dx+jx5Z9987G2s$7DqT#QT%9P+N9`V2#Yk&%I&xrNn`^$DY3CA)y3 zplO|8(?r3kiv)Kb7rc7c@F5SVJV|3TPG_9XXgr(o6{GPx#=nflj7*$N#%fF^OvX-3 zUQEV*O!Z90yP2Lc89!q(XEwHG_F^{nV~%DvE@5tBHlDydgV}fv^GRl7Ru*j*V;zAP1uW zBO|l%A*QoT$O<9lCXxbAMn6Vm1?V{%NohQ54lA-!Sb9QI!owoW0*)smaD&EOFw{se z)Jiba9nz2iB?wR(OMy{Pf>98IWMni>VoYUZWHf%r^n{6#(O8{Di-nQVxPi5q6=DFi c>4e{maK>1W8P}NZfXt9#Q39D!%393|02%+KVgLXD diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta deleted file mode 100644 index b6b04350eee83b04238efb73438189a9e3a25d74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 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�DLHfBA3i6AKGm~;s6*BV_it}?*74l0m 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta deleted file mode 100644 index 8656c26a6732c744d9a78b34c76394e55653d6eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1485 zcmX?Lp`F111&mOd;q%=y(iLw$97u3wem>C!fm>C#Km>C#4nHd-+ zGcz#EVrF2N!_2@imzja#8Z!ffF$)7j3JU{61`7j21q%a14GRN9Ckq3^QWge=JuD0i zM_3pbPOvaATxDTkc*nxP@Rx;wft8hkfs>Vi!GV>5A(WMYA)J+gA%c~GVIC_3!x~lw zhLfxe3=dct7-ZNO7!=qT7?ju;7?jx<7z)`K7^bo@FzjYyV0gsFz`(@Lz`(-Jz`)AR zz!1#Nz>v(&z)-@@z;KA2f#DcC1H%b+28NUD3=DtR85kHi7#IXN7#Ku27#I{e7#Per z7#LhR7#Msx7#IRM7#QL>7#IpT7#JEj7#KP@7#Mmu7#MbNFfg3tU|=}S!N72agMr~c z2Ll5$Cj)~pCj)~xCj)~DCj)~eCj)~gCj&zuCj&z$Cj&zgCj&zXCj&z>Cj&z_Cj&!2 zCj-N7P6mcEoD2--I2jnub22b6axpNlaxpN7axpMSaxpNdaWOD>b1^VPb1^U^b1^Wa zb1^WKa4|4U<6>ag!o|R_hl_#X02c$pPc8-qPHqMUIc^39V{Qfpb8ZF(OKt`RD{cmc z9Bu}N0&WI|25tt17H$THiQEhfE4UdLc5yQ>9O7nRIL6JuaG9Hd;RiPZ13M1`13wP~ zgD?*RgEtQYLo^QqLjey1Ln{vhLnjXdLpKitLk|xF!$TehhNnCX3}1N|7=H3FFtG75 zFv#*UFlh2JFc|VOFqrZ(FgWotFof|kFeLFZFl6yEFy!$vFf8R|VA#sbz;KM0f#DV} z1H(OD28IW`3=9u>85o@T7#Q677#PC&7#O1Y7#K467#Mo_7#L>qF)%FTV_;ay$H1_O zkAdL|9|OY!J_d#td<+b4_!t-r_!$@+_!$@i`573}`573p`572;`574U_!$_E@G~%+ z=VxHJ%+J7}CBVSoF2KOxEx^DKEx^DKFTlW%Bf!8gOMro4jQ|6~76Ar^9RdstM+F!d zJ_s-{{1;$gU>9Uy;1*|f&Fh!7oVVWQV!*oFghLeH}3}*!y z814!(Fgz4wV0b6Uz`!ZQz#uKez@RL|z@RR~z+fW8z~Cdqzz{9Oz>qA&z>qG)z)&K@ zz|bbdz%W&afnlx?1H(cg28LTg3=FS?7#MyFF);85GcX7UGcX7VGcX7XGcaTdGcfEH zW?*U;)h%zwT6lGxeEy}>aCC0!YB*wrXCdR;^ zEXKg#DaODMA;!RvAjZIuBF4b5QH+7%pcn(gbuk8p7h((yZ^RfF-ia|Vycc6&a1du; za1m!<2oYysh!AIBNEK&bs1s*km>|x;FhiVyVU9Qh!%A@mhW+9U3>U>27;cI)Fx(Yq zV0b0Yz`!8Ez#t^Sz#t{Tz#u2Vz@RO`z+flAz~C#vzz{0Izz`|Hz%X5cfnk{h1H*0! z28MGI3=Eef7#OZdFfd$|U|_J9WMFWXWMBxEWMBxFWMD{Qj^33%B diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache deleted file mode 100644 index ad64dbc455d155e0b9e23d18e9cd296f2200f899..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5915 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta deleted file mode 100644 index 4404517ca4be50751de9a68d9658ab34e27040a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_inline deleted file mode 100644 index 3d06590585e32906712f8c5273a50463af96e4b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3168 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 X9H7MoXuA}8W@ZwU0C~@Z$$|+0|LW{@ diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta deleted file mode 100644 index e5bd75e58b0eb4da8415e982f4799788bdd6d70d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1761 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 VqHWXM}5vD*(91sxtrp diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta deleted file mode 100644 index 09ee85c7a6bdebe1a73eed8f2ae2ab57dd95a16b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4057 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache deleted file mode 100644 index 93d3cc108ad346f287a237b00ebf3854763118c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14554 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 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_inline b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta deleted file mode 100644 index abfcf6a5e95e84863043c38a0ea00a48f1cb0d89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 911 zcmZ>AiAZOF0!BtCg9}Qh=cFd)>gQw@mw*HW85kJ;FfDzl{qG&~MUVg#3o$S-2s1D+ z#4|83tYu(e_{PA%;KInjFo}_Y;W{G&!)-Vw?;NQk)D7rko56mYfU>>6{D<^Eeq8E^{(4T;XJ3_|M6} zz|6(KAjiePpv1+%5WvO2(863NSE;2rw{c3NSEO z3otPF3NSGE3otMQ2rw{o2{1716<}c4C&0jPUVwq&ssIDSbpZy38v+ar(t->O@`4Nu zp@Iwy^8^_f_6agD91vt+I4H=#@Jx__L0^c0!9a+Cp+bm(p+<;-VS^9@!+RkHhW|ng z3}V6z40^&044%Ra43WYN3{k=i42y*s7&ZtqFl-TKU|<$uUVhjvB#TXd&iZL*p5@TR^Eylp`ON@bmNt}U!O`L&2Pn>}vN}PeAM4W-4 J42l_`004g+d!_&Y diff --git a/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache b/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache deleted file mode 100644 index f51ee88b699a73add287667f1ba0dd898f806f30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32735 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 2))) | 0; -} - -/** - * standard string hash popularised by java - * @param {string} s - * @returns {number} - */ -function hashString(s) { - let hash = 0; - const len = s.length; - for (let i = 0; i < len; i++) { - hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0; - } - return hash; -} - -/** - * hash a number by converting to two integers and do some jumbling - * @param {number} n - * @returns {number} - */ -function hashNumber(n) { - tempDataView.setFloat64(0, n); - const i = tempDataView.getInt32(0); - const j = tempDataView.getInt32(4); - return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j; -} - -/** - * hash a BigInt by converting it to a string and hashing that - * @param {BigInt} n - * @returns {number} - */ -function hashBigInt(n) { - return hashString(n.toString()); -} - -/** - * hash any js object - * @param {any} o - * @returns {number} - */ -function hashObject(o) { - const proto = Object.getPrototypeOf(o); - if (proto !== null && typeof proto.hashCode === "function") { - try { - const code = o.hashCode(o); - if (typeof code === "number") { - return code; - } - } catch {} - } - if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { - return hashByReference(o); - } - if (o instanceof Date) { - return hashNumber(o.getTime()); - } - let h = 0; - if (o instanceof ArrayBuffer) { - o = new Uint8Array(o); - } - if (Array.isArray(o) || o instanceof Uint8Array) { - for (let i = 0; i < o.length; i++) { - h = (Math.imul(31, h) + getHash(o[i])) | 0; - } - } else if (o instanceof Set) { - o.forEach((v) => { - h = (h + getHash(v)) | 0; - }); - } else if (o instanceof Map) { - o.forEach((v, k) => { - h = (h + hashMerge(getHash(v), getHash(k))) | 0; - }); - } else { - const keys = Object.keys(o); - for (let i = 0; i < keys.length; i++) { - const k = keys[i]; - const v = o[k]; - h = (h + hashMerge(getHash(v), hashString(k))) | 0; - } - } - return h; -} - -/** - * hash any js value - * @param {any} u - * @returns {number} - */ -export function getHash(u) { - if (u === null) return 0x42108422; - if (u === undefined) return 0x42108423; - if (u === true) return 0x42108421; - if (u === false) return 0x42108420; - switch (typeof u) { - case "number": - return hashNumber(u); - case "string": - return hashString(u); - case "bigint": - return hashBigInt(u); - case "object": - return hashObject(u); - case "symbol": - return hashByReference(u); - case "function": - return hashByReference(u); - default: - return 0; // should be unreachable - } -} - -/** - * @template K,V - * @typedef {ArrayNode | IndexNode | CollisionNode} Node - */ -/** - * @template K,V - * @typedef {{ type: typeof ENTRY, k: K, v: V }} Entry - */ -/** - * @template K,V - * @typedef {{ type: typeof ARRAY_NODE, size: number, array: (undefined | Entry | Node)[] }} ArrayNode - */ -/** - * @template K,V - * @typedef {{ type: typeof INDEX_NODE, bitmap: number, array: (Entry | Node)[] }} IndexNode - */ -/** - * @template K,V - * @typedef {{ type: typeof COLLISION_NODE, hash: number, array: Entry[] }} CollisionNode - */ -/** - * @typedef {{ val: boolean }} Flag - */ -const SHIFT = 5; // number of bits you need to shift by to get the next bucket -const BUCKET_SIZE = Math.pow(2, SHIFT); -const MASK = BUCKET_SIZE - 1; // used to zero out all bits not in the bucket -const MAX_INDEX_NODE = BUCKET_SIZE / 2; // when does index node grow into array node -const MIN_ARRAY_NODE = BUCKET_SIZE / 4; // when does array node shrink to index node -const ENTRY = 0; -const ARRAY_NODE = 1; -const INDEX_NODE = 2; -const COLLISION_NODE = 3; - -/** @type {IndexNode} */ -const EMPTY = { - type: INDEX_NODE, - bitmap: 0, - array: [], -}; -/** - * Mask the hash to get only the bucket corresponding to shift - * @param {number} hash - * @param {number} shift - * @returns {number} - */ -function mask(hash, shift) { - return (hash >>> shift) & MASK; -} - -/** - * Set only the Nth bit where N is the masked hash - * @param {number} hash - * @param {number} shift - * @returns {number} - */ -function bitpos(hash, shift) { - return 1 << mask(hash, shift); -} - -/** - * Count the number of 1 bits in a number - * @param {number} x - * @returns {number} - */ -function bitcount(x) { - x -= (x >> 1) & 0x55555555; - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0f0f0f0f; - x += x >> 8; - x += x >> 16; - return x & 0x7f; -} - -/** - * Calculate the array index of an item in a bitmap index node - * @param {number} bitmap - * @param {number} bit - * @returns {number} - */ -function index(bitmap, bit) { - return bitcount(bitmap & (bit - 1)); -} - -/** - * Efficiently copy an array and set one value at an index - * @template T - * @param {T[]} arr - * @param {number} at - * @param {T} val - * @returns {T[]} - */ -function cloneAndSet(arr, at, val) { - const len = arr.length; - const out = new Array(len); - for (let i = 0; i < len; ++i) { - out[i] = arr[i]; - } - out[at] = val; - return out; -} - -/** - * Efficiently copy an array and insert one value at an index - * @template T - * @param {T[]} arr - * @param {number} at - * @param {T} val - * @returns {T[]} - */ -function spliceIn(arr, at, val) { - const len = arr.length; - const out = new Array(len + 1); - let i = 0; - let g = 0; - while (i < at) { - out[g++] = arr[i++]; - } - out[g++] = val; - while (i < len) { - out[g++] = arr[i++]; - } - return out; -} - -/** - * Efficiently copy an array and remove one value at an index - * @template T - * @param {T[]} arr - * @param {number} at - * @returns {T[]} - */ -function spliceOut(arr, at) { - const len = arr.length; - const out = new Array(len - 1); - let i = 0; - let g = 0; - while (i < at) { - out[g++] = arr[i++]; - } - ++i; - while (i < len) { - out[g++] = arr[i++]; - } - return out; -} - -/** - * Create a new node containing two entries - * @template K,V - * @param {number} shift - * @param {K} key1 - * @param {V} val1 - * @param {number} key2hash - * @param {K} key2 - * @param {V} val2 - * @returns {Node} - */ -function createNode(shift, key1, val1, key2hash, key2, val2) { - const key1hash = getHash(key1); - if (key1hash === key2hash) { - return { - type: COLLISION_NODE, - hash: key1hash, - array: [ - { type: ENTRY, k: key1, v: val1 }, - { type: ENTRY, k: key2, v: val2 }, - ], - }; - } - const addedLeaf = { val: false }; - return assoc( - assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf), - shift, - key2hash, - key2, - val2, - addedLeaf, - ); -} - -/** - * @template T,K,V - * @callback AssocFunction - * @param {T} root - * @param {number} shift - * @param {number} hash - * @param {K} key - * @param {V} val - * @param {Flag} addedLeaf - * @returns {Node} - */ -/** - * Associate a node with a new entry, creating a new node - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assoc(root, shift, hash, key, val, addedLeaf) { - switch (root.type) { - case ARRAY_NODE: - return assocArray(root, shift, hash, key, val, addedLeaf); - case INDEX_NODE: - return assocIndex(root, shift, hash, key, val, addedLeaf); - case COLLISION_NODE: - return assocCollision(root, shift, hash, key, val, addedLeaf); - } -} -/** - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assocArray(root, shift, hash, key, val, addedLeaf) { - const idx = mask(hash, shift); - const node = root.array[idx]; - // if the corresponding index is empty set the index to a newly created node - if (node === undefined) { - addedLeaf.val = true; - return { - type: ARRAY_NODE, - size: root.size + 1, - array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), - }; - } - if (node.type === ENTRY) { - // if keys are equal replace the entry - if (isEqual(key, node.k)) { - if (val === node.v) { - return root; - } - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet(root.array, idx, { - type: ENTRY, - k: key, - v: val, - }), - }; - } - // otherwise upgrade the entry to a node and insert - addedLeaf.val = true; - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet( - root.array, - idx, - createNode(shift + SHIFT, node.k, node.v, hash, key, val), - ), - }; - } - // otherwise call assoc on the child node - const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); - // if the child node hasn't changed just return the old root - if (n === node) { - return root; - } - // otherwise set the index to the new node - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet(root.array, idx, n), - }; -} -/** - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assocIndex(root, shift, hash, key, val, addedLeaf) { - const bit = bitpos(hash, shift); - const idx = index(root.bitmap, bit); - // if there is already a item at this hash index.. - if ((root.bitmap & bit) !== 0) { - // if there is a node at the index (not an entry), call assoc on the child node - const node = root.array[idx]; - if (node.type !== ENTRY) { - const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); - if (n === node) { - return root; - } - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet(root.array, idx, n), - }; - } - // otherwise there is an entry at the index - // if the keys are equal replace the entry with the updated value - const nodeKey = node.k; - if (isEqual(key, nodeKey)) { - if (val === node.v) { - return root; - } - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet(root.array, idx, { - type: ENTRY, - k: key, - v: val, - }), - }; - } - // if the keys are not equal, replace the entry with a new child node - addedLeaf.val = true; - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet( - root.array, - idx, - createNode(shift + SHIFT, nodeKey, node.v, hash, key, val), - ), - }; - } else { - // else there is currently no item at the hash index - const n = root.array.length; - // if the number of nodes is at the maximum, expand this node into an array node - if (n >= MAX_INDEX_NODE) { - // create a 32 length array for the new array node (one for each bit in the hash) - const nodes = new Array(32); - // create and insert a node for the new entry - const jdx = mask(hash, shift); - nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf); - let j = 0; - let bitmap = root.bitmap; - // place each item in the index node into the correct spot in the array node - // loop through all 32 bits / array positions - for (let i = 0; i < 32; i++) { - if ((bitmap & 1) !== 0) { - const node = root.array[j++]; - nodes[i] = node; - } - // shift the bitmap to process the next bit - bitmap = bitmap >>> 1; - } - return { - type: ARRAY_NODE, - size: n + 1, - array: nodes, - }; - } else { - // else there is still space in this index node - // simply insert a new entry at the hash index - const newArray = spliceIn(root.array, idx, { - type: ENTRY, - k: key, - v: val, - }); - addedLeaf.val = true; - return { - type: INDEX_NODE, - bitmap: root.bitmap | bit, - array: newArray, - }; - } - } -} -/** - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assocCollision(root, shift, hash, key, val, addedLeaf) { - // if there is a hash collision - if (hash === root.hash) { - const idx = collisionIndexOf(root, key); - // if this key already exists replace the entry with the new value - if (idx !== -1) { - const entry = root.array[idx]; - if (entry.v === val) { - return root; - } - return { - type: COLLISION_NODE, - hash: hash, - array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), - }; - } - // otherwise insert the entry at the end of the array - const size = root.array.length; - addedLeaf.val = true; - return { - type: COLLISION_NODE, - hash: hash, - array: cloneAndSet(root.array, size, { type: ENTRY, k: key, v: val }), - }; - } - // if there is no hash collision, upgrade to an index node - return assoc( - { - type: INDEX_NODE, - bitmap: bitpos(root.hash, shift), - array: [root], - }, - shift, - hash, - key, - val, - addedLeaf, - ); -} -/** - * Find the index of a key in the collision node's array - * @template K,V - * @param {CollisionNode} root - * @param {K} key - * @returns {number} - */ -function collisionIndexOf(root, key) { - const size = root.array.length; - for (let i = 0; i < size; i++) { - if (isEqual(key, root.array[i].k)) { - return i; - } - } - return -1; -} -/** - * @template T,K,V - * @callback FindFunction - * @param {T} root - * @param {number} shift - * @param {number} hash - * @param {K} key - * @returns {undefined | Entry} - */ -/** - * Return the found entry or undefined if not present in the root - * @template K,V - * @type {FindFunction,K,V>} - */ -function find(root, shift, hash, key) { - switch (root.type) { - case ARRAY_NODE: - return findArray(root, shift, hash, key); - case INDEX_NODE: - return findIndex(root, shift, hash, key); - case COLLISION_NODE: - return findCollision(root, key); - } -} -/** - * @template K,V - * @type {FindFunction,K,V>} - */ -function findArray(root, shift, hash, key) { - const idx = mask(hash, shift); - const node = root.array[idx]; - if (node === undefined) { - return undefined; - } - if (node.type !== ENTRY) { - return find(node, shift + SHIFT, hash, key); - } - if (isEqual(key, node.k)) { - return node; - } - return undefined; -} -/** - * @template K,V - * @type {FindFunction,K,V>} - */ -function findIndex(root, shift, hash, key) { - const bit = bitpos(hash, shift); - if ((root.bitmap & bit) === 0) { - return undefined; - } - const idx = index(root.bitmap, bit); - const node = root.array[idx]; - if (node.type !== ENTRY) { - return find(node, shift + SHIFT, hash, key); - } - if (isEqual(key, node.k)) { - return node; - } - return undefined; -} -/** - * @template K,V - * @param {CollisionNode} root - * @param {K} key - * @returns {undefined | Entry} - */ -function findCollision(root, key) { - const idx = collisionIndexOf(root, key); - if (idx < 0) { - return undefined; - } - return root.array[idx]; -} -/** - * @template T,K,V - * @callback WithoutFunction - * @param {T} root - * @param {number} shift - * @param {number} hash - * @param {K} key - * @returns {undefined | Node} - */ -/** - * Remove an entry from the root, returning the updated root. - * Returns undefined if the node should be removed from the parent. - * @template K,V - * @type {WithoutFunction,K,V>} - * */ -function without(root, shift, hash, key) { - switch (root.type) { - case ARRAY_NODE: - return withoutArray(root, shift, hash, key); - case INDEX_NODE: - return withoutIndex(root, shift, hash, key); - case COLLISION_NODE: - return withoutCollision(root, key); - } -} -/** - * @template K,V - * @type {WithoutFunction,K,V>} - */ -function withoutArray(root, shift, hash, key) { - const idx = mask(hash, shift); - const node = root.array[idx]; - if (node === undefined) { - return root; // already empty - } - let n = undefined; - // if node is an entry and the keys are not equal there is nothing to remove - // if node is not an entry do a recursive call - if (node.type === ENTRY) { - if (!isEqual(node.k, key)) { - return root; // no changes - } - } else { - n = without(node, shift + SHIFT, hash, key); - if (n === node) { - return root; // no changes - } - } - // if the recursive call returned undefined the node should be removed - if (n === undefined) { - // if the number of child nodes is at the minimum, pack into an index node - if (root.size <= MIN_ARRAY_NODE) { - const arr = root.array; - const out = new Array(root.size - 1); - let i = 0; - let j = 0; - let bitmap = 0; - while (i < idx) { - const nv = arr[i]; - if (nv !== undefined) { - out[j] = nv; - bitmap |= 1 << i; - ++j; - } - ++i; - } - ++i; // skip copying the removed node - while (i < arr.length) { - const nv = arr[i]; - if (nv !== undefined) { - out[j] = nv; - bitmap |= 1 << i; - ++j; - } - ++i; - } - return { - type: INDEX_NODE, - bitmap: bitmap, - array: out, - }; - } - return { - type: ARRAY_NODE, - size: root.size - 1, - array: cloneAndSet(root.array, idx, n), - }; - } - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet(root.array, idx, n), - }; -} -/** - * @template K,V - * @type {WithoutFunction,K,V>} - */ -function withoutIndex(root, shift, hash, key) { - const bit = bitpos(hash, shift); - if ((root.bitmap & bit) === 0) { - return root; // already empty - } - const idx = index(root.bitmap, bit); - const node = root.array[idx]; - // if the item is not an entry - if (node.type !== ENTRY) { - const n = without(node, shift + SHIFT, hash, key); - if (n === node) { - return root; // no changes - } - // if not undefined, the child node still has items, so update it - if (n !== undefined) { - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet(root.array, idx, n), - }; - } - // otherwise the child node should be removed - // if it was the only child node, remove this node from the parent - if (root.bitmap === bit) { - return undefined; - } - // otherwise just remove the child node - return { - type: INDEX_NODE, - bitmap: root.bitmap ^ bit, - array: spliceOut(root.array, idx), - }; - } - // otherwise the item is an entry, remove it if the key matches - if (isEqual(key, node.k)) { - if (root.bitmap === bit) { - return undefined; - } - return { - type: INDEX_NODE, - bitmap: root.bitmap ^ bit, - array: spliceOut(root.array, idx), - }; - } - return root; -} -/** - * @template K,V - * @param {CollisionNode} root - * @param {K} key - * @returns {undefined | Node} - */ -function withoutCollision(root, key) { - const idx = collisionIndexOf(root, key); - // if the key not found, no changes - if (idx < 0) { - return root; - } - // otherwise the entry was found, remove it - // if it was the only entry in this node, remove the whole node - if (root.array.length === 1) { - return undefined; - } - // otherwise just remove the entry - return { - type: COLLISION_NODE, - hash: root.hash, - array: spliceOut(root.array, idx), - }; -} -/** - * @template K,V - * @param {undefined | Node} root - * @param {(value:V,key:K)=>void} fn - * @returns {void} - */ -function forEach(root, fn) { - if (root === undefined) { - return; - } - const items = root.array; - const size = items.length; - for (let i = 0; i < size; i++) { - const item = items[i]; - if (item === undefined) { - continue; - } - if (item.type === ENTRY) { - fn(item.v, item.k); - continue; - } - forEach(item, fn); - } -} - -/** - * Extra wrapper to keep track of Dict size and clean up the API - * @template K,V - */ -export default class Dict { - /** - * @template V - * @param {Record} o - * @returns {Dict} - */ - static fromObject(o) { - const keys = Object.keys(o); - /** @type Dict */ - let m = Dict.new(); - for (let i = 0; i < keys.length; i++) { - const k = keys[i]; - m = m.set(k, o[k]); - } - return m; - } - - /** - * @template K,V - * @param {Map} o - * @returns {Dict} - */ - static fromMap(o) { - /** @type Dict */ - let m = Dict.new(); - o.forEach((v, k) => { - m = m.set(k, v); - }); - return m; - } - - static new() { - return new Dict(undefined, 0); - } - - /** - * @param {undefined | Node} root - * @param {number} size - */ - constructor(root, size) { - this.root = root; - this.size = size; - } - /** - * @template NotFound - * @param {K} key - * @param {NotFound} notFound - * @returns {NotFound | V} - */ - get(key, notFound) { - if (this.root === undefined) { - return notFound; - } - const found = find(this.root, 0, getHash(key), key); - if (found === undefined) { - return notFound; - } - return found.v; - } - /** - * @param {K} key - * @param {V} val - * @returns {Dict} - */ - set(key, val) { - const addedLeaf = { val: false }; - const root = this.root === undefined ? EMPTY : this.root; - const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); - if (newRoot === this.root) { - return this; - } - return new Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size); - } - /** - * @param {K} key - * @returns {Dict} - */ - delete(key) { - if (this.root === undefined) { - return this; - } - const newRoot = without(this.root, 0, getHash(key), key); - if (newRoot === this.root) { - return this; - } - if (newRoot === undefined) { - return Dict.new(); - } - return new Dict(newRoot, this.size - 1); - } - /** - * @param {K} key - * @returns {boolean} - */ - has(key) { - if (this.root === undefined) { - return false; - } - return find(this.root, 0, getHash(key), key) !== undefined; - } - /** - * @returns {[K,V][]} - */ - entries() { - if (this.root === undefined) { - return []; - } - /** @type [K,V][] */ - const result = []; - this.forEach((v, k) => result.push([k, v])); - return result; - } - /** - * - * @param {(val:V,key:K)=>void} fn - */ - forEach(fn) { - forEach(this.root, fn); - } - hashCode() { - let h = 0; - this.forEach((v, k) => { - h = (h + hashMerge(getHash(v), getHash(k))) | 0; - }); - return h; - } - /** - * @param {unknown} o - * @returns {boolean} - */ - equals(o) { - if (!(o instanceof Dict) || this.size !== o.size) { - return false; - } - - try { - this.forEach((v, k) => { - if (!isEqual(o.get(k, !v), v)) { - throw unequalDictSymbol; - } - }); - return true; - } catch (e) { - if (e === unequalDictSymbol) { - return false; - } - - throw e; - } - } -} - -// This is thrown internally in Dict.equals() so that it returns false as soon -// as a non-matching key is found -const unequalDictSymbol = /* @__PURE__ */ Symbol(); diff --git a/build/dev/javascript/gleam_stdlib/gleam.mjs b/build/dev/javascript/gleam_stdlib/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs b/build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs deleted file mode 100644 index e6c1a3a..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs +++ /dev/null @@ -1,285 +0,0 @@ -import { Ok, toList, bitArraySlice, bitArraySliceToInt } from "../gleam.mjs"; -import * as $int from "../gleam/int.mjs"; -import * as $order from "../gleam/order.mjs"; -import * as $string from "../gleam/string.mjs"; -import { - bit_array_from_string as from_string, - bit_array_bit_size as bit_size, - bit_array_byte_size as byte_size, - bit_array_pad_to_bytes as pad_to_bytes, - bit_array_slice as slice, - bit_array_concat as concat, - base64_encode, - base64_decode as decode64, - base16_encode, - base16_decode, - bit_array_to_int_and_size, - bit_array_starts_with as starts_with, - bit_array_to_string as to_string, -} from "../gleam_stdlib.mjs"; - -export { - base16_decode, - base16_encode, - base64_encode, - bit_size, - byte_size, - concat, - from_string, - pad_to_bytes, - slice, - starts_with, - to_string, -}; - -/** - * Creates a new bit array by joining two bit arrays. - * - * ## Examples - * - * ```gleam - * append(to: from_string("butter"), suffix: from_string("fly")) - * // -> from_string("butterfly") - * ``` - */ -export function append(first, second) { - return concat(toList([first, second])); -} - -/** - * Decodes a base 64 encoded string into a `BitArray`. - */ -export function base64_decode(encoded) { - let _block; - let $ = byte_size(from_string(encoded)) % 4; - if ($ === 0) { - _block = encoded; - } else { - let n = $; - _block = $string.append(encoded, $string.repeat("=", 4 - n)); - } - let padded = _block; - return decode64(padded); -} - -/** - * Encodes a `BitArray` into a base 64 encoded string with URL and filename - * safe alphabet. - * - * If the bit array does not contain a whole number of bytes then it is padded - * with zero bits prior to being encoded. - */ -export function base64_url_encode(input, padding) { - let _pipe = input; - let _pipe$1 = base64_encode(_pipe, padding); - let _pipe$2 = $string.replace(_pipe$1, "+", "-"); - return $string.replace(_pipe$2, "/", "_"); -} - -/** - * Decodes a base 64 encoded string with URL and filename safe alphabet into a - * `BitArray`. - */ -export function base64_url_decode(encoded) { - let _pipe = encoded; - let _pipe$1 = $string.replace(_pipe, "-", "+"); - let _pipe$2 = $string.replace(_pipe$1, "_", "/"); - return base64_decode(_pipe$2); -} - -function inspect_loop(loop$input, loop$accumulator) { - while (true) { - let input = loop$input; - let accumulator = loop$accumulator; - if (input.bitSize === 0) { - return accumulator; - } else if (input.bitSize === 1) { - let x = bitArraySliceToInt(input, 0, 1, true, false); - return (accumulator + $int.to_string(x)) + ":size(1)"; - } else if (input.bitSize === 2) { - let x = bitArraySliceToInt(input, 0, 2, true, false); - return (accumulator + $int.to_string(x)) + ":size(2)"; - } else if (input.bitSize === 3) { - let x = bitArraySliceToInt(input, 0, 3, true, false); - return (accumulator + $int.to_string(x)) + ":size(3)"; - } else if (input.bitSize === 4) { - let x = bitArraySliceToInt(input, 0, 4, true, false); - return (accumulator + $int.to_string(x)) + ":size(4)"; - } else if (input.bitSize === 5) { - let x = bitArraySliceToInt(input, 0, 5, true, false); - return (accumulator + $int.to_string(x)) + ":size(5)"; - } else if (input.bitSize === 6) { - let x = bitArraySliceToInt(input, 0, 6, true, false); - return (accumulator + $int.to_string(x)) + ":size(6)"; - } else if (input.bitSize === 7) { - let x = bitArraySliceToInt(input, 0, 7, true, false); - return (accumulator + $int.to_string(x)) + ":size(7)"; - } else if (input.bitSize >= 8) { - let x = input.byteAt(0); - let rest = bitArraySlice(input, 8); - let _block; - if (rest.bitSize === 0) { - _block = ""; - } else { - _block = ", "; - } - let suffix = _block; - let accumulator$1 = (accumulator + $int.to_string(x)) + suffix; - loop$input = rest; - loop$accumulator = accumulator$1; - } else { - return accumulator; - } - } -} - -/** - * Converts a bit array to a string containing the decimal value of each byte. - * - * Use this over `string.inspect` when you have a bit array you want printed - * in the array syntax even if it is valid UTF-8. - * - * ## Examples - * - * ```gleam - * inspect(<<0, 20, 0x20, 255>>) - * // -> "<<0, 20, 32, 255>>" - * - * inspect(<<100, 5:3>>) - * // -> "<<100, 5:size(3)>>" - * ``` - */ -export function inspect(input) { - return inspect_loop(input, "<<") + ">>"; -} - -/** - * Compare two bit arrays as sequences of bytes. - * - * ## Examples - * - * ```gleam - * compare(<<1>>, <<2>>) - * // -> Lt - * - * compare(<<"AB":utf8>>, <<"AA":utf8>>) - * // -> Gt - * - * compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>) - * // -> Eq - * ``` - */ -export function compare(loop$a, loop$b) { - while (true) { - let a = loop$a; - let b = loop$b; - if (a.bitSize >= 8) { - if (b.bitSize >= 8) { - let first_byte = a.byteAt(0); - let first_rest = bitArraySlice(a, 8); - let second_byte = b.byteAt(0); - let second_rest = bitArraySlice(b, 8); - let f = first_byte; - let s = second_byte; - if (f > s) { - return new $order.Gt(); - } else { - let f$1 = first_byte; - let s$1 = second_byte; - if (f$1 < s$1) { - return new $order.Lt(); - } else { - loop$a = first_rest; - loop$b = second_rest; - } - } - } else if (b.bitSize === 0) { - return new $order.Gt(); - } else { - let first = a; - let second = b; - let $ = bit_array_to_int_and_size(first); - let $1 = bit_array_to_int_and_size(second); - let a$1 = $[0]; - let b$1 = $1[0]; - if (a$1 > b$1) { - return new $order.Gt(); - } else { - let a$2 = $[0]; - let b$2 = $1[0]; - if (a$2 < b$2) { - return new $order.Lt(); - } else { - let size_a = $[1]; - let size_b = $1[1]; - if (size_a > size_b) { - return new $order.Gt(); - } else { - let size_a$1 = $[1]; - let size_b$1 = $1[1]; - if (size_a$1 < size_b$1) { - return new $order.Lt(); - } else { - return new $order.Eq(); - } - } - } - } - } - } else if (b.bitSize === 0) { - if (a.bitSize === 0) { - return new $order.Eq(); - } else { - return new $order.Gt(); - } - } else if (a.bitSize === 0) { - return new $order.Lt(); - } else { - let first = a; - let second = b; - let $ = bit_array_to_int_and_size(first); - let $1 = bit_array_to_int_and_size(second); - let a$1 = $[0]; - let b$1 = $1[0]; - if (a$1 > b$1) { - return new $order.Gt(); - } else { - let a$2 = $[0]; - let b$2 = $1[0]; - if (a$2 < b$2) { - return new $order.Lt(); - } else { - let size_a = $[1]; - let size_b = $1[1]; - if (size_a > size_b) { - return new $order.Gt(); - } else { - let size_a$1 = $[1]; - let size_b$1 = $1[1]; - if (size_a$1 < size_b$1) { - return new $order.Lt(); - } else { - return new $order.Eq(); - } - } - } - } - } - } -} - -/** - * Tests to see whether a bit array is valid UTF-8. - */ -export function is_utf8(bits) { - return is_utf8_loop(bits); -} - -function is_utf8_loop(bits) { - let $ = to_string(bits); - if ($ instanceof Ok) { - return true; - } else { - return false; - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/bool.mjs b/build/dev/javascript/gleam_stdlib/gleam/bool.mjs deleted file mode 100644 index 1a761a2..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/bool.mjs +++ /dev/null @@ -1,313 +0,0 @@ -/** - * Returns the and of two bools, but it evaluates both arguments. - * - * It's the function equivalent of the `&&` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * and(True, True) - * // -> True - * ``` - * - * ```gleam - * and(False, True) - * // -> False - * ``` - * - * ```gleam - * False |> and(True) - * // -> False - * ``` - */ -export function and(a, b) { - return a && b; -} - -/** - * Returns the or of two bools, but it evaluates both arguments. - * - * It's the function equivalent of the `||` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * or(True, True) - * // -> True - * ``` - * - * ```gleam - * or(False, True) - * // -> True - * ``` - * - * ```gleam - * False |> or(True) - * // -> True - * ``` - */ -export function or(a, b) { - return a || b; -} - -/** - * Returns the opposite bool value. - * - * This is the same as the `!` or `not` operators in some other languages. - * - * ## Examples - * - * ```gleam - * negate(True) - * // -> False - * ``` - * - * ```gleam - * negate(False) - * // -> True - * ``` - */ -export function negate(bool) { - return !bool; -} - -/** - * Returns the nor of two bools. - * - * ## Examples - * - * ```gleam - * nor(False, False) - * // -> True - * ``` - * - * ```gleam - * nor(False, True) - * // -> False - * ``` - * - * ```gleam - * nor(True, False) - * // -> False - * ``` - * - * ```gleam - * nor(True, True) - * // -> False - * ``` - */ -export function nor(a, b) { - return !(a || b); -} - -/** - * Returns the nand of two bools. - * - * ## Examples - * - * ```gleam - * nand(False, False) - * // -> True - * ``` - * - * ```gleam - * nand(False, True) - * // -> True - * ``` - * - * ```gleam - * nand(True, False) - * // -> True - * ``` - * - * ```gleam - * nand(True, True) - * // -> False - * ``` - */ -export function nand(a, b) { - return !(a && b); -} - -/** - * Returns the exclusive or of two bools. - * - * ## Examples - * - * ```gleam - * exclusive_or(False, False) - * // -> False - * ``` - * - * ```gleam - * exclusive_or(False, True) - * // -> True - * ``` - * - * ```gleam - * exclusive_or(True, False) - * // -> True - * ``` - * - * ```gleam - * exclusive_or(True, True) - * // -> False - * ``` - */ -export function exclusive_or(a, b) { - return a !== b; -} - -/** - * Returns the exclusive nor of two bools. - * - * ## Examples - * - * ```gleam - * exclusive_nor(False, False) - * // -> True - * ``` - * - * ```gleam - * exclusive_nor(False, True) - * // -> False - * ``` - * - * ```gleam - * exclusive_nor(True, False) - * // -> False - * ``` - * - * ```gleam - * exclusive_nor(True, True) - * // -> True - * ``` - */ -export function exclusive_nor(a, b) { - return a === b; -} - -/** - * Returns a string representation of the given bool. - * - * ## Examples - * - * ```gleam - * to_string(True) - * // -> "True" - * ``` - * - * ```gleam - * to_string(False) - * // -> "False" - * ``` - */ -export function to_string(bool) { - if (bool) { - return "True"; - } else { - return "False"; - } -} - -/** - * Run a callback function if the given bool is `False`, otherwise return a - * default value. - * - * With a `use` expression this function can simulate the early-return pattern - * found in some other programming languages. - * - * In a procedural language: - * - * ```js - * if (predicate) return value; - * // ... - * ``` - * - * In Gleam with a `use` expression: - * - * ```gleam - * use <- guard(when: predicate, return: value) - * // ... - * ``` - * - * Like everything in Gleam `use` is an expression, so it short circuits the - * current block, not the entire function. As a result you can assign the value - * to a variable: - * - * ```gleam - * let x = { - * use <- guard(when: predicate, return: value) - * // ... - * } - * ``` - * - * Note that unlike in procedural languages the `return` value is evaluated - * even when the predicate is `False`, so it is advisable not to perform - * expensive computation nor side-effects there. - * - * - * ## Examples - * - * ```gleam - * let name = "" - * use <- guard(when: name == "", return: "Welcome!") - * "Hello, " <> name - * // -> "Welcome!" - * ``` - * - * ```gleam - * let name = "Kamaka" - * use <- guard(when: name == "", return: "Welcome!") - * "Hello, " <> name - * // -> "Hello, Kamaka" - * ``` - */ -export function guard(requirement, consequence, alternative) { - if (requirement) { - return consequence; - } else { - return alternative(); - } -} - -/** - * Runs a callback function if the given bool is `True`, otherwise runs an - * alternative callback function. - * - * Useful when further computation should be delayed regardless of the given - * bool's value. - * - * See [`guard`](#guard) for more info. - * - * ## Examples - * - * ```gleam - * let name = "Kamaka" - * let inquiry = fn() { "How may we address you?" } - * use <- lazy_guard(when: name == "", return: inquiry) - * "Hello, " <> name - * // -> "Hello, Kamaka" - * ``` - * - * ```gleam - * import gleam/int - * - * let name = "" - * let greeting = fn() { "Hello, " <> name } - * use <- lazy_guard(when: name == "", otherwise: greeting) - * let number = int.random(99) - * let name = "User " <> int.to_string(number) - * "Welcome, " <> name - * // -> "Welcome, User 54" - * ``` - */ -export function lazy_guard(requirement, consequence, alternative) { - if (requirement) { - return consequence(); - } else { - return alternative(); - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs b/build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs deleted file mode 100644 index 517efd0..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs +++ /dev/null @@ -1,225 +0,0 @@ -import { - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, -} from "../gleam.mjs"; -import * as $bit_array from "../gleam/bit_array.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $string_tree from "../gleam/string_tree.mjs"; - -class Bytes extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class Text extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class Many extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -/** - * Appends a bytes tree onto the end of another. - * - * Runs in constant time. - */ -export function append_tree(first, second) { - if (second instanceof Bytes) { - return new Many(toList([first, second])); - } else if (second instanceof Text) { - return new Many(toList([first, second])); - } else { - let trees = second[0]; - return new Many(listPrepend(first, trees)); - } -} - -/** - * Prepends a bytes tree onto the start of another. - * - * Runs in constant time. - */ -export function prepend_tree(second, first) { - return append_tree(first, second); -} - -/** - * Joins a list of bytes trees into a single one. - * - * Runs in constant time. - */ -export function concat(trees) { - return new Many(trees); -} - -/** - * Create an empty `BytesTree`. Useful as the start of a pipe chaining many - * trees together. - */ -export function new$() { - return concat(toList([])); -} - -/** - * Creates a new bytes tree from a string. - * - * Runs in constant time when running on Erlang. - * Runs in linear time otherwise. - */ -export function from_string(string) { - return new Text($string_tree.from_string(string)); -} - -/** - * Prepends a string onto the start of a bytes tree. - * - * Runs in constant time when running on Erlang. - * Runs in linear time with the length of the string otherwise. - */ -export function prepend_string(second, first) { - return append_tree(from_string(first), second); -} - -/** - * Appends a string onto the end of a bytes tree. - * - * Runs in constant time when running on Erlang. - * Runs in linear time with the length of the string otherwise. - */ -export function append_string(first, second) { - return append_tree(first, from_string(second)); -} - -/** - * Creates a new bytes tree from a string tree. - * - * Runs in constant time when running on Erlang. - * Runs in linear time otherwise. - */ -export function from_string_tree(tree) { - return new Text(tree); -} - -function wrap_list(bits) { - return new Bytes(bits); -} - -/** - * Creates a new bytes tree from a bit array. - * - * Runs in constant time. - */ -export function from_bit_array(bits) { - let _pipe = bits; - let _pipe$1 = $bit_array.pad_to_bytes(_pipe); - return wrap_list(_pipe$1); -} - -/** - * Prepends a bit array to the start of a bytes tree. - * - * Runs in constant time. - */ -export function prepend(second, first) { - return append_tree(from_bit_array(first), second); -} - -/** - * Appends a bit array to the end of a bytes tree. - * - * Runs in constant time. - */ -export function append(first, second) { - return append_tree(first, from_bit_array(second)); -} - -/** - * Joins a list of bit arrays into a single bytes tree. - * - * Runs in constant time. - */ -export function concat_bit_arrays(bits) { - let _pipe = bits; - let _pipe$1 = $list.map(_pipe, from_bit_array); - return concat(_pipe$1); -} - -function to_list(loop$stack, loop$acc) { - while (true) { - let stack = loop$stack; - let acc = loop$acc; - if (stack instanceof $Empty) { - return acc; - } else { - let $ = stack.head; - if ($ instanceof $Empty) { - let remaining_stack = stack.tail; - loop$stack = remaining_stack; - loop$acc = acc; - } else { - let $1 = $.head; - if ($1 instanceof Bytes) { - let remaining_stack = stack.tail; - let rest = $.tail; - let bits = $1[0]; - loop$stack = listPrepend(rest, remaining_stack); - loop$acc = listPrepend(bits, acc); - } else if ($1 instanceof Text) { - let remaining_stack = stack.tail; - let rest = $.tail; - let tree = $1[0]; - let bits = $bit_array.from_string($string_tree.to_string(tree)); - loop$stack = listPrepend(rest, remaining_stack); - loop$acc = listPrepend(bits, acc); - } else { - let remaining_stack = stack.tail; - let rest = $.tail; - let trees = $1[0]; - loop$stack = listPrepend(trees, listPrepend(rest, remaining_stack)); - loop$acc = acc; - } - } - } - } -} - -/** - * Turns a bytes tree into a bit array. - * - * Runs in linear time. - * - * When running on Erlang this function is implemented natively by the - * virtual machine and is highly optimised. - */ -export function to_bit_array(tree) { - let _pipe = toList([toList([tree])]); - let _pipe$1 = to_list(_pipe, toList([])); - let _pipe$2 = $list.reverse(_pipe$1); - return $bit_array.concat(_pipe$2); -} - -/** - * Returns the size of the bytes tree's content in bytes. - * - * Runs in linear time. - */ -export function byte_size(tree) { - let _pipe = toList([toList([tree])]); - let _pipe$1 = to_list(_pipe, toList([])); - return $list.fold( - _pipe$1, - 0, - (acc, bits) => { return $bit_array.byte_size(bits) + acc; }, - ); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/dict.mjs b/build/dev/javascript/gleam_stdlib/gleam/dict.mjs deleted file mode 100644 index aa206af..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/dict.mjs +++ /dev/null @@ -1,534 +0,0 @@ -import { Ok, Error, toList, Empty as $Empty, prepend as listPrepend, isEqual } from "../gleam.mjs"; -import * as $option from "../gleam/option.mjs"; -import { - map_size as size, - map_to_list as to_list, - new_map as new$, - map_get as get, - map_insert as do_insert, - map_remove as do_delete, -} from "../gleam_stdlib.mjs"; - -export { get, new$, size, to_list }; - -/** - * Determines whether or not the dict is empty. - * - * ## Examples - * - * ```gleam - * new() |> is_empty - * // -> True - * ``` - * - * ```gleam - * new() |> insert("b", 1) |> is_empty - * // -> False - * ``` - */ -export function is_empty(dict) { - return size(dict) === 0; -} - -function do_has_key(key, dict) { - return !isEqual(get(dict, key), new Error(undefined)); -} - -/** - * Determines whether or not a value present in the dict for a given key. - * - * ## Examples - * - * ```gleam - * new() |> insert("a", 0) |> has_key("a") - * // -> True - * ``` - * - * ```gleam - * new() |> insert("a", 0) |> has_key("b") - * // -> False - * ``` - */ -export function has_key(dict, key) { - return do_has_key(key, dict); -} - -/** - * Inserts a value into the dict with the given key. - * - * If the dict already has a value for the given key then the value is - * replaced with the new value. - * - * ## Examples - * - * ```gleam - * new() |> insert("a", 0) - * // -> from_list([#("a", 0)]) - * ``` - * - * ```gleam - * new() |> insert("a", 0) |> insert("a", 5) - * // -> from_list([#("a", 5)]) - * ``` - */ -export function insert(dict, key, value) { - return do_insert(key, value, dict); -} - -function from_list_loop(loop$list, loop$initial) { - while (true) { - let list = loop$list; - let initial = loop$initial; - if (list instanceof $Empty) { - return initial; - } else { - let rest = list.tail; - let key = list.head[0]; - let value = list.head[1]; - loop$list = rest; - loop$initial = insert(initial, key, value); - } - } -} - -/** - * Converts a list of 2-element tuples `#(key, value)` to a dict. - * - * If two tuples have the same key the last one in the list will be the one - * that is present in the dict. - */ -export function from_list(list) { - return from_list_loop(list, new$()); -} - -function reverse_and_concat(loop$remaining, loop$accumulator) { - while (true) { - let remaining = loop$remaining; - let accumulator = loop$accumulator; - if (remaining instanceof $Empty) { - return accumulator; - } else { - let first = remaining.head; - let rest = remaining.tail; - loop$remaining = rest; - loop$accumulator = listPrepend(first, accumulator); - } - } -} - -function do_keys_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse_and_concat(acc, toList([])); - } else { - let rest = list.tail; - let key = list.head[0]; - loop$list = rest; - loop$acc = listPrepend(key, acc); - } - } -} - -/** - * Gets a list of all keys in a given dict. - * - * Dicts are not ordered so the keys are not returned in any specific order. Do - * not write code that relies on the order keys are returned by this function - * as it may change in later versions of Gleam or Erlang. - * - * ## Examples - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> keys - * // -> ["a", "b"] - * ``` - */ -export function keys(dict) { - return do_keys_loop(to_list(dict), toList([])); -} - -function do_values_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse_and_concat(acc, toList([])); - } else { - let rest = list.tail; - let value = list.head[1]; - loop$list = rest; - loop$acc = listPrepend(value, acc); - } - } -} - -/** - * Gets a list of all values in a given dict. - * - * Dicts are not ordered so the values are not returned in any specific order. Do - * not write code that relies on the order values are returned by this function - * as it may change in later versions of Gleam or Erlang. - * - * ## Examples - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> values - * // -> [0, 1] - * ``` - */ -export function values(dict) { - let list_of_pairs = to_list(dict); - return do_values_loop(list_of_pairs, toList([])); -} - -function do_take_loop(loop$dict, loop$desired_keys, loop$acc) { - while (true) { - let dict = loop$dict; - let desired_keys = loop$desired_keys; - let acc = loop$acc; - let insert$1 = (taken, key) => { - let $ = get(dict, key); - if ($ instanceof Ok) { - let value = $[0]; - return insert(taken, key, value); - } else { - return taken; - } - }; - if (desired_keys instanceof $Empty) { - return acc; - } else { - let first = desired_keys.head; - let rest = desired_keys.tail; - loop$dict = dict; - loop$desired_keys = rest; - loop$acc = insert$1(acc, first); - } - } -} - -function do_take(desired_keys, dict) { - return do_take_loop(dict, desired_keys, new$()); -} - -/** - * Creates a new dict from a given dict, only including any entries for which the - * keys are in a given list. - * - * ## Examples - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) - * |> take(["b"]) - * // -> from_list([#("b", 1)]) - * ``` - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) - * |> take(["a", "b", "c"]) - * // -> from_list([#("a", 0), #("b", 1)]) - * ``` - */ -export function take(dict, desired_keys) { - return do_take(desired_keys, dict); -} - -function insert_pair(dict, pair) { - return insert(dict, pair[0], pair[1]); -} - -function fold_inserts(loop$new_entries, loop$dict) { - while (true) { - let new_entries = loop$new_entries; - let dict = loop$dict; - if (new_entries instanceof $Empty) { - return dict; - } else { - let first = new_entries.head; - let rest = new_entries.tail; - loop$new_entries = rest; - loop$dict = insert_pair(dict, first); - } - } -} - -/** - * Creates a new dict from a pair of given dicts by combining their entries. - * - * If there are entries with the same keys in both dicts the entry from the - * second dict takes precedence. - * - * ## Examples - * - * ```gleam - * let a = from_list([#("a", 0), #("b", 1)]) - * let b = from_list([#("b", 2), #("c", 3)]) - * merge(a, b) - * // -> from_list([#("a", 0), #("b", 2), #("c", 3)]) - * ``` - */ -export function merge(dict, new_entries) { - let _pipe = new_entries; - let _pipe$1 = to_list(_pipe); - return fold_inserts(_pipe$1, dict); -} - -/** - * Creates a new dict from a given dict with all the same entries except for the - * one with a given key, if it exists. - * - * ## Examples - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> delete("a") - * // -> from_list([#("b", 1)]) - * ``` - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> delete("c") - * // -> from_list([#("a", 0), #("b", 1)]) - * ``` - */ -export function delete$(dict, key) { - return do_delete(key, dict); -} - -/** - * Creates a new dict from a given dict with all the same entries except any with - * keys found in a given list. - * - * ## Examples - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> drop(["a"]) - * // -> from_list([#("b", 1)]) - * ``` - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> drop(["c"]) - * // -> from_list([#("a", 0), #("b", 1)]) - * ``` - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) |> drop(["a", "b", "c"]) - * // -> from_list([]) - * ``` - */ -export function drop(loop$dict, loop$disallowed_keys) { - while (true) { - let dict = loop$dict; - let disallowed_keys = loop$disallowed_keys; - if (disallowed_keys instanceof $Empty) { - return dict; - } else { - let first = disallowed_keys.head; - let rest = disallowed_keys.tail; - loop$dict = delete$(dict, first); - loop$disallowed_keys = rest; - } - } -} - -/** - * Creates a new dict with one entry inserted or updated using a given function. - * - * If there was not an entry in the dict for the given key then the function - * gets `None` as its argument, otherwise it gets `Some(value)`. - * - * ## Example - * - * ```gleam - * let dict = from_list([#("a", 0)]) - * let increment = fn(x) { - * case x { - * Some(i) -> i + 1 - * None -> 0 - * } - * } - * - * upsert(dict, "a", increment) - * // -> from_list([#("a", 1)]) - * - * upsert(dict, "b", increment) - * // -> from_list([#("a", 0), #("b", 0)]) - * ``` - */ -export function upsert(dict, key, fun) { - let $ = get(dict, key); - if ($ instanceof Ok) { - let value = $[0]; - return insert(dict, key, fun(new $option.Some(value))); - } else { - return insert(dict, key, fun(new $option.None())); - } -} - -function fold_loop(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return initial; - } else { - let rest = list.tail; - let k = list.head[0]; - let v = list.head[1]; - loop$list = rest; - loop$initial = fun(initial, k, v); - loop$fun = fun; - } - } -} - -/** - * Combines all entries into a single value by calling a given function on each - * one. - * - * Dicts are not ordered so the values are not returned in any specific order. Do - * not write code that relies on the order entries are used by this function - * as it may change in later versions of Gleam or Erlang. - * - * # Examples - * - * ```gleam - * let dict = from_list([#("a", 1), #("b", 3), #("c", 9)]) - * fold(dict, 0, fn(accumulator, key, value) { accumulator + value }) - * // -> 13 - * ``` - * - * ```gleam - * import gleam/string - * - * let dict = from_list([#("a", 1), #("b", 3), #("c", 9)]) - * fold(dict, "", fn(accumulator, key, value) { - * string.append(accumulator, key) - * }) - * // -> "abc" - * ``` - */ -export function fold(dict, initial, fun) { - return fold_loop(to_list(dict), initial, fun); -} - -function do_map_values(f, dict) { - let f$1 = (dict, k, v) => { return insert(dict, k, f(k, v)); }; - return fold(dict, new$(), f$1); -} - -/** - * Updates all values in a given dict by calling a given function on each key - * and value. - * - * ## Examples - * - * ```gleam - * from_list([#(3, 3), #(2, 4)]) - * |> map_values(fn(key, value) { key * value }) - * // -> from_list([#(3, 9), #(2, 8)]) - * ``` - */ -export function map_values(dict, fun) { - return do_map_values(fun, dict); -} - -function do_filter(f, dict) { - let insert$1 = (dict, k, v) => { - let $ = f(k, v); - if ($) { - return insert(dict, k, v); - } else { - return dict; - } - }; - return fold(dict, new$(), insert$1); -} - -/** - * Creates a new dict from a given dict, minus any entries that a given function - * returns `False` for. - * - * ## Examples - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) - * |> filter(fn(key, value) { value != 0 }) - * // -> from_list([#("b", 1)]) - * ``` - * - * ```gleam - * from_list([#("a", 0), #("b", 1)]) - * |> filter(fn(key, value) { True }) - * // -> from_list([#("a", 0), #("b", 1)]) - * ``` - */ -export function filter(dict, predicate) { - return do_filter(predicate, dict); -} - -/** - * Calls a function for each key and value in a dict, discarding the return - * value. - * - * Useful for producing a side effect for every item of a dict. - * - * ```gleam - * import gleam/io - * - * let dict = from_list([#("a", "apple"), #("b", "banana"), #("c", "cherry")]) - * - * each(dict, fn(k, v) { - * io.println(key <> " => " <> value) - * }) - * // -> Nil - * // a => apple - * // b => banana - * // c => cherry - * ``` - * - * The order of elements in the iteration is an implementation detail that - * should not be relied upon. - */ -export function each(dict, fun) { - return fold( - dict, - undefined, - (nil, k, v) => { - fun(k, v); - return nil; - }, - ); -} - -/** - * Creates a new dict from a pair of given dicts by combining their entries. - * - * If there are entries with the same keys in both dicts the given function is - * used to determine the new value to use in the resulting dict. - * - * ## Examples - * - * ```gleam - * let a = from_list([#("a", 0), #("b", 1)]) - * let b = from_list([#("a", 2), #("c", 3)]) - * combine(a, b, fn(one, other) { one + other }) - * // -> from_list([#("a", 2), #("b", 1), #("c", 3)]) - * ``` - */ -export function combine(dict, other, fun) { - return fold( - dict, - other, - (acc, key, value) => { - let $ = get(acc, key); - if ($ instanceof Ok) { - let other_value = $[0]; - return insert(acc, key, fun(value, other_value)); - } else { - return insert(acc, key, value); - } - }, - ); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs b/build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs deleted file mode 100644 index 3c67bbb..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs +++ /dev/null @@ -1,35 +0,0 @@ -import * as $dict from "../gleam/dict.mjs"; -import { - classify_dynamic as classify, - identity as bool, - identity as string, - identity as float, - identity as int, - identity as bit_array, - identity as list, - list_to_array as array, - identity as cast, -} from "../gleam_stdlib.mjs"; - -export { array, bit_array, bool, classify, float, int, list, string }; - -/** - * Create a dynamic value made an unordered series of keys and values, where - * the keys are unique. - * - * On Erlang this will be a map, on JavaScript this will be a Gleam dict - * object. - */ -export function properties(entries) { - return cast($dict.from_list(entries)); -} - -/** - * A dynamic value representing nothing. - * - * On Erlang this will be the atom `nil`, on JavaScript this will be - * `undefined`. - */ -export function nil() { - return cast(undefined); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs b/build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs deleted file mode 100644 index 25c8902..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs +++ /dev/null @@ -1,947 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - isEqual, -} from "../../gleam.mjs"; -import * as $bit_array from "../../gleam/bit_array.mjs"; -import * as $dict from "../../gleam/dict.mjs"; -import * as $dynamic from "../../gleam/dynamic.mjs"; -import * as $int from "../../gleam/int.mjs"; -import * as $list from "../../gleam/list.mjs"; -import * as $option from "../../gleam/option.mjs"; -import { None, Some } from "../../gleam/option.mjs"; -import { - index as bare_index, - int as dynamic_int, - float as dynamic_float, - bit_array as dynamic_bit_array, - list as decode_list, - dict as decode_dict, - identity as cast, - is_null, - string as dynamic_string, -} from "../../gleam_stdlib.mjs"; - -export class DecodeError extends $CustomType { - constructor(expected, found, path) { - super(); - this.expected = expected; - this.found = found; - this.path = path; - } -} -export const DecodeError$DecodeError = (expected, found, path) => - new DecodeError(expected, found, path); -export const DecodeError$isDecodeError = (value) => - value instanceof DecodeError; -export const DecodeError$DecodeError$expected = (value) => value.expected; -export const DecodeError$DecodeError$0 = (value) => value.expected; -export const DecodeError$DecodeError$found = (value) => value.found; -export const DecodeError$DecodeError$1 = (value) => value.found; -export const DecodeError$DecodeError$path = (value) => value.path; -export const DecodeError$DecodeError$2 = (value) => value.path; - -class Decoder extends $CustomType { - constructor(function$) { - super(); - this.function = function$; - } -} - -/** - * Run a decoder on a `Dynamic` value, decoding the value if it is of the - * desired type, or returning errors. - * - * # Examples - * - * ```gleam - * let decoder = { - * use name <- decode.field("email", decode.string) - * use email <- decode.field("password", decode.string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * decode.run(data, decoder) - * ``` - */ -export function run(data, decoder) { - let $ = decoder.function(data); - let maybe_invalid_data; - let errors; - maybe_invalid_data = $[0]; - errors = $[1]; - if (errors instanceof $Empty) { - return new Ok(maybe_invalid_data); - } else { - return new Error(errors); - } -} - -/** - * Finalise a decoder having successfully extracted a value. - * - * # Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("email"), dynamic.string("lucy@example.com")), - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ])) - * - * let decoder = { - * use name <- decode.field("name", string) - * use email <- decode.field("email", string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) - * ``` - */ -export function success(data) { - return new Decoder((_) => { return [data, toList([])]; }); -} - -function decode_dynamic(data) { - return [data, toList([])]; -} - -/** - * Apply a transformation function to any value decoded by the decoder. - * - * # Examples - * - * ```gleam - * let decoder = decode.int |> decode.map(int.to_string) - * let result = decode.run(dynamic.int(1000), decoder) - * assert result == Ok("1000") - * ``` - */ -export function map(decoder, transformer) { - return new Decoder( - (d) => { - let $ = decoder.function(d); - let data; - let errors; - data = $[0]; - errors = $[1]; - return [transformer(data), errors]; - }, - ); -} - -/** - * Apply a transformation function to any errors returned by the decoder. - */ -export function map_errors(decoder, transformer) { - return new Decoder( - (d) => { - let $ = decoder.function(d); - let data; - let errors; - data = $[0]; - errors = $[1]; - return [data, transformer(errors)]; - }, - ); -} - -/** - * Create a new decoder based upon the value of a previous decoder. - * - * This may be useful to run one previous decoder to use in further decoding. - */ -export function then$(decoder, next) { - return new Decoder( - (dynamic_data) => { - let $ = decoder.function(dynamic_data); - let data; - let errors; - data = $[0]; - errors = $[1]; - let decoder$1 = next(data); - let $1 = decoder$1.function(dynamic_data); - let layer; - let data$1; - layer = $1; - data$1 = $1[0]; - if (errors instanceof $Empty) { - return layer; - } else { - return [data$1, errors]; - } - }, - ); -} - -function run_decoders(loop$data, loop$failure, loop$decoders) { - while (true) { - let data = loop$data; - let failure = loop$failure; - let decoders = loop$decoders; - if (decoders instanceof $Empty) { - return failure; - } else { - let decoder = decoders.head; - let decoders$1 = decoders.tail; - let $ = decoder.function(data); - let layer; - let errors; - layer = $; - errors = $[1]; - if (errors instanceof $Empty) { - return layer; - } else { - loop$data = data; - loop$failure = failure; - loop$decoders = decoders$1; - } - } - } -} - -/** - * Create a new decoder from several other decoders. Each of the inner - * decoders is run in turn, and the value from the first to succeed is used. - * - * If no decoder succeeds then the errors from the first decoder is used. - * If you wish for different errors then you may wish to use the - * `collapse_errors` or `map_errors` functions. - * - * # Examples - * - * ```gleam - * let decoder = decode.one_of(decode.string, or: [ - * decode.int |> decode.map(int.to_string), - * decode.float |> decode.map(float.to_string), - * ]) - * decode.run(dynamic.int(1000), decoder) - * // -> Ok("1000") - * ``` - */ -export function one_of(first, alternatives) { - return new Decoder( - (dynamic_data) => { - let $ = first.function(dynamic_data); - let layer; - let errors; - layer = $; - errors = $[1]; - if (errors instanceof $Empty) { - return layer; - } else { - return run_decoders(dynamic_data, layer, alternatives); - } - }, - ); -} - -/** - * Create a decoder that can refer to itself, useful for decoding deeply - * nested data. - * - * Attempting to create a recursive decoder without this function could result - * in an infinite loop. If you are using `field` or other `use`able functions - * then you may not need to use this function. - * - * ```gleam - * type Nested { - * Nested(List(Nested)) - * Value(String) - * } - * - * fn nested_decoder() -> decode.Decoder(Nested) { - * use <- decode.recursive - * decode.one_of(decode.string |> decode.map(Value), [ - * decode.list(nested_decoder()) |> decode.map(Nested), - * ]) - * } - * ``` - */ -export function recursive(inner) { - return new Decoder( - (data) => { - let decoder = inner(); - return decoder.function(data); - }, - ); -} - -/** - * A decoder that decodes nullable values of a type decoded by with a given - * decoder. - * - * This function can handle common representations of null on all runtimes, such as - * `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on - * JavaScript. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.int(100), decode.optional(decode.int)) - * assert result == Ok(option.Some(100)) - * ``` - * - * ```gleam - * let result = decode.run(dynamic.nil(), decode.optional(decode.int)) - * assert result == Ok(option.None) - * ``` - */ -export function optional(inner) { - return new Decoder( - (data) => { - let $ = is_null(data); - if ($) { - return [new $option.None(), toList([])]; - } else { - let $1 = inner.function(data); - let data$1; - let errors; - data$1 = $1[0]; - errors = $1[1]; - return [new $option.Some(data$1), errors]; - } - }, - ); -} - -/** - * A decoder that decodes `Dynamic` values. This decoder never returns an error. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.float(3.14), decode.dynamic) - * assert result == Ok(dynamic.float(3.14)) - * ``` - */ -export const dynamic = /* @__PURE__ */ new Decoder(decode_dynamic); - -/** - * Construct a decode error for some unexpected dynamic data. - */ -export function decode_error(expected, found) { - return toList([ - new DecodeError(expected, $dynamic.classify(found), toList([])), - ]); -} - -function run_dynamic_function(data, name, f) { - let $ = f(data); - if ($ instanceof Ok) { - let data$1 = $[0]; - return [data$1, toList([])]; - } else { - let zero = $[0]; - return [ - zero, - toList([new DecodeError(name, $dynamic.classify(data), toList([]))]), - ]; - } -} - -function decode_bool(data) { - let $ = isEqual(cast(true), data); - if ($) { - return [true, toList([])]; - } else { - let $1 = isEqual(cast(false), data); - if ($1) { - return [false, toList([])]; - } else { - return [false, decode_error("Bool", data)]; - } - } -} - -function decode_int(data) { - return run_dynamic_function(data, "Int", dynamic_int); -} - -function decode_float(data) { - return run_dynamic_function(data, "Float", dynamic_float); -} - -function decode_bit_array(data) { - return run_dynamic_function(data, "BitArray", dynamic_bit_array); -} - -/** - * Replace all errors produced by a decoder with one single error for a named - * expected type. - * - * This function may be useful if you wish to simplify errors before - * presenting them to a user, particularly when using the `one_of` function. - * - * # Examples - * - * ```gleam - * let decoder = decode.string |> decode.collapse_errors("MyThing") - * let result = decode.run(dynamic.int(1000), decoder) - * assert result == Error([DecodeError("MyThing", "Int", [])]) - * ``` - */ -export function collapse_errors(decoder, name) { - return new Decoder( - (dynamic_data) => { - let $ = decoder.function(dynamic_data); - let layer; - let data; - let errors; - layer = $; - data = $[0]; - errors = $[1]; - if (errors instanceof $Empty) { - return layer; - } else { - return [data, decode_error(name, dynamic_data)]; - } - }, - ); -} - -/** - * Define a decoder that always fails. The parameter for this function is the - * name of the type that has failed to decode. - */ -export function failure(zero, expected) { - return new Decoder((d) => { return [zero, decode_error(expected, d)]; }); -} - -/** - * Create a decoder for a new data type from a decoding function. - * - * This function is used for new primitive types. For example, you might - * define a decoder for Erlang's pid type. - * - * A default "zero" value is also required to make a decoder. When this - * decoder is used as part of a larger decoder this zero value used as - * a placeholder so that the rest of the decoder can continue to run and - * collect all decoding errors. - * - * If you were to make a decoder for the `String` type (rather than using the - * build-in `string` decoder) you would define it like so: - * - * ```gleam - * pub fn string_decoder() -> decode.Decoder(String) { - * let default = "" - * decode.new_primitive_decoder("String", fn(data) { - * case dynamic.string(data) { - * Ok(x) -> Ok(x) - * Error(_) -> Error(default) - * } - * }) - * } - * ``` - */ -export function new_primitive_decoder(name, decoding_function) { - return new Decoder( - (d) => { - let $ = decoding_function(d); - if ($ instanceof Ok) { - let t = $[0]; - return [t, toList([])]; - } else { - let zero = $[0]; - return [ - zero, - toList([new DecodeError(name, $dynamic.classify(d), toList([]))]), - ]; - } - }, - ); -} - -/** - * A decoder that decodes `Bool` values. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.bool(True), decode.bool) - * assert result == Ok(True) - * ``` - */ -export const bool = /* @__PURE__ */ new Decoder(decode_bool); - -/** - * A decoder that decodes `Int` values. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.int(147), decode.int) - * assert result == Ok(147) - * ``` - */ -export const int = /* @__PURE__ */ new Decoder(decode_int); - -/** - * A decoder that decodes `Float` values. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.float(3.14), decode.float) - * assert result == Ok(3.14) - * ``` - */ -export const float = /* @__PURE__ */ new Decoder(decode_float); - -/** - * A decoder that decodes `BitArray` values. This decoder never returns an error. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.bit_array(<<5, 7>>), decode.bit_array) - * assert result == Ok(<<5, 7>>) - * ``` - */ -export const bit_array = /* @__PURE__ */ new Decoder(decode_bit_array); - -function decode_string(data) { - return run_dynamic_function(data, "String", dynamic_string); -} - -/** - * A decoder that decodes `String` values. - * - * # Examples - * - * ```gleam - * let result = decode.run(dynamic.string("Hello!"), decode.string) - * assert result == Ok("Hello!") - * ``` - */ -export const string = /* @__PURE__ */ new Decoder(decode_string); - -function fold_dict(acc, key, value, key_decoder, value_decoder) { - let $ = key_decoder(key); - let $1 = $[1]; - if ($1 instanceof $Empty) { - let key$1 = $[0]; - let $2 = value_decoder(value); - let $3 = $2[1]; - if ($3 instanceof $Empty) { - let value$1 = $2[0]; - let dict$1 = $dict.insert(acc[0], key$1, value$1); - return [dict$1, acc[1]]; - } else { - let errors = $3; - return push_path([$dict.new$(), errors], toList(["values"])); - } - } else { - let errors = $1; - return push_path([$dict.new$(), errors], toList(["keys"])); - } -} - -/** - * A decoder that decodes dicts where all keys and vales are decoded with - * given decoders. - * - * # Examples - * - * ```gleam - * let values = dynamic.properties([ - * #(dynamic.string("one"), dynamic.int(1)), - * #(dynamic.string("two"), dynamic.int(2)), - * ]) - * - * let result = - * decode.run(values, decode.dict(decode.string, decode.int)) - * assert result == Ok(values) - * ``` - */ -export function dict(key, value) { - return new Decoder( - (data) => { - let $ = decode_dict(data); - if ($ instanceof Ok) { - let dict$1 = $[0]; - return $dict.fold( - dict$1, - [$dict.new$(), toList([])], - (a, k, v) => { - let $1 = a[1]; - if ($1 instanceof $Empty) { - return fold_dict(a, k, v, key.function, value.function); - } else { - return a; - } - }, - ); - } else { - return [$dict.new$(), decode_error("Dict", data)]; - } - }, - ); -} - -/** - * A decoder that decodes lists where all elements are decoded with a given - * decoder. - * - * # Examples - * - * ```gleam - * let result = - * [1, 2, 3] - * |> list.map(dynamic.int) - * |> dynamic.list - * |> decode.run(decode.list(of: decode.int)) - * assert result == Ok([1, 2, 3]) - * ``` - */ -export function list(inner) { - return new Decoder( - (data) => { - return decode_list( - data, - inner.function, - (p, k) => { return push_path(p, toList([k])); }, - 0, - toList([]), - ); - }, - ); -} - -function push_path(layer, path) { - let decoder = one_of( - string, - toList([ - (() => { - let _pipe = int; - return map(_pipe, $int.to_string); - })(), - ]), - ); - let path$1 = $list.map( - path, - (key) => { - let key$1 = cast(key); - let $ = run(key$1, decoder); - if ($ instanceof Ok) { - let key$2 = $[0]; - return key$2; - } else { - return ("<" + $dynamic.classify(key$1)) + ">"; - } - }, - ); - let errors = $list.map( - layer[1], - (error) => { - return new DecodeError( - error.expected, - error.found, - $list.append(path$1, error.path), - ); - }, - ); - return [layer[0], errors]; -} - -function index( - loop$path, - loop$position, - loop$inner, - loop$data, - loop$handle_miss -) { - while (true) { - let path = loop$path; - let position = loop$position; - let inner = loop$inner; - let data = loop$data; - let handle_miss = loop$handle_miss; - if (path instanceof $Empty) { - let _pipe = data; - let _pipe$1 = inner(_pipe); - return push_path(_pipe$1, $list.reverse(position)); - } else { - let key = path.head; - let path$1 = path.tail; - let $ = bare_index(data, key); - if ($ instanceof Ok) { - let $1 = $[0]; - if ($1 instanceof Some) { - let data$1 = $1[0]; - loop$path = path$1; - loop$position = listPrepend(key, position); - loop$inner = inner; - loop$data = data$1; - loop$handle_miss = handle_miss; - } else { - return handle_miss(data, listPrepend(key, position)); - } - } else { - let kind = $[0]; - let $1 = inner(data); - let default$; - default$ = $1[0]; - let _pipe = [ - default$, - toList([new DecodeError(kind, $dynamic.classify(data), toList([]))]), - ]; - return push_path(_pipe, $list.reverse(position)); - } - } - } -} - -/** - * The same as [`field`](#field), except taking a path to the value rather - * than a field name. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * # Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("data"), dynamic.properties([ - * #(dynamic.string("email"), dynamic.string("lucy@example.com")), - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ]) - * ])) - * - * let decoder = { - * use name <- decode.subfield(["data", "name"], decode.string) - * use email <- decode.subfield(["data", "email"], decode.string) - * decode.success(SignUp(name: name, email: email)) - * } - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) - * ``` - */ -export function subfield(field_path, field_decoder, next) { - return new Decoder( - (data) => { - let $ = index( - field_path, - toList([]), - field_decoder.function, - data, - (data, position) => { - let $1 = field_decoder.function(data); - let default$; - default$ = $1[0]; - let _pipe = [ - default$, - toList([new DecodeError("Field", "Nothing", toList([]))]), - ]; - return push_path(_pipe, $list.reverse(position)); - }, - ); - let out; - let errors1; - out = $[0]; - errors1 = $[1]; - let $1 = next(out).function(data); - let out$1; - let errors2; - out$1 = $1[0]; - errors2 = $1[1]; - return [out$1, $list.append(errors1, errors2)]; - }, - ); -} - -/** - * A decoder that decodes a value that is nested within other values. For - * example, decoding a value that is within some deeply nested JSON objects. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * # Examples - * - * ```gleam - * let decoder = decode.at(["one", "two"], decode.int) - * - * let data = dynamic.properties([ - * #(dynamic.string("one"), dynamic.properties([ - * #(dynamic.string("two"), dynamic.int(1000)), - * ])), - * ])) - * - * - * decode.run(data, decoder) - * // -> Ok(1000) - * ``` - * - * ```gleam - * dynamic.nil() - * |> decode.run(decode.optional(decode.int)) - * // -> Ok(option.None) - * ``` - */ -export function at(path, inner) { - return new Decoder( - (data) => { - return index( - path, - toList([]), - inner.function, - data, - (data, position) => { - let $ = inner.function(data); - let default$; - default$ = $[0]; - let _pipe = [ - default$, - toList([new DecodeError("Field", "Nothing", toList([]))]), - ]; - return push_path(_pipe, $list.reverse(position)); - }, - ); - }, - ); -} - -/** - * Run a decoder on a field of a `Dynamic` value, decoding the value if it is - * of the desired type, or returning errors. An error is returned if there is - * no field for the specified key. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * # Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("email"), dynamic.string("lucy@example.com")), - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ])) - * - * let decoder = { - * use name <- decode.field("name", string) - * use email <- decode.field("email", string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) - * ``` - * - * If you wish to decode a value that is more deeply nested within the dynamic - * data, see [`subfield`](#subfield) and [`at`](#at). - * - * If you wish to return a default in the event that a field is not present, - * see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at). - */ -export function field(field_name, field_decoder, next) { - return subfield(toList([field_name]), field_decoder, next); -} - -/** - * Run a decoder on a field of a `Dynamic` value, decoding the value if it is - * of the desired type, or returning errors. The given default value is - * returned if there is no field for the specified key. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * # Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ])) - * - * let decoder = { - * use name <- decode.field("name", string) - * use email <- decode.optional_field("email", "n/a", string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "n/a")) - * ``` - */ -export function optional_field(key, default$, field_decoder, next) { - return new Decoder( - (data) => { - let _block; - let _block$1; - let $1 = bare_index(data, key); - if ($1 instanceof Ok) { - let $2 = $1[0]; - if ($2 instanceof Some) { - let data$1 = $2[0]; - _block$1 = field_decoder.function(data$1); - } else { - _block$1 = [default$, toList([])]; - } - } else { - let kind = $1[0]; - _block$1 = [ - default$, - toList([new DecodeError(kind, $dynamic.classify(data), toList([]))]), - ]; - } - let _pipe = _block$1; - _block = push_path(_pipe, toList([key])); - let $ = _block; - let out; - let errors1; - out = $[0]; - errors1 = $[1]; - let $2 = next(out).function(data); - let out$1; - let errors2; - out$1 = $2[0]; - errors2 = $2[1]; - return [out$1, $list.append(errors1, errors2)]; - }, - ); -} - -/** - * A decoder that decodes a value that is nested within other values. For - * example, decoding a value that is within some deeply nested JSON objects. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * # Examples - * - * ```gleam - * let decoder = decode.optionally_at(["one", "two"], 100, decode.int) - * - * let data = dynamic.properties([ - * #(dynamic.string("one"), dynamic.properties([])), - * ])) - * - * - * decode.run(data, decoder) - * // -> Ok(100) - * ``` - */ -export function optionally_at(path, default$, inner) { - return new Decoder( - (data) => { - return index( - path, - toList([]), - inner.function, - data, - (_, _1) => { return [default$, toList([])]; }, - ); - }, - ); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/float.mjs b/build/dev/javascript/gleam_stdlib/gleam/float.mjs deleted file mode 100644 index 4f3aaa6..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/float.mjs +++ /dev/null @@ -1,553 +0,0 @@ -import { Ok, Error, Empty as $Empty, divideFloat } from "../gleam.mjs"; -import * as $order from "../gleam/order.mjs"; -import { - parse_float as parse, - float_to_string as to_string, - ceiling, - floor, - round as js_round, - truncate, - identity as do_to_float, - power as do_power, - random_uniform as random, - log as do_log, - exp as exponential, -} from "../gleam_stdlib.mjs"; - -export { ceiling, exponential, floor, parse, random, to_string, truncate }; - -/** - * Compares two `Float`s, returning an `Order`: - * `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. - * - * ## Examples - * - * ```gleam - * compare(2.0, 2.3) - * // -> Lt - * ``` - * - * To handle - * [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) - * you may use [`loosely_compare`](#loosely_compare) instead. - */ -export function compare(a, b) { - let $ = a === b; - if ($) { - return new $order.Eq(); - } else { - let $1 = a < b; - if ($1) { - return new $order.Lt(); - } else { - return new $order.Gt(); - } - } -} - -/** - * Compares two `Float`s, returning the smaller of the two. - * - * ## Examples - * - * ```gleam - * min(2.0, 2.3) - * // -> 2.0 - * ``` - */ -export function min(a, b) { - let $ = a < b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Compares two `Float`s, returning the larger of the two. - * - * ## Examples - * - * ```gleam - * max(2.0, 2.3) - * // -> 2.3 - * ``` - */ -export function max(a, b) { - let $ = a > b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Restricts a `Float` between a lower and upper bound. - * - * ## Examples - * - * ```gleam - * clamp(1.2, min: 1.4, max: 1.6) - * // -> 1.4 - * ``` - */ -export function clamp(x, min_bound, max_bound) { - let _pipe = x; - let _pipe$1 = min(_pipe, max_bound); - return max(_pipe$1, min_bound); -} - -/** - * Returns the absolute value of the input as a `Float`. - * - * ## Examples - * - * ```gleam - * absolute_value(-12.5) - * // -> 12.5 - * ``` - * - * ```gleam - * absolute_value(10.2) - * // -> 10.2 - * ``` - */ -export function absolute_value(x) { - let $ = x >= 0.0; - if ($) { - return x; - } else { - return 0.0 - x; - } -} - -/** - * Compares two `Float`s within a tolerance, returning an `Order`: - * `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. - * - * This function allows Float comparison while handling - * [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). - * - * Notice: For `Float`s the tolerance won't be exact: - * `5.3 - 5.0` is not exactly `0.3`. - * - * ## Examples - * - * ```gleam - * loosely_compare(5.0, with: 5.3, tolerating: 0.5) - * // -> Eq - * ``` - * - * If you want to check only for equality you may use - * [`loosely_equals`](#loosely_equals) instead. - */ -export function loosely_compare(a, b, tolerance) { - let difference = absolute_value(a - b); - let $ = difference <= tolerance; - if ($) { - return new $order.Eq(); - } else { - return compare(a, b); - } -} - -/** - * Checks for equality of two `Float`s within a tolerance, - * returning an `Bool`. - * - * This function allows Float comparison while handling - * [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). - * - * Notice: For `Float`s the tolerance won't be exact: - * `5.3 - 5.0` is not exactly `0.3`. - * - * ## Examples - * - * ```gleam - * loosely_equals(5.0, with: 5.3, tolerating: 0.5) - * // -> True - * ``` - * - * ```gleam - * loosely_equals(5.0, with: 5.1, tolerating: 0.1) - * // -> False - * ``` - */ -export function loosely_equals(a, b, tolerance) { - let difference = absolute_value(a - b); - return difference <= tolerance; -} - -/** - * Returns the results of the base being raised to the power of the - * exponent, as a `Float`. - * - * ## Examples - * - * ```gleam - * power(2.0, -1.0) - * // -> Ok(0.5) - * ``` - * - * ```gleam - * power(2.0, 2.0) - * // -> Ok(4.0) - * ``` - * - * ```gleam - * power(8.0, 1.5) - * // -> Ok(22.627416997969522) - * ``` - * - * ```gleam - * 4.0 |> power(of: 2.0) - * // -> Ok(16.0) - * ``` - * - * ```gleam - * power(-1.0, 0.5) - * // -> Error(Nil) - * ``` - */ -export function power(base, exponent) { - let fractional = (ceiling(exponent) - exponent) > 0.0; - let $ = ((base < 0.0) && fractional) || ((base === 0.0) && (exponent < 0.0)); - if ($) { - return new Error(undefined); - } else { - return new Ok(do_power(base, exponent)); - } -} - -/** - * Returns the square root of the input as a `Float`. - * - * ## Examples - * - * ```gleam - * square_root(4.0) - * // -> Ok(2.0) - * ``` - * - * ```gleam - * square_root(-16.0) - * // -> Error(Nil) - * ``` - */ -export function square_root(x) { - return power(x, 0.5); -} - -/** - * Returns the negative of the value provided. - * - * ## Examples - * - * ```gleam - * negate(1.0) - * // -> -1.0 - * ``` - */ -export function negate(x) { - return -1.0 * x; -} - -/** - * Rounds the value to the nearest whole number as an `Int`. - * - * ## Examples - * - * ```gleam - * round(2.3) - * // -> 2 - * ``` - * - * ```gleam - * round(2.5) - * // -> 3 - * ``` - */ -export function round(x) { - let $ = x >= 0.0; - if ($) { - return js_round(x); - } else { - return 0 - js_round(negate(x)); - } -} - -/** - * Converts the value to a given precision as a `Float`. - * The precision is the number of allowed decimal places. - * Negative precisions are allowed and force rounding - * to the nearest tenth, hundredth, thousandth etc. - * - * ## Examples - * - * ```gleam - * to_precision(2.43434348473, precision: 2) - * // -> 2.43 - * ``` - * - * ```gleam - * to_precision(547890.453444, precision: -3) - * // -> 548000.0 - * ``` - */ -export function to_precision(x, precision) { - let $ = precision <= 0; - if ($) { - let factor = do_power(10.0, do_to_float(- precision)); - return do_to_float(round(divideFloat(x, factor))) * factor; - } else { - let factor = do_power(10.0, do_to_float(precision)); - return divideFloat(do_to_float(round(x * factor)), factor); - } -} - -function sum_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first + initial; - } - } -} - -/** - * Sums a list of `Float`s. - * - * ## Example - * - * ```gleam - * sum([1.0, 2.2, 3.3]) - * // -> 6.5 - * ``` - */ -export function sum(numbers) { - return sum_loop(numbers, 0.0); -} - -function product_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first * initial; - } - } -} - -/** - * Multiplies a list of `Float`s and returns the product. - * - * ## Example - * - * ```gleam - * product([2.5, 3.2, 4.2]) - * // -> 33.6 - * ``` - */ -export function product(numbers) { - return product_loop(numbers, 1.0); -} - -/** - * Computes the modulo of an float division of inputs as a `Result`. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * ## Examples - * - * ```gleam - * modulo(13.3, by: 3.3) - * // -> Ok(0.1) - * ``` - * - * ```gleam - * modulo(-13.3, by: 3.3) - * // -> Ok(3.2) - * ``` - * - * ```gleam - * modulo(13.3, by: -3.3) - * // -> Ok(-3.2) - * ``` - * - * ```gleam - * modulo(-13.3, by: -3.3) - * // -> Ok(-0.1) - * ``` - */ -export function modulo(dividend, divisor) { - if (divisor === 0.0) { - return new Error(undefined); - } else { - return new Ok(dividend - (floor(divideFloat(dividend, divisor)) * divisor)); - } -} - -/** - * Returns division of the inputs as a `Result`. - * - * ## Examples - * - * ```gleam - * divide(0.0, 1.0) - * // -> Ok(0.0) - * ``` - * - * ```gleam - * divide(1.0, 0.0) - * // -> Error(Nil) - * ``` - */ -export function divide(a, b) { - if (b === 0.0) { - return new Error(undefined); - } else { - let b$1 = b; - return new Ok(divideFloat(a, b$1)); - } -} - -/** - * Adds two floats together. - * - * It's the function equivalent of the `+.` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * add(1.0, 2.0) - * // -> 3.0 - * ``` - * - * ```gleam - * import gleam/list - * - * list.fold([1.0, 2.0, 3.0], 0.0, add) - * // -> 6.0 - * ``` - * - * ```gleam - * 3.0 |> add(2.0) - * // -> 5.0 - * ``` - */ -export function add(a, b) { - return a + b; -} - -/** - * Multiplies two floats together. - * - * It's the function equivalent of the `*.` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * multiply(2.0, 4.0) - * // -> 8.0 - * ``` - * - * ```gleam - * import gleam/list - * - * list.fold([2.0, 3.0, 4.0], 1.0, multiply) - * // -> 24.0 - * ``` - * - * ```gleam - * 3.0 |> multiply(2.0) - * // -> 6.0 - * ``` - */ -export function multiply(a, b) { - return a * b; -} - -/** - * Subtracts one float from another. - * - * It's the function equivalent of the `-.` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * subtract(3.0, 1.0) - * // -> 2.0 - * ``` - * - * ```gleam - * import gleam/list - * - * list.fold([1.0, 2.0, 3.0], 10.0, subtract) - * // -> 4.0 - * ``` - * - * ```gleam - * 3.0 |> subtract(_, 2.0) - * // -> 1.0 - * ``` - * - * ```gleam - * 3.0 |> subtract(2.0, _) - * // -> -1.0 - * ``` - */ -export function subtract(a, b) { - return a - b; -} - -/** - * Returns the natural logarithm (base e) of the given as a `Result`. If the - * input is less than or equal to 0, returns `Error(Nil)`. - * - * ## Examples - * - * ```gleam - * logarithm(1.0) - * // -> Ok(0.0) - * ``` - * - * ```gleam - * logarithm(2.718281828459045) // e - * // -> Ok(1.0) - * ``` - * - * ```gleam - * logarithm(0.0) - * // -> Error(Nil) - * ``` - * - * ```gleam - * logarithm(-1.0) - * // -> Error(Nil) - * ``` - */ -export function logarithm(x) { - let $ = x <= 0.0; - if ($) { - return new Error(undefined); - } else { - return new Ok(do_log(x)); - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/function.mjs b/build/dev/javascript/gleam_stdlib/gleam/function.mjs deleted file mode 100644 index 2292fbc..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/function.mjs +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Takes a single argument and always returns its input value. - */ -export function identity(x) { - return x; -} - -/** - * Takes an argument and a single function, calls that function with that - * argument and returns that argument instead of the function return value. - * - * Useful for running synchronous side effects in a pipeline. - */ -export function tap(arg, effect) { - effect(arg); - return arg; -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/int.mjs b/build/dev/javascript/gleam_stdlib/gleam/int.mjs deleted file mode 100644 index 5824eb6..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/int.mjs +++ /dev/null @@ -1,816 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - remainderInt, - divideInt, -} from "../gleam.mjs"; -import * as $float from "../gleam/float.mjs"; -import * as $order from "../gleam/order.mjs"; -import { - parse_int as parse, - int_from_base_string as do_base_parse, - to_string, - int_to_base_string as do_to_base_string, - identity as to_float, - bitwise_and, - bitwise_not, - bitwise_or, - bitwise_exclusive_or, - bitwise_shift_left, - bitwise_shift_right, -} from "../gleam_stdlib.mjs"; - -export { - bitwise_and, - bitwise_exclusive_or, - bitwise_not, - bitwise_or, - bitwise_shift_left, - bitwise_shift_right, - parse, - to_float, - to_string, -}; - -/** - * Returns the absolute value of the input. - * - * ## Examples - * - * ```gleam - * absolute_value(-12) - * // -> 12 - * ``` - * - * ```gleam - * absolute_value(10) - * // -> 10 - * ``` - */ -export function absolute_value(x) { - let $ = x >= 0; - if ($) { - return x; - } else { - return x * -1; - } -} - -/** - * Parses a given string as an int in a given base if possible. - * Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. - * - * ## Examples - * - * ```gleam - * base_parse("10", 2) - * // -> Ok(2) - * ``` - * - * ```gleam - * base_parse("30", 16) - * // -> Ok(48) - * ``` - * - * ```gleam - * base_parse("1C", 36) - * // -> Ok(48) - * ``` - * - * ```gleam - * base_parse("48", 1) - * // -> Error(Nil) - * ``` - * - * ```gleam - * base_parse("48", 37) - * // -> Error(Nil) - * ``` - */ -export function base_parse(string, base) { - let $ = (base >= 2) && (base <= 36); - if ($) { - return do_base_parse(string, base); - } else { - return new Error(undefined); - } -} - -/** - * Prints a given int to a string using the base number provided. - * Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. - * For common bases (2, 8, 16, 36), use the `to_baseN` functions. - * - * ## Examples - * - * ```gleam - * to_base_string(2, 2) - * // -> Ok("10") - * ``` - * - * ```gleam - * to_base_string(48, 16) - * // -> Ok("30") - * ``` - * - * ```gleam - * to_base_string(48, 36) - * // -> Ok("1C") - * ``` - * - * ```gleam - * to_base_string(48, 1) - * // -> Error(Nil) - * ``` - * - * ```gleam - * to_base_string(48, 37) - * // -> Error(Nil) - * ``` - */ -export function to_base_string(x, base) { - let $ = (base >= 2) && (base <= 36); - if ($) { - return new Ok(do_to_base_string(x, base)); - } else { - return new Error(undefined); - } -} - -/** - * Prints a given int to a string using base-2. - * - * ## Examples - * - * ```gleam - * to_base2(2) - * // -> "10" - * ``` - */ -export function to_base2(x) { - return do_to_base_string(x, 2); -} - -/** - * Prints a given int to a string using base-8. - * - * ## Examples - * - * ```gleam - * to_base8(15) - * // -> "17" - * ``` - */ -export function to_base8(x) { - return do_to_base_string(x, 8); -} - -/** - * Prints a given int to a string using base-16. - * - * ## Examples - * - * ```gleam - * to_base16(48) - * // -> "30" - * ``` - */ -export function to_base16(x) { - return do_to_base_string(x, 16); -} - -/** - * Prints a given int to a string using base-36. - * - * ## Examples - * - * ```gleam - * to_base36(48) - * // -> "1C" - * ``` - */ -export function to_base36(x) { - return do_to_base_string(x, 36); -} - -/** - * Returns the results of the base being raised to the power of the - * exponent, as a `Float`. - * - * ## Examples - * - * ```gleam - * power(2, -1.0) - * // -> Ok(0.5) - * ``` - * - * ```gleam - * power(2, 2.0) - * // -> Ok(4.0) - * ``` - * - * ```gleam - * power(8, 1.5) - * // -> Ok(22.627416997969522) - * ``` - * - * ```gleam - * 4 |> power(of: 2.0) - * // -> Ok(16.0) - * ``` - * - * ```gleam - * power(-1, 0.5) - * // -> Error(Nil) - * ``` - */ -export function power(base, exponent) { - let _pipe = base; - let _pipe$1 = to_float(_pipe); - return $float.power(_pipe$1, exponent); -} - -/** - * Returns the square root of the input as a `Float`. - * - * ## Examples - * - * ```gleam - * square_root(4) - * // -> Ok(2.0) - * ``` - * - * ```gleam - * square_root(-16) - * // -> Error(Nil) - * ``` - */ -export function square_root(x) { - let _pipe = x; - let _pipe$1 = to_float(_pipe); - return $float.square_root(_pipe$1); -} - -/** - * Compares two ints, returning an order. - * - * ## Examples - * - * ```gleam - * compare(2, 3) - * // -> Lt - * ``` - * - * ```gleam - * compare(4, 3) - * // -> Gt - * ``` - * - * ```gleam - * compare(3, 3) - * // -> Eq - * ``` - */ -export function compare(a, b) { - let $ = a === b; - if ($) { - return new $order.Eq(); - } else { - let $1 = a < b; - if ($1) { - return new $order.Lt(); - } else { - return new $order.Gt(); - } - } -} - -/** - * Compares two ints, returning the smaller of the two. - * - * ## Examples - * - * ```gleam - * min(2, 3) - * // -> 2 - * ``` - */ -export function min(a, b) { - let $ = a < b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Compares two ints, returning the larger of the two. - * - * ## Examples - * - * ```gleam - * max(2, 3) - * // -> 3 - * ``` - */ -export function max(a, b) { - let $ = a > b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Restricts an int between a lower and upper bound. - * - * ## Examples - * - * ```gleam - * clamp(40, min: 50, max: 60) - * // -> 50 - * ``` - */ -export function clamp(x, min_bound, max_bound) { - let _pipe = x; - let _pipe$1 = min(_pipe, max_bound); - return max(_pipe$1, min_bound); -} - -/** - * Returns whether the value provided is even. - * - * ## Examples - * - * ```gleam - * is_even(2) - * // -> True - * ``` - * - * ```gleam - * is_even(3) - * // -> False - * ``` - */ -export function is_even(x) { - return (x % 2) === 0; -} - -/** - * Returns whether the value provided is odd. - * - * ## Examples - * - * ```gleam - * is_odd(3) - * // -> True - * ``` - * - * ```gleam - * is_odd(2) - * // -> False - * ``` - */ -export function is_odd(x) { - return (x % 2) !== 0; -} - -/** - * Returns the negative of the value provided. - * - * ## Examples - * - * ```gleam - * negate(1) - * // -> -1 - * ``` - */ -export function negate(x) { - return -1 * x; -} - -function sum_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first + initial; - } - } -} - -/** - * Sums a list of ints. - * - * ## Example - * - * ```gleam - * sum([1, 2, 3]) - * // -> 6 - * ``` - */ -export function sum(numbers) { - return sum_loop(numbers, 0); -} - -function product_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first * initial; - } - } -} - -/** - * Multiplies a list of ints and returns the product. - * - * ## Example - * - * ```gleam - * product([2, 3, 4]) - * // -> 24 - * ``` - */ -export function product(numbers) { - return product_loop(numbers, 1); -} - -function digits_loop(loop$x, loop$base, loop$acc) { - while (true) { - let x = loop$x; - let base = loop$base; - let acc = loop$acc; - let $ = absolute_value(x) < base; - if ($) { - return listPrepend(x, acc); - } else { - loop$x = divideInt(x, base); - loop$base = base; - loop$acc = listPrepend(remainderInt(x, base), acc); - } - } -} - -export function digits(x, base) { - let $ = base < 2; - if ($) { - return new Error(undefined); - } else { - return new Ok(digits_loop(x, base, toList([]))); - } -} - -function undigits_loop(loop$numbers, loop$base, loop$acc) { - while (true) { - let numbers = loop$numbers; - let base = loop$base; - let acc = loop$acc; - if (numbers instanceof $Empty) { - return new Ok(acc); - } else { - let digit = numbers.head; - if (digit >= base) { - return new Error(undefined); - } else { - let digit$1 = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$base = base; - loop$acc = acc * base + digit$1; - } - } - } -} - -export function undigits(numbers, base) { - let $ = base < 2; - if ($) { - return new Error(undefined); - } else { - return undigits_loop(numbers, base, 0); - } -} - -/** - * Generates a random int between zero and the given maximum. - * - * The lower number is inclusive, the upper number is exclusive. - * - * ## Examples - * - * ```gleam - * random(10) - * // -> 4 - * ``` - * - * ```gleam - * random(1) - * // -> 0 - * ``` - * - * ```gleam - * random(-1) - * // -> -1 - * ``` - */ -export function random(max) { - let _pipe = ($float.random() * to_float(max)); - let _pipe$1 = $float.floor(_pipe); - return $float.round(_pipe$1); -} - -/** - * Performs a truncated integer division. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * ## Examples - * - * ```gleam - * divide(0, 1) - * // -> Ok(0) - * ``` - * - * ```gleam - * divide(1, 0) - * // -> Error(Nil) - * ``` - * - * ```gleam - * divide(5, 2) - * // -> Ok(2) - * ``` - * - * ```gleam - * divide(-99, 2) - * // -> Ok(-49) - * ``` - */ -export function divide(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let divisor$1 = divisor; - return new Ok(divideInt(dividend, divisor$1)); - } -} - -/** - * Computes the remainder of an integer division of inputs as a `Result`. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * Most the time you will want to use the `%` operator instead of this - * function. - * - * ## Examples - * - * ```gleam - * remainder(3, 2) - * // -> Ok(1) - * ``` - * - * ```gleam - * remainder(1, 0) - * // -> Error(Nil) - * ``` - * - * ```gleam - * remainder(10, -1) - * // -> Ok(0) - * ``` - * - * ```gleam - * remainder(13, by: 3) - * // -> Ok(1) - * ``` - * - * ```gleam - * remainder(-13, by: 3) - * // -> Ok(-1) - * ``` - * - * ```gleam - * remainder(13, by: -3) - * // -> Ok(1) - * ``` - * - * ```gleam - * remainder(-13, by: -3) - * // -> Ok(-1) - * ``` - */ -export function remainder(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let divisor$1 = divisor; - return new Ok(remainderInt(dividend, divisor$1)); - } -} - -/** - * Computes the modulo of an integer division of inputs as a `Result`. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * Most the time you will want to use the `%` operator instead of this - * function. - * - * ## Examples - * - * ```gleam - * modulo(3, 2) - * // -> Ok(1) - * ``` - * - * ```gleam - * modulo(1, 0) - * // -> Error(Nil) - * ``` - * - * ```gleam - * modulo(10, -1) - * // -> Ok(0) - * ``` - * - * ```gleam - * modulo(13, by: 3) - * // -> Ok(1) - * ``` - * - * ```gleam - * modulo(-13, by: 3) - * // -> Ok(2) - * ``` - */ -export function modulo(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let remainder$1 = remainderInt(dividend, divisor); - let $ = remainder$1 * divisor < 0; - if ($) { - return new Ok(remainder$1 + divisor); - } else { - return new Ok(remainder$1); - } - } -} - -/** - * Performs a *floored* integer division, which means that the result will - * always be rounded towards negative infinity. - * - * If you want to perform truncated integer division (rounding towards zero), - * use `int.divide()` or the `/` operator instead. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * ## Examples - * - * ```gleam - * floor_divide(1, 0) - * // -> Error(Nil) - * ``` - * - * ```gleam - * floor_divide(5, 2) - * // -> Ok(2) - * ``` - * - * ```gleam - * floor_divide(6, -4) - * // -> Ok(-2) - * ``` - * - * ```gleam - * floor_divide(-99, 2) - * // -> Ok(-50) - * ``` - */ -export function floor_divide(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let divisor$1 = divisor; - let $ = (dividend * divisor$1 < 0) && ((remainderInt(dividend, divisor$1)) !== 0); - if ($) { - return new Ok((divideInt(dividend, divisor$1)) - 1); - } else { - return new Ok(divideInt(dividend, divisor$1)); - } - } -} - -/** - * Adds two integers together. - * - * It's the function equivalent of the `+` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * add(1, 2) - * // -> 3 - * ``` - * - * ```gleam - * import gleam/list - * list.fold([1, 2, 3], 0, add) - * // -> 6 - * ``` - * - * ```gleam - * 3 |> add(2) - * // -> 5 - * ``` - */ -export function add(a, b) { - return a + b; -} - -/** - * Multiplies two integers together. - * - * It's the function equivalent of the `*` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * multiply(2, 4) - * // -> 8 - * ``` - * - * ```gleam - * import gleam/list - * - * list.fold([2, 3, 4], 1, multiply) - * // -> 24 - * ``` - * - * ```gleam - * 3 |> multiply(2) - * // -> 6 - * ``` - */ -export function multiply(a, b) { - return a * b; -} - -/** - * Subtracts one int from another. - * - * It's the function equivalent of the `-` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * subtract(3, 1) - * // -> 2 - * ``` - * - * ```gleam - * import gleam/list - * - * list.fold([1, 2, 3], 10, subtract) - * // -> 4 - * ``` - * - * ```gleam - * 3 |> subtract(2) - * // -> 1 - * ``` - * - * ```gleam - * 3 |> subtract(2, _) - * // -> -1 - * ``` - */ -export function subtract(a, b) { - return a - b; -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/io.mjs b/build/dev/javascript/gleam_stdlib/gleam/io.mjs deleted file mode 100644 index ddab435..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/io.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import { - print, - print_error, - console_log as println, - console_error as println_error, -} from "../gleam_stdlib.mjs"; - -export { print, print_error, println, println_error }; diff --git a/build/dev/javascript/gleam_stdlib/gleam/list.mjs b/build/dev/javascript/gleam_stdlib/gleam/list.mjs deleted file mode 100644 index 2ea158e..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/list.mjs +++ /dev/null @@ -1,3209 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - makeError, - divideFloat, - isEqual, -} from "../gleam.mjs"; -import * as $dict from "../gleam/dict.mjs"; -import * as $float from "../gleam/float.mjs"; -import * as $int from "../gleam/int.mjs"; -import * as $order from "../gleam/order.mjs"; - -const FILEPATH = "src/gleam/list.gleam"; - -export class Continue extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const ContinueOrStop$Continue = ($0) => new Continue($0); -export const ContinueOrStop$isContinue = (value) => value instanceof Continue; -export const ContinueOrStop$Continue$0 = (value) => value[0]; - -export class Stop extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const ContinueOrStop$Stop = ($0) => new Stop($0); -export const ContinueOrStop$isStop = (value) => value instanceof Stop; -export const ContinueOrStop$Stop$0 = (value) => value[0]; - -class Ascending extends $CustomType {} - -class Descending extends $CustomType {} - -function length_loop(loop$list, loop$count) { - while (true) { - let list = loop$list; - let count = loop$count; - if (list instanceof $Empty) { - return count; - } else { - let list$1 = list.tail; - loop$list = list$1; - loop$count = count + 1; - } - } -} - -/** - * Counts the number of elements in a given list. - * - * This function has to traverse the list to determine the number of elements, - * so it runs in linear time. - * - * This function is natively implemented by the virtual machine and is highly - * optimised. - * - * ## Examples - * - * ```gleam - * length([]) - * // -> 0 - * ``` - * - * ```gleam - * length([1]) - * // -> 1 - * ``` - * - * ```gleam - * length([1, 2]) - * // -> 2 - * ``` - */ -export function length(list) { - return length_loop(list, 0); -} - -function count_loop(loop$list, loop$predicate, loop$acc) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - let acc = loop$acc; - if (list instanceof $Empty) { - return acc; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - loop$acc = acc + 1; - } else { - loop$list = rest$1; - loop$predicate = predicate; - loop$acc = acc; - } - } - } -} - -/** - * Counts the number of elements in a given list satisfying a given predicate. - * - * This function has to traverse the list to determine the number of elements, - * so it runs in linear time. - * - * ## Examples - * - * ```gleam - * count([], fn(a) { a > 0 }) - * // -> 0 - * ``` - * - * ```gleam - * count([1], fn(a) { a > 0 }) - * // -> 1 - * ``` - * - * ```gleam - * count([1, 2, 3], int.is_odd) - * // -> 2 - * ``` - */ -export function count(list, predicate) { - return count_loop(list, predicate, 0); -} - -/** - * Reverses a list and prepends it to another list. - * This function runs in linear time, proportional to the length of the list - * to prepend. - * - * @ignore - */ -function reverse_and_prepend(loop$prefix, loop$suffix) { - while (true) { - let prefix = loop$prefix; - let suffix = loop$suffix; - if (prefix instanceof $Empty) { - return suffix; - } else { - let first$1 = prefix.head; - let rest$1 = prefix.tail; - loop$prefix = rest$1; - loop$suffix = listPrepend(first$1, suffix); - } - } -} - -/** - * Creates a new list from a given list containing the same elements but in the - * opposite order. - * - * This function has to traverse the list to create the new reversed list, so - * it runs in linear time. - * - * This function is natively implemented by the virtual machine and is highly - * optimised. - * - * ## Examples - * - * ```gleam - * reverse([]) - * // -> [] - * ``` - * - * ```gleam - * reverse([1]) - * // -> [1] - * ``` - * - * ```gleam - * reverse([1, 2]) - * // -> [2, 1] - * ``` - */ -export function reverse(list) { - return reverse_and_prepend(list, toList([])); -} - -/** - * Determines whether or not the list is empty. - * - * This function runs in constant time. - * - * ## Examples - * - * ```gleam - * is_empty([]) - * // -> True - * ``` - * - * ```gleam - * is_empty([1]) - * // -> False - * ``` - * - * ```gleam - * is_empty([1, 1]) - * // -> False - * ``` - */ -export function is_empty(list) { - return isEqual(list, toList([])); -} - -/** - * Determines whether or not a given element exists within a given list. - * - * This function traverses the list to find the element, so it runs in linear - * time. - * - * ## Examples - * - * ```gleam - * [] |> contains(any: 0) - * // -> False - * ``` - * - * ```gleam - * [0] |> contains(any: 0) - * // -> True - * ``` - * - * ```gleam - * [1] |> contains(any: 0) - * // -> False - * ``` - * - * ```gleam - * [1, 1] |> contains(any: 0) - * // -> False - * ``` - * - * ```gleam - * [1, 0] |> contains(any: 0) - * // -> True - * ``` - */ -export function contains(loop$list, loop$elem) { - while (true) { - let list = loop$list; - let elem = loop$elem; - if (list instanceof $Empty) { - return false; - } else { - let first$1 = list.head; - if (isEqual(first$1, elem)) { - return true; - } else { - let rest$1 = list.tail; - loop$list = rest$1; - loop$elem = elem; - } - } - } -} - -/** - * Gets the first element from the start of the list, if there is one. - * - * ## Examples - * - * ```gleam - * first([]) - * // -> Error(Nil) - * ``` - * - * ```gleam - * first([0]) - * // -> Ok(0) - * ``` - * - * ```gleam - * first([1, 2]) - * // -> Ok(1) - * ``` - */ -export function first(list) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - return new Ok(first$1); - } -} - -/** - * Returns the list minus the first element. If the list is empty, `Error(Nil)` is - * returned. - * - * This function runs in constant time and does not make a copy of the list. - * - * ## Examples - * - * ```gleam - * rest([]) - * // -> Error(Nil) - * ``` - * - * ```gleam - * rest([0]) - * // -> Ok([]) - * ``` - * - * ```gleam - * rest([1, 2]) - * // -> Ok([2]) - * ``` - */ -export function rest(list) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let rest$1 = list.tail; - return new Ok(rest$1); - } -} - -function group_loop(loop$list, loop$to_key, loop$groups) { - while (true) { - let list = loop$list; - let to_key = loop$to_key; - let groups = loop$groups; - if (list instanceof $Empty) { - return groups; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let key = to_key(first$1); - let _block; - let $ = $dict.get(groups, key); - if ($ instanceof Ok) { - let existing = $[0]; - _block = $dict.insert(groups, key, listPrepend(first$1, existing)); - } else { - _block = $dict.insert(groups, key, toList([first$1])); - } - let groups$1 = _block; - loop$list = rest$1; - loop$to_key = to_key; - loop$groups = groups$1; - } - } -} - -/** - * Groups the elements from the given list by the given key function. - * - * Does not preserve the initial value order. - * - * ## Examples - * - * ```gleam - * import gleam/dict - * - * [Ok(3), Error("Wrong"), Ok(200), Ok(73)] - * |> group(by: fn(i) { - * case i { - * Ok(_) -> "Successful" - * Error(_) -> "Failed" - * } - * }) - * |> dict.to_list - * // -> [ - * // #("Failed", [Error("Wrong")]), - * // #("Successful", [Ok(73), Ok(200), Ok(3)]) - * // ] - * ``` - * - * ```gleam - * import gleam/dict - * - * group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 }) - * |> dict.to_list - * // -> [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])] - * ``` - */ -export function group(list, key) { - return group_loop(list, key, $dict.new$()); -} - -function filter_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let _block; - let $ = fun(first$1); - if ($) { - _block = listPrepend(first$1, acc); - } else { - _block = acc; - } - let new_acc = _block; - loop$list = rest$1; - loop$fun = fun; - loop$acc = new_acc; - } - } -} - -/** - * Returns a new list containing only the elements from the first list for - * which the given functions returns `True`. - * - * ## Examples - * - * ```gleam - * filter([2, 4, 6, 1], fn(x) { x > 2 }) - * // -> [4, 6] - * ``` - * - * ```gleam - * filter([2, 4, 6, 1], fn(x) { x > 6 }) - * // -> [] - * ``` - */ -export function filter(list, predicate) { - return filter_loop(list, predicate, toList([])); -} - -function filter_map_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let _block; - let $ = fun(first$1); - if ($ instanceof Ok) { - let first$2 = $[0]; - _block = listPrepend(first$2, acc); - } else { - _block = acc; - } - let new_acc = _block; - loop$list = rest$1; - loop$fun = fun; - loop$acc = new_acc; - } - } -} - -/** - * Returns a new list containing only the elements from the first list for - * which the given functions returns `Ok(_)`. - * - * ## Examples - * - * ```gleam - * filter_map([2, 4, 6, 1], Error) - * // -> [] - * ``` - * - * ```gleam - * filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) - * // -> [3, 5, 7, 2] - * ``` - */ -export function filter_map(list, fun) { - return filter_map_loop(list, fun, toList([])); -} - -function map_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$fun = fun; - loop$acc = listPrepend(fun(first$1), acc); - } - } -} - -/** - * Returns a new list containing only the elements of the first list after the - * function has been applied to each one. - * - * ## Examples - * - * ```gleam - * map([2, 4, 6], fn(x) { x * 2 }) - * // -> [4, 8, 12] - * ``` - */ -export function map(list, fun) { - return map_loop(list, fun, toList([])); -} - -function map2_loop(loop$list1, loop$list2, loop$fun, loop$acc) { - while (true) { - let list1 = loop$list1; - let list2 = loop$list2; - let fun = loop$fun; - let acc = loop$acc; - if (list1 instanceof $Empty) { - return reverse(acc); - } else if (list2 instanceof $Empty) { - return reverse(acc); - } else { - let a = list1.head; - let as_ = list1.tail; - let b = list2.head; - let bs = list2.tail; - loop$list1 = as_; - loop$list2 = bs; - loop$fun = fun; - loop$acc = listPrepend(fun(a, b), acc); - } - } -} - -/** - * Combines two lists into a single list using the given function. - * - * If a list is longer than the other the extra elements are dropped. - * - * ## Examples - * - * ```gleam - * map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) - * // -> [5, 7, 9] - * ``` - * - * ```gleam - * map2([1, 2], ["a", "b", "c"], fn(i, x) { #(i, x) }) - * // -> [#(1, "a"), #(2, "b")] - * ``` - */ -export function map2(list1, list2, fun) { - return map2_loop(list1, list2, fun, toList([])); -} - -function map_fold_loop(loop$list, loop$fun, loop$acc, loop$list_acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - let list_acc = loop$list_acc; - if (list instanceof $Empty) { - return [acc, reverse(list_acc)]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(acc, first$1); - let acc$1; - let first$2; - acc$1 = $[0]; - first$2 = $[1]; - loop$list = rest$1; - loop$fun = fun; - loop$acc = acc$1; - loop$list_acc = listPrepend(first$2, list_acc); - } - } -} - -/** - * Similar to `map` but also lets you pass around an accumulated value. - * - * ## Examples - * - * ```gleam - * map_fold( - * over: [1, 2, 3], - * from: 100, - * with: fn(memo, i) { #(memo + i, i * 2) } - * ) - * // -> #(106, [2, 4, 6]) - * ``` - */ -export function map_fold(list, initial, fun) { - return map_fold_loop(list, fun, initial, toList([])); -} - -function index_map_loop(loop$list, loop$fun, loop$index, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let index = loop$index; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let acc$1 = listPrepend(fun(first$1, index), acc); - loop$list = rest$1; - loop$fun = fun; - loop$index = index + 1; - loop$acc = acc$1; - } - } -} - -/** - * Returns a new list containing only the elements of the first list after the - * function has been applied to each one and their index. - * - * The index starts at 0, so the first element is 0, the second is 1, and so - * on. - * - * ## Examples - * - * ```gleam - * index_map(["a", "b"], fn(x, i) { #(i, x) }) - * // -> [#(0, "a"), #(1, "b")] - * ``` - */ -export function index_map(list, fun) { - return index_map_loop(list, fun, 0, toList([])); -} - -function try_map_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return new Ok(reverse(acc)); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(first$1); - if ($ instanceof Ok) { - let first$2 = $[0]; - loop$list = rest$1; - loop$fun = fun; - loop$acc = listPrepend(first$2, acc); - } else { - return $; - } - } - } -} - -/** - * Takes a function that returns a `Result` and applies it to each element in a - * given list in turn. - * - * If the function returns `Ok(new_value)` for all elements in the list then a - * list of the new values is returned. - * - * If the function returns `Error(reason)` for any of the elements then it is - * returned immediately. None of the elements in the list are processed after - * one returns an `Error`. - * - * ## Examples - * - * ```gleam - * try_map([1, 2, 3], fn(x) { Ok(x + 2) }) - * // -> Ok([3, 4, 5]) - * ``` - * - * ```gleam - * try_map([1, 2, 3], fn(_) { Error(0) }) - * // -> Error(0) - * ``` - * - * ```gleam - * try_map([[1], [2, 3]], first) - * // -> Ok([1, 2]) - * ``` - * - * ```gleam - * try_map([[1], [], [2]], first) - * // -> Error(Nil) - * ``` - */ -export function try_map(list, fun) { - return try_map_loop(list, fun, toList([])); -} - -/** - * Returns a list that is the given list with up to the given number of - * elements removed from the front of the list. - * - * If the element has less than the number of elements an empty list is - * returned. - * - * This function runs in linear time but does not copy the list. - * - * ## Examples - * - * ```gleam - * drop([1, 2, 3, 4], 2) - * // -> [3, 4] - * ``` - * - * ```gleam - * drop([1, 2, 3, 4], 9) - * // -> [] - * ``` - */ -export function drop(loop$list, loop$n) { - while (true) { - let list = loop$list; - let n = loop$n; - let $ = n <= 0; - if ($) { - return list; - } else { - if (list instanceof $Empty) { - return list; - } else { - let rest$1 = list.tail; - loop$list = rest$1; - loop$n = n - 1; - } - } - } -} - -function take_loop(loop$list, loop$n, loop$acc) { - while (true) { - let list = loop$list; - let n = loop$n; - let acc = loop$acc; - let $ = n <= 0; - if ($) { - return reverse(acc); - } else { - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$n = n - 1; - loop$acc = listPrepend(first$1, acc); - } - } - } -} - -/** - * Returns a list containing the first given number of elements from the given - * list. - * - * If the element has less than the number of elements then the full list is - * returned. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * take([1, 2, 3, 4], 2) - * // -> [1, 2] - * ``` - * - * ```gleam - * take([1, 2, 3, 4], 9) - * // -> [1, 2, 3, 4] - * ``` - */ -export function take(list, n) { - return take_loop(list, n, toList([])); -} - -/** - * Returns a new empty list. - * - * ## Examples - * - * ```gleam - * new() - * // -> [] - * ``` - */ -export function new$() { - return toList([]); -} - -/** - * Returns the given item wrapped in a list. - * - * ## Examples - * - * ```gleam - * wrap(1) - * // -> [1] - * - * wrap(["a", "b", "c"]) - * // -> [["a", "b", "c"]] - * - * wrap([[]]) - * // -> [[[]]] - * ``` - */ -export function wrap(item) { - return toList([item]); -} - -function append_loop(loop$first, loop$second) { - while (true) { - let first = loop$first; - let second = loop$second; - if (first instanceof $Empty) { - return second; - } else { - let first$1 = first.head; - let rest$1 = first.tail; - loop$first = rest$1; - loop$second = listPrepend(first$1, second); - } - } -} - -/** - * Joins one list onto the end of another. - * - * This function runs in linear time, and it traverses and copies the first - * list. - * - * ## Examples - * - * ```gleam - * append([1, 2], [3]) - * // -> [1, 2, 3] - * ``` - */ -export function append(first, second) { - return append_loop(reverse(first), second); -} - -/** - * Prefixes an item to a list. This can also be done using the dedicated - * syntax instead - * - * ```gleam - * let existing_list = [2, 3, 4] - * - * [1, ..existing_list] - * // -> [1, 2, 3, 4] - * - * prepend(to: existing_list, this: 1) - * // -> [1, 2, 3, 4] - * ``` - */ -export function prepend(list, item) { - return listPrepend(item, list); -} - -function flatten_loop(loop$lists, loop$acc) { - while (true) { - let lists = loop$lists; - let acc = loop$acc; - if (lists instanceof $Empty) { - return reverse(acc); - } else { - let list = lists.head; - let further_lists = lists.tail; - loop$lists = further_lists; - loop$acc = reverse_and_prepend(list, acc); - } - } -} - -/** - * Joins a list of lists into a single list. - * - * This function traverses all elements twice on the JavaScript target. - * This function traverses all elements once on the Erlang target. - * - * ## Examples - * - * ```gleam - * flatten([[1], [2, 3], []]) - * // -> [1, 2, 3] - * ``` - */ -export function flatten(lists) { - return flatten_loop(lists, toList([])); -} - -/** - * Maps the list with the given function into a list of lists, and then flattens it. - * - * ## Examples - * - * ```gleam - * flat_map([2, 4, 6], fn(x) { [x, x + 1] }) - * // -> [2, 3, 4, 5, 6, 7] - * ``` - */ -export function flat_map(list, fun) { - return flatten(map(list, fun)); -} - -/** - * Reduces a list of elements into a single value by calling a given function - * on each element, going from left to right. - * - * `fold([1, 2, 3], 0, add)` is the equivalent of - * `add(add(add(0, 1), 2), 3)`. - * - * This function runs in linear time. - */ -export function fold(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return initial; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$initial = fun(initial, first$1); - loop$fun = fun; - } - } -} - -/** - * Reduces a list of elements into a single value by calling a given function - * on each element, going from right to left. - * - * `fold_right([1, 2, 3], 0, add)` is the equivalent of - * `add(add(add(0, 3), 2), 1)`. - * - * This function runs in linear time. - * - * Unlike `fold` this function is not tail recursive. Where possible use - * `fold` instead as it will use less memory. - */ -export function fold_right(list, initial, fun) { - if (list instanceof $Empty) { - return initial; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return fun(fold_right(rest$1, initial, fun), first$1); - } -} - -function index_fold_loop(loop$over, loop$acc, loop$with, loop$index) { - while (true) { - let over = loop$over; - let acc = loop$acc; - let with$ = loop$with; - let index = loop$index; - if (over instanceof $Empty) { - return acc; - } else { - let first$1 = over.head; - let rest$1 = over.tail; - loop$over = rest$1; - loop$acc = with$(acc, first$1, index); - loop$with = with$; - loop$index = index + 1; - } - } -} - -/** - * Like fold but the folding function also receives the index of the current element. - * - * ## Examples - * - * ```gleam - * ["a", "b", "c"] - * |> index_fold("", fn(acc, item, index) { - * acc <> int.to_string(index) <> ":" <> item <> " " - * }) - * // -> "0:a 1:b 2:c" - * ``` - * - * ```gleam - * [10, 20, 30] - * |> index_fold(0, fn(acc, item, index) { acc + item * index }) - * // -> 80 - * ``` - */ -export function index_fold(list, initial, fun) { - return index_fold_loop(list, initial, fun, 0); -} - -/** - * A variant of fold that might fail. - * - * The folding function should return `Result(accumulator, error)`. - * If the returned value is `Ok(accumulator)` try_fold will try the next value in the list. - * If the returned value is `Error(error)` try_fold will stop and return that error. - * - * ## Examples - * - * ```gleam - * [1, 2, 3, 4] - * |> try_fold(0, fn(acc, i) { - * case i < 3 { - * True -> Ok(acc + i) - * False -> Error(Nil) - * } - * }) - * // -> Error(Nil) - * ``` - */ -export function try_fold(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return new Ok(initial); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(initial, first$1); - if ($ instanceof Ok) { - let result = $[0]; - loop$list = rest$1; - loop$initial = result; - loop$fun = fun; - } else { - return $; - } - } - } -} - -/** - * A variant of fold that allows to stop folding earlier. - * - * The folding function should return `ContinueOrStop(accumulator)`. - * If the returned value is `Continue(accumulator)` fold_until will try the next value in the list. - * If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator. - * - * ## Examples - * - * ```gleam - * [1, 2, 3, 4] - * |> fold_until(0, fn(acc, i) { - * case i < 3 { - * True -> Continue(acc + i) - * False -> Stop(acc) - * } - * }) - * // -> 3 - * ``` - */ -export function fold_until(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return initial; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(initial, first$1); - if ($ instanceof Continue) { - let next_accumulator = $[0]; - loop$list = rest$1; - loop$initial = next_accumulator; - loop$fun = fun; - } else { - let b = $[0]; - return b; - } - } - } -} - -/** - * Finds the first element in a given list for which the given function returns - * `True`. - * - * Returns `Error(Nil)` if no such element is found. - * - * ## Examples - * - * ```gleam - * find([1, 2, 3], fn(x) { x > 2 }) - * // -> Ok(3) - * ``` - * - * ```gleam - * find([1, 2, 3], fn(x) { x > 4 }) - * // -> Error(Nil) - * ``` - * - * ```gleam - * find([], fn(_) { True }) - * // -> Error(Nil) - * ``` - */ -export function find(loop$list, loop$is_desired) { - while (true) { - let list = loop$list; - let is_desired = loop$is_desired; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = is_desired(first$1); - if ($) { - return new Ok(first$1); - } else { - loop$list = rest$1; - loop$is_desired = is_desired; - } - } - } -} - -/** - * Finds the first element in a given list for which the given function returns - * `Ok(new_value)`, then returns the wrapped `new_value`. - * - * Returns `Error(Nil)` if no such element is found. - * - * ## Examples - * - * ```gleam - * find_map([[], [2], [3]], first) - * // -> Ok(2) - * ``` - * - * ```gleam - * find_map([[], []], first) - * // -> Error(Nil) - * ``` - * - * ```gleam - * find_map([], first) - * // -> Error(Nil) - * ``` - */ -export function find_map(loop$list, loop$fun) { - while (true) { - let list = loop$list; - let fun = loop$fun; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(first$1); - if ($ instanceof Ok) { - return $; - } else { - loop$list = rest$1; - loop$fun = fun; - } - } - } -} - -/** - * Returns `True` if the given function returns `True` for all the elements in - * the given list. If the function returns `False` for any of the elements it - * immediately returns `False` without checking the rest of the list. - * - * ## Examples - * - * ```gleam - * all([], fn(x) { x > 3 }) - * // -> True - * ``` - * - * ```gleam - * all([4, 5], fn(x) { x > 3 }) - * // -> True - * ``` - * - * ```gleam - * all([4, 3], fn(x) { x > 3 }) - * // -> False - * ``` - */ -export function all(loop$list, loop$predicate) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - if (list instanceof $Empty) { - return true; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - } else { - return $; - } - } - } -} - -/** - * Returns `True` if the given function returns `True` for any the elements in - * the given list. If the function returns `True` for any of the elements it - * immediately returns `True` without checking the rest of the list. - * - * ## Examples - * - * ```gleam - * any([], fn(x) { x > 3 }) - * // -> False - * ``` - * - * ```gleam - * any([4, 5], fn(x) { x > 3 }) - * // -> True - * ``` - * - * ```gleam - * any([4, 3], fn(x) { x > 4 }) - * // -> False - * ``` - * - * ```gleam - * any([3, 4], fn(x) { x > 3 }) - * // -> True - * ``` - */ -export function any(loop$list, loop$predicate) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - if (list instanceof $Empty) { - return false; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - return $; - } else { - loop$list = rest$1; - loop$predicate = predicate; - } - } - } -} - -function zip_loop(loop$one, loop$other, loop$acc) { - while (true) { - let one = loop$one; - let other = loop$other; - let acc = loop$acc; - if (one instanceof $Empty) { - return reverse(acc); - } else if (other instanceof $Empty) { - return reverse(acc); - } else { - let first_one = one.head; - let rest_one = one.tail; - let first_other = other.head; - let rest_other = other.tail; - loop$one = rest_one; - loop$other = rest_other; - loop$acc = listPrepend([first_one, first_other], acc); - } - } -} - -/** - * Takes two lists and returns a single list of 2-element tuples. - * - * If one of the lists is longer than the other, the remaining elements from - * the longer list are not used. - * - * ## Examples - * - * ```gleam - * zip([], []) - * // -> [] - * ``` - * - * ```gleam - * zip([1, 2], [3]) - * // -> [#(1, 3)] - * ``` - * - * ```gleam - * zip([1], [3, 4]) - * // -> [#(1, 3)] - * ``` - * - * ```gleam - * zip([1, 2], [3, 4]) - * // -> [#(1, 3), #(2, 4)] - * ``` - */ -export function zip(list, other) { - return zip_loop(list, other, toList([])); -} - -function strict_zip_loop(loop$one, loop$other, loop$acc) { - while (true) { - let one = loop$one; - let other = loop$other; - let acc = loop$acc; - if (one instanceof $Empty) { - if (other instanceof $Empty) { - return new Ok(reverse(acc)); - } else { - return new Error(undefined); - } - } else if (other instanceof $Empty) { - return new Error(undefined); - } else { - let first_one = one.head; - let rest_one = one.tail; - let first_other = other.head; - let rest_other = other.tail; - loop$one = rest_one; - loop$other = rest_other; - loop$acc = listPrepend([first_one, first_other], acc); - } - } -} - -/** - * Takes two lists and returns a single list of 2-element tuples. - * - * If one of the lists is longer than the other, an `Error` is returned. - * - * ## Examples - * - * ```gleam - * strict_zip([], []) - * // -> Ok([]) - * ``` - * - * ```gleam - * strict_zip([1, 2], [3]) - * // -> Error(Nil) - * ``` - * - * ```gleam - * strict_zip([1], [3, 4]) - * // -> Error(Nil) - * ``` - * - * ```gleam - * strict_zip([1, 2], [3, 4]) - * // -> Ok([#(1, 3), #(2, 4)]) - * ``` - */ -export function strict_zip(list, other) { - return strict_zip_loop(list, other, toList([])); -} - -function unzip_loop(loop$input, loop$one, loop$other) { - while (true) { - let input = loop$input; - let one = loop$one; - let other = loop$other; - if (input instanceof $Empty) { - return [reverse(one), reverse(other)]; - } else { - let rest$1 = input.tail; - let first_one = input.head[0]; - let first_other = input.head[1]; - loop$input = rest$1; - loop$one = listPrepend(first_one, one); - loop$other = listPrepend(first_other, other); - } - } -} - -/** - * Takes a single list of 2-element tuples and returns two lists. - * - * ## Examples - * - * ```gleam - * unzip([#(1, 2), #(3, 4)]) - * // -> #([1, 3], [2, 4]) - * ``` - * - * ```gleam - * unzip([]) - * // -> #([], []) - * ``` - */ -export function unzip(input) { - return unzip_loop(input, toList([]), toList([])); -} - -function intersperse_loop(loop$list, loop$separator, loop$acc) { - while (true) { - let list = loop$list; - let separator = loop$separator; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$separator = separator; - loop$acc = listPrepend(first$1, listPrepend(separator, acc)); - } - } -} - -/** - * Inserts a given value between each existing element in a given list. - * - * This function runs in linear time and copies the list. - * - * ## Examples - * - * ```gleam - * intersperse([1, 1, 1], 2) - * // -> [1, 2, 1, 2, 1] - * ``` - * - * ```gleam - * intersperse([], 2) - * // -> [] - * ``` - */ -export function intersperse(list, elem) { - if (list instanceof $Empty) { - return list; - } else { - let $ = list.tail; - if ($ instanceof $Empty) { - return list; - } else { - let first$1 = list.head; - let rest$1 = $; - return intersperse_loop(rest$1, elem, toList([first$1])); - } - } -} - -function unique_loop(loop$list, loop$seen, loop$acc) { - while (true) { - let list = loop$list; - let seen = loop$seen; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = $dict.has_key(seen, first$1); - if ($) { - loop$list = rest$1; - loop$seen = seen; - loop$acc = acc; - } else { - loop$list = rest$1; - loop$seen = $dict.insert(seen, first$1, undefined); - loop$acc = listPrepend(first$1, acc); - } - } - } -} - -/** - * Removes any duplicate elements from a given list. - * - * This function returns in loglinear time. - * - * ## Examples - * - * ```gleam - * unique([1, 1, 1, 4, 7, 3, 3, 4]) - * // -> [1, 4, 7, 3] - * ``` - */ -export function unique(list) { - return unique_loop(list, $dict.new$(), toList([])); -} - -/** - * Given a list it returns slices of it that are locally sorted in ascending - * order. - * - * Imagine you have this list: - * - * ``` - * [1, 2, 3, 2, 1, 0] - * ^^^^^^^ ^^^^^^^ This is a slice in descending order - * | - * | This is a slice that is sorted in ascending order - * ``` - * - * So the produced result will contain these two slices, each one sorted in - * ascending order: `[[1, 2, 3], [0, 1, 2]]`. - * - * - `growing` is an accumulator with the current slice being grown - * - `direction` is the growing direction of the slice being grown, it could - * either be ascending or strictly descending - * - `prev` is the previous element that needs to be added to the growing slice - * it is carried around to check whether we have to keep growing the current - * slice or not - * - `acc` is the accumulator containing the slices sorted in ascending order - * - * @ignore - */ -function sequences( - loop$list, - loop$compare, - loop$growing, - loop$direction, - loop$prev, - loop$acc -) { - while (true) { - let list = loop$list; - let compare = loop$compare; - let growing = loop$growing; - let direction = loop$direction; - let prev = loop$prev; - let acc = loop$acc; - let growing$1 = listPrepend(prev, growing); - if (list instanceof $Empty) { - if (direction instanceof Ascending) { - return listPrepend(reverse(growing$1), acc); - } else { - return listPrepend(growing$1, acc); - } - } else { - let new$1 = list.head; - let rest$1 = list.tail; - let $ = compare(prev, new$1); - if (direction instanceof Ascending) { - if ($ instanceof $order.Lt) { - loop$list = rest$1; - loop$compare = compare; - loop$growing = growing$1; - loop$direction = direction; - loop$prev = new$1; - loop$acc = acc; - } else if ($ instanceof $order.Eq) { - loop$list = rest$1; - loop$compare = compare; - loop$growing = growing$1; - loop$direction = direction; - loop$prev = new$1; - loop$acc = acc; - } else { - let _block; - if (direction instanceof Ascending) { - _block = listPrepend(reverse(growing$1), acc); - } else { - _block = listPrepend(growing$1, acc); - } - let acc$1 = _block; - if (rest$1 instanceof $Empty) { - return listPrepend(toList([new$1]), acc$1); - } else { - let next = rest$1.head; - let rest$2 = rest$1.tail; - let _block$1; - let $1 = compare(new$1, next); - if ($1 instanceof $order.Lt) { - _block$1 = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block$1 = new Ascending(); - } else { - _block$1 = new Descending(); - } - let direction$1 = _block$1; - loop$list = rest$2; - loop$compare = compare; - loop$growing = toList([new$1]); - loop$direction = direction$1; - loop$prev = next; - loop$acc = acc$1; - } - } - } else if ($ instanceof $order.Lt) { - let _block; - if (direction instanceof Ascending) { - _block = listPrepend(reverse(growing$1), acc); - } else { - _block = listPrepend(growing$1, acc); - } - let acc$1 = _block; - if (rest$1 instanceof $Empty) { - return listPrepend(toList([new$1]), acc$1); - } else { - let next = rest$1.head; - let rest$2 = rest$1.tail; - let _block$1; - let $1 = compare(new$1, next); - if ($1 instanceof $order.Lt) { - _block$1 = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block$1 = new Ascending(); - } else { - _block$1 = new Descending(); - } - let direction$1 = _block$1; - loop$list = rest$2; - loop$compare = compare; - loop$growing = toList([new$1]); - loop$direction = direction$1; - loop$prev = next; - loop$acc = acc$1; - } - } else if ($ instanceof $order.Eq) { - let _block; - if (direction instanceof Ascending) { - _block = listPrepend(reverse(growing$1), acc); - } else { - _block = listPrepend(growing$1, acc); - } - let acc$1 = _block; - if (rest$1 instanceof $Empty) { - return listPrepend(toList([new$1]), acc$1); - } else { - let next = rest$1.head; - let rest$2 = rest$1.tail; - let _block$1; - let $1 = compare(new$1, next); - if ($1 instanceof $order.Lt) { - _block$1 = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block$1 = new Ascending(); - } else { - _block$1 = new Descending(); - } - let direction$1 = _block$1; - loop$list = rest$2; - loop$compare = compare; - loop$growing = toList([new$1]); - loop$direction = direction$1; - loop$prev = next; - loop$acc = acc$1; - } - } else { - loop$list = rest$1; - loop$compare = compare; - loop$growing = growing$1; - loop$direction = direction; - loop$prev = new$1; - loop$acc = acc; - } - } - } -} - -/** - * Merges two lists sorted in ascending order into a single list sorted in - * descending order according to the given comparator function. - * - * This reversing of the sort order is not avoidable if we want to implement - * merge as a tail recursive function. We could reverse the accumulator before - * returning it but that would end up being less efficient; so the merging - * algorithm has to play around this. - * - * @ignore - */ -function merge_ascendings(loop$list1, loop$list2, loop$compare, loop$acc) { - while (true) { - let list1 = loop$list1; - let list2 = loop$list2; - let compare = loop$compare; - let acc = loop$acc; - if (list1 instanceof $Empty) { - let list = list2; - return reverse_and_prepend(list, acc); - } else if (list2 instanceof $Empty) { - let list = list1; - return reverse_and_prepend(list, acc); - } else { - let first1 = list1.head; - let rest1 = list1.tail; - let first2 = list2.head; - let rest2 = list2.tail; - let $ = compare(first1, first2); - if ($ instanceof $order.Lt) { - loop$list1 = rest1; - loop$list2 = list2; - loop$compare = compare; - loop$acc = listPrepend(first1, acc); - } else if ($ instanceof $order.Eq) { - loop$list1 = list1; - loop$list2 = rest2; - loop$compare = compare; - loop$acc = listPrepend(first2, acc); - } else { - loop$list1 = list1; - loop$list2 = rest2; - loop$compare = compare; - loop$acc = listPrepend(first2, acc); - } - } - } -} - -/** - * Given a list of ascending lists, it merges adjacent pairs into a single - * descending list, halving their number. - * It returns a list of the remaining descending lists. - * - * @ignore - */ -function merge_ascending_pairs(loop$sequences, loop$compare, loop$acc) { - while (true) { - let sequences = loop$sequences; - let compare = loop$compare; - let acc = loop$acc; - if (sequences instanceof $Empty) { - return reverse(acc); - } else { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return reverse(listPrepend(reverse(sequence), acc)); - } else { - let ascending1 = sequences.head; - let ascending2 = $.head; - let rest$1 = $.tail; - let descending = merge_ascendings( - ascending1, - ascending2, - compare, - toList([]), - ); - loop$sequences = rest$1; - loop$compare = compare; - loop$acc = listPrepend(descending, acc); - } - } - } -} - -/** - * This is exactly the same as merge_ascendings but mirrored: it merges two - * lists sorted in descending order into a single list sorted in ascending - * order according to the given comparator function. - * - * This reversing of the sort order is not avoidable if we want to implement - * merge as a tail recursive function. We could reverse the accumulator before - * returning it but that would end up being less efficient; so the merging - * algorithm has to play around this. - * - * @ignore - */ -function merge_descendings(loop$list1, loop$list2, loop$compare, loop$acc) { - while (true) { - let list1 = loop$list1; - let list2 = loop$list2; - let compare = loop$compare; - let acc = loop$acc; - if (list1 instanceof $Empty) { - let list = list2; - return reverse_and_prepend(list, acc); - } else if (list2 instanceof $Empty) { - let list = list1; - return reverse_and_prepend(list, acc); - } else { - let first1 = list1.head; - let rest1 = list1.tail; - let first2 = list2.head; - let rest2 = list2.tail; - let $ = compare(first1, first2); - if ($ instanceof $order.Lt) { - loop$list1 = list1; - loop$list2 = rest2; - loop$compare = compare; - loop$acc = listPrepend(first2, acc); - } else if ($ instanceof $order.Eq) { - loop$list1 = rest1; - loop$list2 = list2; - loop$compare = compare; - loop$acc = listPrepend(first1, acc); - } else { - loop$list1 = rest1; - loop$list2 = list2; - loop$compare = compare; - loop$acc = listPrepend(first1, acc); - } - } - } -} - -/** - * This is the same as merge_ascending_pairs but flipped for descending lists. - * - * @ignore - */ -function merge_descending_pairs(loop$sequences, loop$compare, loop$acc) { - while (true) { - let sequences = loop$sequences; - let compare = loop$compare; - let acc = loop$acc; - if (sequences instanceof $Empty) { - return reverse(acc); - } else { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return reverse(listPrepend(reverse(sequence), acc)); - } else { - let descending1 = sequences.head; - let descending2 = $.head; - let rest$1 = $.tail; - let ascending = merge_descendings( - descending1, - descending2, - compare, - toList([]), - ); - loop$sequences = rest$1; - loop$compare = compare; - loop$acc = listPrepend(ascending, acc); - } - } - } -} - -/** - * Given some some sorted sequences (assumed to be sorted in `direction`) it - * merges them all together until we're left with just a list sorted in - * ascending order. - * - * @ignore - */ -function merge_all(loop$sequences, loop$direction, loop$compare) { - while (true) { - let sequences = loop$sequences; - let direction = loop$direction; - let compare = loop$compare; - if (sequences instanceof $Empty) { - return sequences; - } else if (direction instanceof Ascending) { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return sequence; - } else { - let sequences$1 = merge_ascending_pairs(sequences, compare, toList([])); - loop$sequences = sequences$1; - loop$direction = new Descending(); - loop$compare = compare; - } - } else { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return reverse(sequence); - } else { - let sequences$1 = merge_descending_pairs(sequences, compare, toList([])); - loop$sequences = sequences$1; - loop$direction = new Ascending(); - loop$compare = compare; - } - } - } -} - -/** - * Sorts from smallest to largest based upon the ordering specified by a given - * function. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) - * // -> [1, 2, 3, 4, 4, 5, 6] - * ``` - */ -export function sort(list, compare) { - if (list instanceof $Empty) { - return list; - } else { - let $ = list.tail; - if ($ instanceof $Empty) { - return list; - } else { - let x = list.head; - let y = $.head; - let rest$1 = $.tail; - let _block; - let $1 = compare(x, y); - if ($1 instanceof $order.Lt) { - _block = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block = new Ascending(); - } else { - _block = new Descending(); - } - let direction = _block; - let sequences$1 = sequences( - rest$1, - compare, - toList([x]), - direction, - y, - toList([]), - ); - return merge_all(sequences$1, new Ascending(), compare); - } - } -} - -function range_loop(loop$start, loop$stop, loop$acc) { - while (true) { - let start = loop$start; - let stop = loop$stop; - let acc = loop$acc; - let $ = $int.compare(start, stop); - if ($ instanceof $order.Lt) { - loop$start = start; - loop$stop = stop - 1; - loop$acc = listPrepend(stop, acc); - } else if ($ instanceof $order.Eq) { - return listPrepend(stop, acc); - } else { - loop$start = start; - loop$stop = stop + 1; - loop$acc = listPrepend(stop, acc); - } - } -} - -/** - * Creates a list of ints ranging from a given start and finish. - * - * ## Examples - * - * ```gleam - * range(0, 0) - * // -> [0] - * ``` - * - * ```gleam - * range(0, 5) - * // -> [0, 1, 2, 3, 4, 5] - * ``` - * - * ```gleam - * range(1, -5) - * // -> [1, 0, -1, -2, -3, -4, -5] - * ``` - */ -export function range(start, stop) { - return range_loop(start, stop, toList([])); -} - -function repeat_loop(loop$item, loop$times, loop$acc) { - while (true) { - let item = loop$item; - let times = loop$times; - let acc = loop$acc; - let $ = times <= 0; - if ($) { - return acc; - } else { - loop$item = item; - loop$times = times - 1; - loop$acc = listPrepend(item, acc); - } - } -} - -/** - * Builds a list of a given value a given number of times. - * - * ## Examples - * - * ```gleam - * repeat("a", times: 0) - * // -> [] - * ``` - * - * ```gleam - * repeat("a", times: 5) - * // -> ["a", "a", "a", "a", "a"] - * ``` - */ -export function repeat(a, times) { - return repeat_loop(a, times, toList([])); -} - -function split_loop(loop$list, loop$n, loop$taken) { - while (true) { - let list = loop$list; - let n = loop$n; - let taken = loop$taken; - let $ = n <= 0; - if ($) { - return [reverse(taken), list]; - } else { - if (list instanceof $Empty) { - return [reverse(taken), toList([])]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$n = n - 1; - loop$taken = listPrepend(first$1, taken); - } - } - } -} - -/** - * Splits a list in two before the given index. - * - * If the list is not long enough to have the given index the before list will - * be the input list, and the after list will be empty. - * - * ## Examples - * - * ```gleam - * split([6, 7, 8, 9], 0) - * // -> #([], [6, 7, 8, 9]) - * ``` - * - * ```gleam - * split([6, 7, 8, 9], 2) - * // -> #([6, 7], [8, 9]) - * ``` - * - * ```gleam - * split([6, 7, 8, 9], 4) - * // -> #([6, 7, 8, 9], []) - * ``` - */ -export function split(list, index) { - return split_loop(list, index, toList([])); -} - -function split_while_loop(loop$list, loop$f, loop$acc) { - while (true) { - let list = loop$list; - let f = loop$f; - let acc = loop$acc; - if (list instanceof $Empty) { - return [reverse(acc), toList([])]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = f(first$1); - if ($) { - loop$list = rest$1; - loop$f = f; - loop$acc = listPrepend(first$1, acc); - } else { - return [reverse(acc), list]; - } - } - } -} - -/** - * Splits a list in two before the first element that a given function returns - * `False` for. - * - * If the function returns `True` for all elements the first list will be the - * input list, and the second list will be empty. - * - * ## Examples - * - * ```gleam - * split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 }) - * // -> #([1, 2, 3], [4, 5]) - * ``` - * - * ```gleam - * split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 }) - * // -> #([1, 2, 3, 4, 5], []) - * ``` - */ -export function split_while(list, predicate) { - return split_while_loop(list, predicate, toList([])); -} - -/** - * Given a list of 2-element tuples, finds the first tuple that has a given - * key as the first element and returns the second element. - * - * If no tuple is found with the given key then `Error(Nil)` is returned. - * - * This function may be useful for interacting with Erlang code where lists of - * tuples are common. - * - * ## Examples - * - * ```gleam - * key_find([#("a", 0), #("b", 1)], "a") - * // -> Ok(0) - * ``` - * - * ```gleam - * key_find([#("a", 0), #("b", 1)], "b") - * // -> Ok(1) - * ``` - * - * ```gleam - * key_find([#("a", 0), #("b", 1)], "c") - * // -> Error(Nil) - * ``` - */ -export function key_find(keyword_list, desired_key) { - return find_map( - keyword_list, - (keyword) => { - let key; - let value; - key = keyword[0]; - value = keyword[1]; - let $ = isEqual(key, desired_key); - if ($) { - return new Ok(value); - } else { - return new Error(undefined); - } - }, - ); -} - -/** - * Given a list of 2-element tuples, finds all tuples that have a given - * key as the first element and returns the second element. - * - * This function may be useful for interacting with Erlang code where lists of - * tuples are common. - * - * ## Examples - * - * ```gleam - * key_filter([#("a", 0), #("b", 1), #("a", 2)], "a") - * // -> [0, 2] - * ``` - * - * ```gleam - * key_filter([#("a", 0), #("b", 1)], "c") - * // -> [] - * ``` - */ -export function key_filter(keyword_list, desired_key) { - return filter_map( - keyword_list, - (keyword) => { - let key; - let value; - key = keyword[0]; - value = keyword[1]; - let $ = isEqual(key, desired_key); - if ($) { - return new Ok(value); - } else { - return new Error(undefined); - } - }, - ); -} - -function key_pop_loop(loop$list, loop$key, loop$checked) { - while (true) { - let list = loop$list; - let key = loop$key; - let checked = loop$checked; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let k = list.head[0]; - if (isEqual(k, key)) { - let rest$1 = list.tail; - let v = list.head[1]; - return new Ok([v, reverse_and_prepend(checked, rest$1)]); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$key = key; - loop$checked = listPrepend(first$1, checked); - } - } - } -} - -/** - * Given a list of 2-element tuples, finds the first tuple that has a given - * key as the first element. This function will return the second element - * of the found tuple and list with tuple removed. - * - * If no tuple is found with the given key then `Error(Nil)` is returned. - * - * ## Examples - * - * ```gleam - * key_pop([#("a", 0), #("b", 1)], "a") - * // -> Ok(#(0, [#("b", 1)])) - * ``` - * - * ```gleam - * key_pop([#("a", 0), #("b", 1)], "b") - * // -> Ok(#(1, [#("a", 0)])) - * ``` - * - * ```gleam - * key_pop([#("a", 0), #("b", 1)], "c") - * // -> Error(Nil) - * ``` - */ -export function key_pop(list, key) { - return key_pop_loop(list, key, toList([])); -} - -function key_set_loop(loop$list, loop$key, loop$value, loop$inspected) { - while (true) { - let list = loop$list; - let key = loop$key; - let value = loop$value; - let inspected = loop$inspected; - if (list instanceof $Empty) { - return reverse(listPrepend([key, value], inspected)); - } else { - let k = list.head[0]; - if (isEqual(k, key)) { - let rest$1 = list.tail; - return reverse_and_prepend(inspected, listPrepend([k, value], rest$1)); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$key = key; - loop$value = value; - loop$inspected = listPrepend(first$1, inspected); - } - } - } -} - -/** - * Given a list of 2-element tuples, inserts a key and value into the list. - * - * If there was already a tuple with the key then it is replaced, otherwise it - * is added to the end of the list. - * - * ## Examples - * - * ```gleam - * key_set([#(5, 0), #(4, 1)], 4, 100) - * // -> [#(5, 0), #(4, 100)] - * ``` - * - * ```gleam - * key_set([#(5, 0), #(4, 1)], 1, 100) - * // -> [#(5, 0), #(4, 1), #(1, 100)] - * ``` - */ -export function key_set(list, key, value) { - return key_set_loop(list, key, value, toList([])); -} - -/** - * Calls a function for each element in a list, discarding the return value. - * - * Useful for calling a side effect for every item of a list. - * - * ```gleam - * import gleam/io - * - * each(["1", "2", "3"], io.println) - * // -> Nil - * // 1 - * // 2 - * // 3 - * ``` - */ -export function each(loop$list, loop$f) { - while (true) { - let list = loop$list; - let f = loop$f; - if (list instanceof $Empty) { - return undefined; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - f(first$1); - loop$list = rest$1; - loop$f = f; - } - } -} - -/** - * Calls a `Result` returning function for each element in a list, discarding - * the return value. If the function returns `Error` then the iteration is - * stopped and the error is returned. - * - * Useful for calling a side effect for every item of a list. - * - * ## Examples - * - * ```gleam - * try_each( - * over: [1, 2, 3], - * with: function_that_might_fail, - * ) - * // -> Ok(Nil) - * ``` - */ -export function try_each(loop$list, loop$fun) { - while (true) { - let list = loop$list; - let fun = loop$fun; - if (list instanceof $Empty) { - return new Ok(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(first$1); - if ($ instanceof Ok) { - loop$list = rest$1; - loop$fun = fun; - } else { - return $; - } - } - } -} - -function partition_loop(loop$list, loop$categorise, loop$trues, loop$falses) { - while (true) { - let list = loop$list; - let categorise = loop$categorise; - let trues = loop$trues; - let falses = loop$falses; - if (list instanceof $Empty) { - return [reverse(trues), reverse(falses)]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = categorise(first$1); - if ($) { - loop$list = rest$1; - loop$categorise = categorise; - loop$trues = listPrepend(first$1, trues); - loop$falses = falses; - } else { - loop$list = rest$1; - loop$categorise = categorise; - loop$trues = trues; - loop$falses = listPrepend(first$1, falses); - } - } - } -} - -/** - * Partitions a list into a tuple/pair of lists - * by a given categorisation function. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * [1, 2, 3, 4, 5] |> partition(int.is_odd) - * // -> #([1, 3, 5], [2, 4]) - * ``` - */ -export function partition(list, categorise) { - return partition_loop(list, categorise, toList([]), toList([])); -} - -function window_loop(loop$acc, loop$list, loop$n) { - while (true) { - let acc = loop$acc; - let list = loop$list; - let n = loop$n; - let window$1 = take(list, n); - let $ = length(window$1) === n; - if ($) { - loop$acc = listPrepend(window$1, acc); - loop$list = drop(list, 1); - loop$n = n; - } else { - return reverse(acc); - } - } -} - -/** - * Returns a list of sliding windows. - * - * ## Examples - * - * ```gleam - * window([1,2,3,4,5], 3) - * // -> [[1, 2, 3], [2, 3, 4], [3, 4, 5]] - * ``` - * - * ```gleam - * window([1, 2], 4) - * // -> [] - * ``` - */ -export function window(list, n) { - let $ = n <= 0; - if ($) { - return toList([]); - } else { - return window_loop(toList([]), list, n); - } -} - -/** - * Returns a list of tuples containing two contiguous elements. - * - * ## Examples - * - * ```gleam - * window_by_2([1,2,3,4]) - * // -> [#(1, 2), #(2, 3), #(3, 4)] - * ``` - * - * ```gleam - * window_by_2([1]) - * // -> [] - * ``` - */ -export function window_by_2(list) { - return zip(list, drop(list, 1)); -} - -/** - * Drops the first elements in a given list for which the predicate function returns `True`. - * - * ## Examples - * - * ```gleam - * drop_while([1, 2, 3, 4], fn (x) { x < 3 }) - * // -> [3, 4] - * ``` - */ -export function drop_while(loop$list, loop$predicate) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - if (list instanceof $Empty) { - return list; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - } else { - return listPrepend(first$1, rest$1); - } - } - } -} - -function take_while_loop(loop$list, loop$predicate, loop$acc) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - loop$acc = listPrepend(first$1, acc); - } else { - return reverse(acc); - } - } - } -} - -/** - * Takes the first elements in a given list for which the predicate function returns `True`. - * - * ## Examples - * - * ```gleam - * take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) - * // -> [1, 2] - * ``` - */ -export function take_while(list, predicate) { - return take_while_loop(list, predicate, toList([])); -} - -function chunk_loop( - loop$list, - loop$f, - loop$previous_key, - loop$current_chunk, - loop$acc -) { - while (true) { - let list = loop$list; - let f = loop$f; - let previous_key = loop$previous_key; - let current_chunk = loop$current_chunk; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(listPrepend(reverse(current_chunk), acc)); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let key = f(first$1); - let $ = isEqual(key, previous_key); - if ($) { - loop$list = rest$1; - loop$f = f; - loop$previous_key = key; - loop$current_chunk = listPrepend(first$1, current_chunk); - loop$acc = acc; - } else { - let new_acc = listPrepend(reverse(current_chunk), acc); - loop$list = rest$1; - loop$f = f; - loop$previous_key = key; - loop$current_chunk = toList([first$1]); - loop$acc = new_acc; - } - } - } -} - -/** - * Returns a list of chunks in which - * the return value of calling `f` on each element is the same. - * - * ## Examples - * - * ```gleam - * [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 }) - * // -> [[1], [2, 2], [3], [4, 4, 6], [7, 7]] - * ``` - */ -export function chunk(list, f) { - if (list instanceof $Empty) { - return list; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return chunk_loop(rest$1, f, f(first$1), toList([first$1]), toList([])); - } -} - -function sized_chunk_loop( - loop$list, - loop$count, - loop$left, - loop$current_chunk, - loop$acc -) { - while (true) { - let list = loop$list; - let count = loop$count; - let left = loop$left; - let current_chunk = loop$current_chunk; - let acc = loop$acc; - if (list instanceof $Empty) { - if (current_chunk instanceof $Empty) { - return reverse(acc); - } else { - let remaining = current_chunk; - return reverse(listPrepend(reverse(remaining), acc)); - } - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let chunk$1 = listPrepend(first$1, current_chunk); - let $ = left > 1; - if ($) { - loop$list = rest$1; - loop$count = count; - loop$left = left - 1; - loop$current_chunk = chunk$1; - loop$acc = acc; - } else { - loop$list = rest$1; - loop$count = count; - loop$left = count; - loop$current_chunk = toList([]); - loop$acc = listPrepend(reverse(chunk$1), acc); - } - } - } -} - -/** - * Returns a list of chunks containing `count` elements each. - * - * If the last chunk does not have `count` elements, it is instead - * a partial chunk, with less than `count` elements. - * - * For any `count` less than 1 this function behaves as if it was set to 1. - * - * ## Examples - * - * ```gleam - * [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2) - * // -> [[1, 2], [3, 4], [5, 6]] - * ``` - * - * ```gleam - * [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3) - * // -> [[1, 2, 3], [4, 5, 6], [7, 8]] - * ``` - */ -export function sized_chunk(list, count) { - return sized_chunk_loop(list, count, count, toList([]), toList([])); -} - -/** - * This function acts similar to fold, but does not take an initial state. - * Instead, it starts from the first element in the list - * and combines it with each subsequent element in turn using the given - * function. The function is called as `fun(accumulator, current_element)`. - * - * Returns `Ok` to indicate a successful run, and `Error` if called on an - * empty list. - * - * ## Examples - * - * ```gleam - * [] |> reduce(fn(acc, x) { acc + x }) - * // -> Error(Nil) - * ``` - * - * ```gleam - * [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) - * // -> Ok(15) - * ``` - */ -export function reduce(list, fun) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return new Ok(fold(rest$1, first$1, fun)); - } -} - -function scan_loop(loop$list, loop$accumulator, loop$accumulated, loop$fun) { - while (true) { - let list = loop$list; - let accumulator = loop$accumulator; - let accumulated = loop$accumulated; - let fun = loop$fun; - if (list instanceof $Empty) { - return reverse(accumulated); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let next = fun(accumulator, first$1); - loop$list = rest$1; - loop$accumulator = next; - loop$accumulated = listPrepend(next, accumulated); - loop$fun = fun; - } - } -} - -/** - * Similar to `fold`, but yields the state of the accumulator at each stage. - * - * ## Examples - * - * ```gleam - * scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i }) - * // -> [101, 103, 106] - * ``` - */ -export function scan(list, initial, fun) { - return scan_loop(list, initial, toList([]), fun); -} - -/** - * Returns the last element in the given list. - * - * Returns `Error(Nil)` if the list is empty. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * last([]) - * // -> Error(Nil) - * ``` - * - * ```gleam - * last([1, 2, 3, 4, 5]) - * // -> Ok(5) - * ``` - */ -export function last(loop$list) { - while (true) { - let list = loop$list; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let $ = list.tail; - if ($ instanceof $Empty) { - let last$1 = list.head; - return new Ok(last$1); - } else { - let rest$1 = $; - loop$list = rest$1; - } - } - } -} - -/** - * Return unique combinations of elements in the list. - * - * ## Examples - * - * ```gleam - * combinations([1, 2, 3], 2) - * // -> [[1, 2], [1, 3], [2, 3]] - * ``` - * - * ```gleam - * combinations([1, 2, 3, 4], 3) - * // -> [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]] - * ``` - */ -export function combinations(items, n) { - if (n === 0) { - return toList([toList([])]); - } else if (items instanceof $Empty) { - return items; - } else { - let first$1 = items.head; - let rest$1 = items.tail; - let _pipe = rest$1; - let _pipe$1 = combinations(_pipe, n - 1); - let _pipe$2 = map( - _pipe$1, - (combination) => { return listPrepend(first$1, combination); }, - ); - let _pipe$3 = reverse(_pipe$2); - return fold( - _pipe$3, - combinations(rest$1, n), - (acc, c) => { return listPrepend(c, acc); }, - ); - } -} - -function combination_pairs_loop(loop$items, loop$acc) { - while (true) { - let items = loop$items; - let acc = loop$acc; - if (items instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = items.head; - let rest$1 = items.tail; - let first_combinations = map( - rest$1, - (other) => { return [first$1, other]; }, - ); - let acc$1 = reverse_and_prepend(first_combinations, acc); - loop$items = rest$1; - loop$acc = acc$1; - } - } -} - -/** - * Return unique pair combinations of elements in the list. - * - * ## Examples - * - * ```gleam - * combination_pairs([1, 2, 3]) - * // -> [#(1, 2), #(1, 3), #(2, 3)] - * ``` - */ -export function combination_pairs(items) { - return combination_pairs_loop(items, toList([])); -} - -function take_firsts(loop$rows, loop$column, loop$remaining_rows) { - while (true) { - let rows = loop$rows; - let column = loop$column; - let remaining_rows = loop$remaining_rows; - if (rows instanceof $Empty) { - return [reverse(column), reverse(remaining_rows)]; - } else { - let $ = rows.head; - if ($ instanceof $Empty) { - let rest$1 = rows.tail; - loop$rows = rest$1; - loop$column = column; - loop$remaining_rows = remaining_rows; - } else { - let rest_rows = rows.tail; - let first$1 = $.head; - let remaining_row = $.tail; - let remaining_rows$1 = listPrepend(remaining_row, remaining_rows); - loop$rows = rest_rows; - loop$column = listPrepend(first$1, column); - loop$remaining_rows = remaining_rows$1; - } - } - } -} - -function transpose_loop(loop$rows, loop$columns) { - while (true) { - let rows = loop$rows; - let columns = loop$columns; - if (rows instanceof $Empty) { - return reverse(columns); - } else { - let $ = take_firsts(rows, toList([]), toList([])); - let column; - let rest$1; - column = $[0]; - rest$1 = $[1]; - if (column instanceof $Empty) { - loop$rows = rest$1; - loop$columns = columns; - } else { - loop$rows = rest$1; - loop$columns = listPrepend(column, columns); - } - } - } -} - -/** - * Transpose rows and columns of the list of lists. - * - * Notice: This function is not tail recursive, - * and thus may exceed stack size if called, - * with large lists (on the JavaScript target). - * - * ## Examples - * - * ```gleam - * transpose([[1, 2, 3], [101, 102, 103]]) - * // -> [[1, 101], [2, 102], [3, 103]] - * ``` - */ -export function transpose(list_of_lists) { - return transpose_loop(list_of_lists, toList([])); -} - -/** - * Make a list alternating the elements from the given lists - * - * ## Examples - * - * ```gleam - * interleave([[1, 2], [101, 102], [201, 202]]) - * // -> [1, 101, 201, 2, 102, 202] - * ``` - */ -export function interleave(list) { - let _pipe = list; - let _pipe$1 = transpose(_pipe); - return flatten(_pipe$1); -} - -function shuffle_pair_unwrap_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return acc; - } else { - let elem_pair = list.head; - let enumerable = list.tail; - loop$list = enumerable; - loop$acc = listPrepend(elem_pair[1], acc); - } - } -} - -function do_shuffle_by_pair_indexes(list_of_pairs) { - return sort( - list_of_pairs, - (a_pair, b_pair) => { return $float.compare(a_pair[0], b_pair[0]); }, - ); -} - -/** - * Takes a list, randomly sorts all items and returns the shuffled list. - * - * This function uses `float.random` to decide the order of the elements. - * - * ## Example - * - * ```gleam - * range(1, 10) |> shuffle() - * // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5] - * ``` - */ -export function shuffle(list) { - let _pipe = list; - let _pipe$1 = fold( - _pipe, - toList([]), - (acc, a) => { return listPrepend([$float.random(), a], acc); }, - ); - let _pipe$2 = do_shuffle_by_pair_indexes(_pipe$1); - return shuffle_pair_unwrap_loop(_pipe$2, toList([])); -} - -function max_loop(loop$list, loop$compare, loop$max) { - while (true) { - let list = loop$list; - let compare = loop$compare; - let max = loop$max; - if (list instanceof $Empty) { - return max; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = compare(first$1, max); - if ($ instanceof $order.Lt) { - loop$list = rest$1; - loop$compare = compare; - loop$max = max; - } else if ($ instanceof $order.Eq) { - loop$list = rest$1; - loop$compare = compare; - loop$max = max; - } else { - loop$list = rest$1; - loop$compare = compare; - loop$max = first$1; - } - } - } -} - -/** - * Takes a list and a comparator, and returns the maximum element in the list - * - * - * ## Example - * - * ```gleam - * range(1, 10) |> list.max(int.compare) - * // -> Ok(10) - * ``` - * - * ```gleam - * ["a", "c", "b"] |> list.max(string.compare) - * // -> Ok("c") - * ``` - */ -export function max(list, compare) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return new Ok(max_loop(rest$1, compare, first$1)); - } -} - -function build_reservoir_loop(loop$list, loop$size, loop$reservoir) { - while (true) { - let list = loop$list; - let size = loop$size; - let reservoir = loop$reservoir; - let reservoir_size = $dict.size(reservoir); - let $ = reservoir_size >= size; - if ($) { - return [reservoir, list]; - } else { - if (list instanceof $Empty) { - return [reservoir, toList([])]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let reservoir$1 = $dict.insert(reservoir, reservoir_size, first$1); - loop$list = rest$1; - loop$size = size; - loop$reservoir = reservoir$1; - } - } - } -} - -/** - * Builds the initial reservoir used by Algorithm L. - * This is a dictionary with keys ranging from `0` up to `n - 1` where each - * value is the corresponding element at that position in `list`. - * - * This also returns the remaining elements of `list` that didn't end up in - * the reservoir. - * - * @ignore - */ -function build_reservoir(list, n) { - return build_reservoir_loop(list, n, $dict.new$()); -} - -const min_positive = 2.2250738585072014e-308; - -function log_random() { - let $ = $float.logarithm($float.random() + min_positive); - let random; - if ($ instanceof Ok) { - random = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam/list", - 2391, - "log_random", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 56078, - end: 56149, - pattern_start: 56089, - pattern_end: 56099 - } - ) - } - return random; -} - -function sample_loop(loop$list, loop$reservoir, loop$n, loop$w) { - while (true) { - let list = loop$list; - let reservoir = loop$reservoir; - let n = loop$n; - let w = loop$w; - let _block; - { - let $ = $float.logarithm(1.0 - w); - let log; - if ($ instanceof Ok) { - log = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam/list", - 2374, - "sample_loop", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 55639, - end: 55685, - pattern_start: 55650, - pattern_end: 55657 - } - ) - } - _block = $float.round($float.floor(divideFloat(log_random(), log))); - } - let skip = _block; - let $ = drop(list, skip); - if ($ instanceof $Empty) { - return reservoir; - } else { - let first$1 = $.head; - let rest$1 = $.tail; - let reservoir$1 = $dict.insert(reservoir, $int.random(n), first$1); - let w$1 = w * $float.exponential( - divideFloat(log_random(), $int.to_float(n)), - ); - loop$list = rest$1; - loop$reservoir = reservoir$1; - loop$n = n; - loop$w = w$1; - } - } -} - -/** - * Returns a random sample of up to n elements from a list using reservoir - * sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L). - * Returns an empty list if the sample size is less than or equal to 0. - * - * Order is not random, only selection is. - * - * ## Examples - * - * ```gleam - * reservoir_sample([1, 2, 3, 4, 5], 3) - * // -> [2, 4, 5] // A random sample of 3 items - * ``` - */ -export function sample(list, n) { - let $ = build_reservoir(list, n); - let reservoir; - let rest$1; - reservoir = $[0]; - rest$1 = $[1]; - let $1 = $dict.is_empty(reservoir); - if ($1) { - return toList([]); - } else { - let w = $float.exponential(divideFloat(log_random(), $int.to_float(n))); - return $dict.values(sample_loop(rest$1, reservoir, n, w)); - } -} - -function permutation_zip(list, rest, acc) { - if (list instanceof $Empty) { - return reverse(acc); - } else { - let head = list.head; - let tail = list.tail; - return permutation_prepend( - head, - permutations(reverse_and_prepend(rest, tail)), - tail, - listPrepend(head, rest), - acc, - ); - } -} - -function permutation_prepend( - loop$el, - loop$permutations, - loop$list_1, - loop$list_2, - loop$acc -) { - while (true) { - let el = loop$el; - let permutations = loop$permutations; - let list_1 = loop$list_1; - let list_2 = loop$list_2; - let acc = loop$acc; - if (permutations instanceof $Empty) { - return permutation_zip(list_1, list_2, acc); - } else { - let head = permutations.head; - let tail = permutations.tail; - loop$el = el; - loop$permutations = tail; - loop$list_1 = list_1; - loop$list_2 = list_2; - loop$acc = listPrepend(listPrepend(el, head), acc); - } - } -} - -/** - * Returns all the permutations of a list. - * - * ## Examples - * - * ```gleam - * permutations([1, 2]) - * // -> [[1, 2], [2, 1]] - * ``` - */ -export function permutations(list) { - if (list instanceof $Empty) { - return toList([toList([])]); - } else { - let l = list; - return permutation_zip(l, toList([]), toList([])); - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/option.mjs b/build/dev/javascript/gleam_stdlib/gleam/option.mjs deleted file mode 100644 index 5e820a3..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/option.mjs +++ /dev/null @@ -1,419 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - isEqual, -} from "../gleam.mjs"; - -export class Some extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Option$Some = ($0) => new Some($0); -export const Option$isSome = (value) => value instanceof Some; -export const Option$Some$0 = (value) => value[0]; - -export class None extends $CustomType {} -export const Option$None = () => new None(); -export const Option$isNone = (value) => value instanceof None; - -function reverse_and_prepend(loop$prefix, loop$suffix) { - while (true) { - let prefix = loop$prefix; - let suffix = loop$suffix; - if (prefix instanceof $Empty) { - return suffix; - } else { - let first = prefix.head; - let rest = prefix.tail; - loop$prefix = rest; - loop$suffix = listPrepend(first, suffix); - } - } -} - -function reverse(list) { - return reverse_and_prepend(list, toList([])); -} - -function all_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return new Some(reverse(acc)); - } else { - let $ = list.head; - if ($ instanceof Some) { - let rest = list.tail; - let first = $[0]; - loop$list = rest; - loop$acc = listPrepend(first, acc); - } else { - return new None(); - } - } - } -} - -/** - * Combines a list of `Option`s into a single `Option`. - * If all elements in the list are `Some` then returns a `Some` holding the list of values. - * If any element is `None` then returns`None`. - * - * ## Examples - * - * ```gleam - * all([Some(1), Some(2)]) - * // -> Some([1, 2]) - * ``` - * - * ```gleam - * all([Some(1), None]) - * // -> None - * ``` - */ -export function all(list) { - return all_loop(list, toList([])); -} - -/** - * Checks whether the `Option` is a `Some` value. - * - * ## Examples - * - * ```gleam - * is_some(Some(1)) - * // -> True - * ``` - * - * ```gleam - * is_some(None) - * // -> False - * ``` - */ -export function is_some(option) { - return !isEqual(option, new None()); -} - -/** - * Checks whether the `Option` is a `None` value. - * - * ## Examples - * - * ```gleam - * is_none(Some(1)) - * // -> False - * ``` - * - * ```gleam - * is_none(None) - * // -> True - * ``` - */ -export function is_none(option) { - return isEqual(option, new None()); -} - -/** - * Converts an `Option` type to a `Result` type. - * - * ## Examples - * - * ```gleam - * to_result(Some(1), "some_error") - * // -> Ok(1) - * ``` - * - * ```gleam - * to_result(None, "some_error") - * // -> Error("some_error") - * ``` - */ -export function to_result(option, e) { - if (option instanceof Some) { - let a = option[0]; - return new Ok(a); - } else { - return new Error(e); - } -} - -/** - * Converts a `Result` type to an `Option` type. - * - * ## Examples - * - * ```gleam - * from_result(Ok(1)) - * // -> Some(1) - * ``` - * - * ```gleam - * from_result(Error("some_error")) - * // -> None - * ``` - */ -export function from_result(result) { - if (result instanceof Ok) { - let a = result[0]; - return new Some(a); - } else { - return new None(); - } -} - -/** - * Extracts the value from an `Option`, returning a default value if there is none. - * - * ## Examples - * - * ```gleam - * unwrap(Some(1), 0) - * // -> 1 - * ``` - * - * ```gleam - * unwrap(None, 0) - * // -> 0 - * ``` - */ -export function unwrap(option, default$) { - if (option instanceof Some) { - let x = option[0]; - return x; - } else { - return default$; - } -} - -/** - * Extracts the value from an `Option`, evaluating the default function if the option is `None`. - * - * ## Examples - * - * ```gleam - * lazy_unwrap(Some(1), fn() { 0 }) - * // -> 1 - * ``` - * - * ```gleam - * lazy_unwrap(None, fn() { 0 }) - * // -> 0 - * ``` - */ -export function lazy_unwrap(option, default$) { - if (option instanceof Some) { - let x = option[0]; - return x; - } else { - return default$(); - } -} - -/** - * Updates a value held within the `Some` of an `Option` by calling a given function - * on it. - * - * If the `Option` is a `None` rather than `Some`, the function is not called and the - * `Option` stays the same. - * - * ## Examples - * - * ```gleam - * map(over: Some(1), with: fn(x) { x + 1 }) - * // -> Some(2) - * ``` - * - * ```gleam - * map(over: None, with: fn(x) { x + 1 }) - * // -> None - * ``` - */ -export function map(option, fun) { - if (option instanceof Some) { - let x = option[0]; - return new Some(fun(x)); - } else { - return option; - } -} - -/** - * Merges a nested `Option` into a single layer. - * - * ## Examples - * - * ```gleam - * flatten(Some(Some(1))) - * // -> Some(1) - * ``` - * - * ```gleam - * flatten(Some(None)) - * // -> None - * ``` - * - * ```gleam - * flatten(None) - * // -> None - * ``` - */ -export function flatten(option) { - if (option instanceof Some) { - let x = option[0]; - return x; - } else { - return option; - } -} - -/** - * Updates a value held within the `Some` of an `Option` by calling a given function - * on it, where the given function also returns an `Option`. The two options are - * then merged together into one `Option`. - * - * If the `Option` is a `None` rather than `Some` the function is not called and the - * option stays the same. - * - * This function is the equivalent of calling `map` followed by `flatten`, and - * it is useful for chaining together multiple functions that return `Option`. - * - * ## Examples - * - * ```gleam - * then(Some(1), fn(x) { Some(x + 1) }) - * // -> Some(2) - * ``` - * - * ```gleam - * then(Some(1), fn(x) { Some(#("a", x)) }) - * // -> Some(#("a", 1)) - * ``` - * - * ```gleam - * then(Some(1), fn(_) { None }) - * // -> None - * ``` - * - * ```gleam - * then(None, fn(x) { Some(x + 1) }) - * // -> None - * ``` - */ -export function then$(option, fun) { - if (option instanceof Some) { - let x = option[0]; - return fun(x); - } else { - return option; - } -} - -/** - * Returns the first value if it is `Some`, otherwise returns the second value. - * - * ## Examples - * - * ```gleam - * or(Some(1), Some(2)) - * // -> Some(1) - * ``` - * - * ```gleam - * or(Some(1), None) - * // -> Some(1) - * ``` - * - * ```gleam - * or(None, Some(2)) - * // -> Some(2) - * ``` - * - * ```gleam - * or(None, None) - * // -> None - * ``` - */ -export function or(first, second) { - if (first instanceof Some) { - return first; - } else { - return second; - } -} - -/** - * Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value. - * - * ## Examples - * - * ```gleam - * lazy_or(Some(1), fn() { Some(2) }) - * // -> Some(1) - * ``` - * - * ```gleam - * lazy_or(Some(1), fn() { None }) - * // -> Some(1) - * ``` - * - * ```gleam - * lazy_or(None, fn() { Some(2) }) - * // -> Some(2) - * ``` - * - * ```gleam - * lazy_or(None, fn() { None }) - * // -> None - * ``` - */ -export function lazy_or(first, second) { - if (first instanceof Some) { - return first; - } else { - return second(); - } -} - -function values_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let $ = list.head; - if ($ instanceof Some) { - let rest = list.tail; - let first = $[0]; - loop$list = rest; - loop$acc = listPrepend(first, acc); - } else { - let rest = list.tail; - loop$list = rest; - loop$acc = acc; - } - } - } -} - -/** - * Given a list of `Option`s, - * returns only the values inside `Some`. - * - * ## Examples - * - * ```gleam - * values([Some(1), None, Some(3)]) - * // -> [1, 3] - * ``` - */ -export function values(options) { - return values_loop(options, toList([])); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/order.mjs b/build/dev/javascript/gleam_stdlib/gleam/order.mjs deleted file mode 100644 index 617938c..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/order.mjs +++ /dev/null @@ -1,178 +0,0 @@ -import { CustomType as $CustomType, isEqual } from "../gleam.mjs"; - -export class Lt extends $CustomType {} -export const Order$Lt = () => new Lt(); -export const Order$isLt = (value) => value instanceof Lt; - -export class Eq extends $CustomType {} -export const Order$Eq = () => new Eq(); -export const Order$isEq = (value) => value instanceof Eq; - -export class Gt extends $CustomType {} -export const Order$Gt = () => new Gt(); -export const Order$isGt = (value) => value instanceof Gt; - -/** - * Inverts an order, so less-than becomes greater-than and greater-than - * becomes less-than. - * - * ## Examples - * - * ```gleam - * negate(Lt) - * // -> Gt - * ``` - * - * ```gleam - * negate(Eq) - * // -> Eq - * ``` - * - * ```gleam - * negate(Gt) - * // -> Lt - * ``` - */ -export function negate(order) { - if (order instanceof Lt) { - return new Gt(); - } else if (order instanceof Eq) { - return order; - } else { - return new Lt(); - } -} - -/** - * Produces a numeric representation of the order. - * - * ## Examples - * - * ```gleam - * to_int(Lt) - * // -> -1 - * ``` - * - * ```gleam - * to_int(Eq) - * // -> 0 - * ``` - * - * ```gleam - * to_int(Gt) - * // -> 1 - * ``` - */ -export function to_int(order) { - if (order instanceof Lt) { - return -1; - } else if (order instanceof Eq) { - return 0; - } else { - return 1; - } -} - -/** - * Compares two `Order` values to one another, producing a new `Order`. - * - * ## Examples - * - * ```gleam - * compare(Eq, with: Lt) - * // -> Gt - * ``` - */ -export function compare(a, b) { - let x = a; - let y = b; - if (isEqual(x, y)) { - return new Eq(); - } else if (a instanceof Lt) { - return new Lt(); - } else if (a instanceof Eq && b instanceof Gt) { - return new Lt(); - } else { - return new Gt(); - } -} - -/** - * Inverts an ordering function, so less-than becomes greater-than and greater-than - * becomes less-than. - * - * ## Examples - * - * ```gleam - * import gleam/int - * import gleam/list - * - * list.sort([1, 5, 4], by: reverse(int.compare)) - * // -> [5, 4, 1] - * ``` - */ -export function reverse(orderer) { - return (a, b) => { return orderer(b, a); }; -} - -/** - * Return a fallback `Order` in case the first argument is `Eq`. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * break_tie(in: int.compare(1, 1), with: Lt) - * // -> Lt - * ``` - * - * ```gleam - * import gleam/int - * - * break_tie(in: int.compare(1, 0), with: Eq) - * // -> Gt - * ``` - */ -export function break_tie(order, other) { - if (order instanceof Lt) { - return order; - } else if (order instanceof Eq) { - return other; - } else { - return order; - } -} - -/** - * Invokes a fallback function returning an `Order` in case the first argument - * is `Eq`. - * - * This can be useful when the fallback comparison might be expensive and it - * needs to be delayed until strictly necessary. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt }) - * // -> Lt - * ``` - * - * ```gleam - * import gleam/int - * - * lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq }) - * // -> Gt - * ``` - */ -export function lazy_break_tie(order, comparison) { - if (order instanceof Lt) { - return order; - } else if (order instanceof Eq) { - return comparison(); - } else { - return order; - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/pair.mjs b/build/dev/javascript/gleam_stdlib/gleam/pair.mjs deleted file mode 100644 index 13f0cd5..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/pair.mjs +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Returns the first element in a pair. - * - * ## Examples - * - * ```gleam - * first(#(1, 2)) - * // -> 1 - * ``` - */ -export function first(pair) { - let a; - a = pair[0]; - return a; -} - -/** - * Returns the second element in a pair. - * - * ## Examples - * - * ```gleam - * second(#(1, 2)) - * // -> 2 - * ``` - */ -export function second(pair) { - let a; - a = pair[1]; - return a; -} - -/** - * Returns a new pair with the elements swapped. - * - * ## Examples - * - * ```gleam - * swap(#(1, 2)) - * // -> #(2, 1) - * ``` - */ -export function swap(pair) { - let a; - let b; - a = pair[0]; - b = pair[1]; - return [b, a]; -} - -/** - * Returns a new pair with the first element having had `with` applied to - * it. - * - * ## Examples - * - * ```gleam - * #(1, 2) |> map_first(fn(n) { n * 2 }) - * // -> #(2, 2) - * ``` - */ -export function map_first(pair, fun) { - let a; - let b; - a = pair[0]; - b = pair[1]; - return [fun(a), b]; -} - -/** - * Returns a new pair with the second element having had `with` applied to - * it. - * - * ## Examples - * - * ```gleam - * #(1, 2) |> map_second(fn(n) { n * 2 }) - * // -> #(1, 4) - * ``` - */ -export function map_second(pair, fun) { - let a; - let b; - a = pair[0]; - b = pair[1]; - return [a, fun(b)]; -} - -/** - * Returns a new pair with the given elements. This can also be done using the dedicated - * syntax instead: `new(1, 2) == #(1, 2)`. - * - * ## Examples - * - * ```gleam - * new(1, 2) - * // -> #(1, 2) - * ``` - */ -export function new$(first, second) { - return [first, second]; -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/result.mjs b/build/dev/javascript/gleam_stdlib/gleam/result.mjs deleted file mode 100644 index 527de4f..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/result.mjs +++ /dev/null @@ -1,494 +0,0 @@ -import { Ok, Error, toList, Empty as $Empty, prepend as listPrepend } from "../gleam.mjs"; -import * as $list from "../gleam/list.mjs"; - -/** - * Checks whether the result is an `Ok` value. - * - * ## Examples - * - * ```gleam - * is_ok(Ok(1)) - * // -> True - * ``` - * - * ```gleam - * is_ok(Error(Nil)) - * // -> False - * ``` - */ -export function is_ok(result) { - if (result instanceof Ok) { - return true; - } else { - return false; - } -} - -/** - * Checks whether the result is an `Error` value. - * - * ## Examples - * - * ```gleam - * is_error(Ok(1)) - * // -> False - * ``` - * - * ```gleam - * is_error(Error(Nil)) - * // -> True - * ``` - */ -export function is_error(result) { - if (result instanceof Ok) { - return false; - } else { - return true; - } -} - -/** - * Updates a value held within the `Ok` of a result by calling a given function - * on it. - * - * If the result is an `Error` rather than `Ok` the function is not called and the - * result stays the same. - * - * ## Examples - * - * ```gleam - * map(over: Ok(1), with: fn(x) { x + 1 }) - * // -> Ok(2) - * ``` - * - * ```gleam - * map(over: Error(1), with: fn(x) { x + 1 }) - * // -> Error(1) - * ``` - */ -export function map(result, fun) { - if (result instanceof Ok) { - let x = result[0]; - return new Ok(fun(x)); - } else { - return result; - } -} - -/** - * Updates a value held within the `Error` of a result by calling a given function - * on it. - * - * If the result is `Ok` rather than `Error` the function is not called and the - * result stays the same. - * - * ## Examples - * - * ```gleam - * map_error(over: Error(1), with: fn(x) { x + 1 }) - * // -> Error(2) - * ``` - * - * ```gleam - * map_error(over: Ok(1), with: fn(x) { x + 1 }) - * // -> Ok(1) - * ``` - */ -export function map_error(result, fun) { - if (result instanceof Ok) { - return result; - } else { - let error = result[0]; - return new Error(fun(error)); - } -} - -/** - * Merges a nested `Result` into a single layer. - * - * ## Examples - * - * ```gleam - * flatten(Ok(Ok(1))) - * // -> Ok(1) - * ``` - * - * ```gleam - * flatten(Ok(Error(""))) - * // -> Error("") - * ``` - * - * ```gleam - * flatten(Error(Nil)) - * // -> Error(Nil) - * ``` - */ -export function flatten(result) { - if (result instanceof Ok) { - let x = result[0]; - return x; - } else { - return result; - } -} - -/** - * "Updates" an `Ok` result by passing its value to a function that yields a result, - * and returning the yielded result. (This may "replace" the `Ok` with an `Error`.) - * - * If the input is an `Error` rather than an `Ok`, the function is not called and - * the original `Error` is returned. - * - * This function is the equivalent of calling `map` followed by `flatten`, and - * it is useful for chaining together multiple functions that may fail. - * - * ## Examples - * - * ```gleam - * try(Ok(1), fn(x) { Ok(x + 1) }) - * // -> Ok(2) - * ``` - * - * ```gleam - * try(Ok(1), fn(x) { Ok(#("a", x)) }) - * // -> Ok(#("a", 1)) - * ``` - * - * ```gleam - * try(Ok(1), fn(_) { Error("Oh no") }) - * // -> Error("Oh no") - * ``` - * - * ```gleam - * try(Error(Nil), fn(x) { Ok(x + 1) }) - * // -> Error(Nil) - * ``` - */ -export function try$(result, fun) { - if (result instanceof Ok) { - let x = result[0]; - return fun(x); - } else { - return result; - } -} - -export function then$(result, fun) { - return try$(result, fun); -} - -/** - * Extracts the `Ok` value from a result, returning a default value if the result - * is an `Error`. - * - * ## Examples - * - * ```gleam - * unwrap(Ok(1), 0) - * // -> 1 - * ``` - * - * ```gleam - * unwrap(Error(""), 0) - * // -> 0 - * ``` - */ -export function unwrap(result, default$) { - if (result instanceof Ok) { - let v = result[0]; - return v; - } else { - return default$; - } -} - -/** - * Extracts the `Ok` value from a result, evaluating the default function if the result - * is an `Error`. - * - * ## Examples - * - * ```gleam - * lazy_unwrap(Ok(1), fn() { 0 }) - * // -> 1 - * ``` - * - * ```gleam - * lazy_unwrap(Error(""), fn() { 0 }) - * // -> 0 - * ``` - */ -export function lazy_unwrap(result, default$) { - if (result instanceof Ok) { - let v = result[0]; - return v; - } else { - return default$(); - } -} - -/** - * Extracts the `Error` value from a result, returning a default value if the result - * is an `Ok`. - * - * ## Examples - * - * ```gleam - * unwrap_error(Error(1), 0) - * // -> 1 - * ``` - * - * ```gleam - * unwrap_error(Ok(""), 0) - * // -> 0 - * ``` - */ -export function unwrap_error(result, default$) { - if (result instanceof Ok) { - return default$; - } else { - let e = result[0]; - return e; - } -} - -export function unwrap_both(result) { - if (result instanceof Ok) { - let a = result[0]; - return a; - } else { - let a = result[0]; - return a; - } -} - -/** - * Returns the first value if it is `Ok`, otherwise returns the second value. - * - * ## Examples - * - * ```gleam - * or(Ok(1), Ok(2)) - * // -> Ok(1) - * ``` - * - * ```gleam - * or(Ok(1), Error("Error 2")) - * // -> Ok(1) - * ``` - * - * ```gleam - * or(Error("Error 1"), Ok(2)) - * // -> Ok(2) - * ``` - * - * ```gleam - * or(Error("Error 1"), Error("Error 2")) - * // -> Error("Error 2") - * ``` - */ -export function or(first, second) { - if (first instanceof Ok) { - return first; - } else { - return second; - } -} - -/** - * Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value. - * - * If you need access to the initial error value, use `result.try_recover`. - * - * ## Examples - * - * ```gleam - * lazy_or(Ok(1), fn() { Ok(2) }) - * // -> Ok(1) - * ``` - * - * ```gleam - * lazy_or(Ok(1), fn() { Error("Error 2") }) - * // -> Ok(1) - * ``` - * - * ```gleam - * lazy_or(Error("Error 1"), fn() { Ok(2) }) - * // -> Ok(2) - * ``` - * - * ```gleam - * lazy_or(Error("Error 1"), fn() { Error("Error 2") }) - * // -> Error("Error 2") - * ``` - */ -export function lazy_or(first, second) { - if (first instanceof Ok) { - return first; - } else { - return second(); - } -} - -/** - * Combines a list of results into a single result. - * If all elements in the list are `Ok` then returns an `Ok` holding the list of values. - * If any element is `Error` then returns the first error. - * - * ## Examples - * - * ```gleam - * all([Ok(1), Ok(2)]) - * // -> Ok([1, 2]) - * ``` - * - * ```gleam - * all([Ok(1), Error("e")]) - * // -> Error("e") - * ``` - */ -export function all(results) { - return $list.try_map(results, (result) => { return result; }); -} - -function partition_loop(loop$results, loop$oks, loop$errors) { - while (true) { - let results = loop$results; - let oks = loop$oks; - let errors = loop$errors; - if (results instanceof $Empty) { - return [oks, errors]; - } else { - let $ = results.head; - if ($ instanceof Ok) { - let rest = results.tail; - let a = $[0]; - loop$results = rest; - loop$oks = listPrepend(a, oks); - loop$errors = errors; - } else { - let rest = results.tail; - let e = $[0]; - loop$results = rest; - loop$oks = oks; - loop$errors = listPrepend(e, errors); - } - } - } -} - -/** - * Given a list of results, returns a pair where the first element is a list - * of all the values inside `Ok` and the second element is a list with all the - * values inside `Error`. The values in both lists appear in reverse order with - * respect to their position in the original list of results. - * - * ## Examples - * - * ```gleam - * partition([Ok(1), Error("a"), Error("b"), Ok(2)]) - * // -> #([2, 1], ["b", "a"]) - * ``` - */ -export function partition(results) { - return partition_loop(results, toList([]), toList([])); -} - -/** - * Replace the value within a result - * - * ## Examples - * - * ```gleam - * replace(Ok(1), Nil) - * // -> Ok(Nil) - * ``` - * - * ```gleam - * replace(Error(1), Nil) - * // -> Error(1) - * ``` - */ -export function replace(result, value) { - if (result instanceof Ok) { - return new Ok(value); - } else { - return result; - } -} - -/** - * Replace the error within a result - * - * ## Examples - * - * ```gleam - * replace_error(Error(1), Nil) - * // -> Error(Nil) - * ``` - * - * ```gleam - * replace_error(Ok(1), Nil) - * // -> Ok(1) - * ``` - */ -export function replace_error(result, error) { - if (result instanceof Ok) { - return result; - } else { - return new Error(error); - } -} - -/** - * Given a list of results, returns only the values inside `Ok`. - * - * ## Examples - * - * ```gleam - * values([Ok(1), Error("a"), Ok(3)]) - * // -> [1, 3] - * ``` - */ -export function values(results) { - return $list.filter_map(results, (result) => { return result; }); -} - -/** - * Updates a value held within the `Error` of a result by calling a given function - * on it, where the given function also returns a result. The two results are - * then merged together into one result. - * - * If the result is an `Ok` rather than `Error` the function is not called and the - * result stays the same. - * - * This function is useful for chaining together computations that may fail - * and trying to recover from possible errors. - * - * If you do not need access to the initial error value, use `result.lazy_or`. - * - * ## Examples - * - * ```gleam - * Ok(1) |> try_recover(with: fn(_) { Error("failed to recover") }) - * // -> Ok(1) - * ``` - * - * ```gleam - * Error(1) |> try_recover(with: fn(error) { Ok(error + 1) }) - * // -> Ok(2) - * ``` - * - * ```gleam - * Error(1) |> try_recover(with: fn(error) { Error("failed to recover") }) - * // -> Error("failed to recover") - * ``` - */ -export function try_recover(result, fun) { - if (result instanceof Ok) { - return result; - } else { - let error = result[0]; - return fun(error); - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/set.mjs b/build/dev/javascript/gleam_stdlib/gleam/set.mjs deleted file mode 100644 index dc1ae52..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/set.mjs +++ /dev/null @@ -1,412 +0,0 @@ -import { CustomType as $CustomType, isEqual } from "../gleam.mjs"; -import * as $dict from "../gleam/dict.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $result from "../gleam/result.mjs"; - -class Set extends $CustomType { - constructor(dict) { - super(); - this.dict = dict; - } -} - -/** - * Creates a new empty set. - */ -export function new$() { - return new Set($dict.new$()); -} - -/** - * Gets the number of members in a set. - * - * This function runs in constant time. - * - * ## Examples - * - * ```gleam - * new() - * |> insert(1) - * |> insert(2) - * |> size - * // -> 2 - * ``` - */ -export function size(set) { - return $dict.size(set.dict); -} - -/** - * Determines whether or not the set is empty. - * - * ## Examples - * - * ```gleam - * new() |> is_empty - * // -> True - * ``` - * - * ```gleam - * new() |> insert(1) |> is_empty - * // -> False - * ``` - */ -export function is_empty(set) { - return isEqual(set, new$()); -} - -/** - * Checks whether a set contains a given member. - * - * This function runs in logarithmic time. - * - * ## Examples - * - * ```gleam - * new() - * |> insert(2) - * |> contains(2) - * // -> True - * ``` - * - * ```gleam - * new() - * |> insert(2) - * |> contains(1) - * // -> False - * ``` - */ -export function contains(set, member) { - let _pipe = set.dict; - let _pipe$1 = $dict.get(_pipe, member); - return $result.is_ok(_pipe$1); -} - -/** - * Removes a member from a set. If the set does not contain the member then - * the set is returned unchanged. - * - * This function runs in logarithmic time. - * - * ## Examples - * - * ```gleam - * new() - * |> insert(2) - * |> delete(2) - * |> contains(1) - * // -> False - * ``` - */ -export function delete$(set, member) { - return new Set($dict.delete$(set.dict, member)); -} - -/** - * Converts the set into a list of the contained members. - * - * The list has no specific ordering, any unintentional ordering may change in - * future versions of Gleam or Erlang. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * new() |> insert(2) |> to_list - * // -> [2] - * ``` - */ -export function to_list(set) { - return $dict.keys(set.dict); -} - -/** - * Combines all entries into a single value by calling a given function on each - * one. - * - * Sets are not ordered so the values are not returned in any specific order. - * Do not write code that relies on the order entries are used by this - * function as it may change in later versions of Gleam or Erlang. - * - * # Examples - * - * ```gleam - * from_list([1, 3, 9]) - * |> fold(0, fn(accumulator, member) { accumulator + member }) - * // -> 13 - * ``` - */ -export function fold(set, initial, reducer) { - return $dict.fold(set.dict, initial, (a, k, _) => { return reducer(a, k); }); -} - -/** - * Creates a new set from an existing set, minus any members that a given - * function returns `False` for. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * from_list([1, 4, 6, 3, 675, 44, 67]) - * |> filter(keeping: int.is_even) - * |> to_list - * // -> [4, 6, 44] - * ``` - */ -export function filter(set, predicate) { - return new Set($dict.filter(set.dict, (m, _) => { return predicate(m); })); -} - -/** - * Creates a new set from a given set with all the same entries except any - * entry found on the given list. - * - * ## Examples - * - * ```gleam - * from_list([1, 2, 3, 4]) - * |> drop([1, 3]) - * |> to_list - * // -> [2, 4] - * ``` - */ -export function drop(set, disallowed) { - return $list.fold(disallowed, set, delete$); -} - -/** - * Creates a new set from a given set, only including any members which are in - * a given list. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * from_list([1, 2, 3]) - * |> take([1, 3, 5]) - * |> to_list - * // -> [1, 3] - * ``` - */ -export function take(set, desired) { - return new Set($dict.take(set.dict, desired)); -} - -function order(first, second) { - let $ = $dict.size(first.dict) > $dict.size(second.dict); - if ($) { - return [first, second]; - } else { - return [second, first]; - } -} - -/** - * Creates a new set that contains members that are present in both given sets. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * intersection(from_list([1, 2]), from_list([2, 3])) |> to_list - * // -> [2] - * ``` - */ -export function intersection(first, second) { - let $ = order(first, second); - let larger; - let smaller; - larger = $[0]; - smaller = $[1]; - return take(larger, to_list(smaller)); -} - -/** - * Creates a new set that contains members that are present in the first set - * but not the second. - * - * ## Examples - * - * ```gleam - * difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list - * // -> [1] - * ``` - */ -export function difference(first, second) { - return drop(first, to_list(second)); -} - -/** - * Determines if a set is fully contained by another. - * - * ## Examples - * - * ```gleam - * is_subset(from_list([1]), from_list([1, 2])) - * // -> True - * ``` - * - * ```gleam - * is_subset(from_list([1, 2, 3]), from_list([3, 4, 5])) - * // -> False - * ``` - */ -export function is_subset(first, second) { - return isEqual(intersection(first, second), first); -} - -/** - * Determines if two sets contain no common members - * - * ## Examples - * - * ```gleam - * is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6])) - * // -> True - * ``` - * - * ```gleam - * is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5])) - * // -> False - * ``` - */ -export function is_disjoint(first, second) { - return isEqual(intersection(first, second), new$()); -} - -/** - * Calls a function for each member in a set, discarding the return - * value. - * - * Useful for producing a side effect for every item of a set. - * - * ```gleam - * let set = from_list(["apple", "banana", "cherry"]) - * - * each(set, io.println) - * // -> Nil - * // apple - * // banana - * // cherry - * ``` - * - * The order of elements in the iteration is an implementation detail that - * should not be relied upon. - */ -export function each(set, fun) { - return fold( - set, - undefined, - (nil, member) => { - fun(member); - return nil; - }, - ); -} - -const token = undefined; - -/** - * Inserts an member into the set. - * - * This function runs in logarithmic time. - * - * ## Examples - * - * ```gleam - * new() - * |> insert(1) - * |> insert(2) - * |> size - * // -> 2 - * ``` - */ -export function insert(set, member) { - return new Set($dict.insert(set.dict, member, token)); -} - -/** - * Creates a new set of the members in a given list. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * import gleam/int - * import gleam/list - * - * [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort(by: int.compare) - * // -> [1, 2, 3, 4] - * ``` - */ -export function from_list(members) { - let dict = $list.fold( - members, - $dict.new$(), - (m, k) => { return $dict.insert(m, k, token); }, - ); - return new Set(dict); -} - -/** - * Creates a new set from a given set with the result of applying the given - * function to each member. - * - * ## Examples - * - * ```gleam - * from_list([1, 2, 3, 4]) - * |> map(with: fn(x) { x * 2 }) - * |> to_list - * // -> [2, 4, 6, 8] - * ``` - */ -export function map(set, fun) { - return fold( - set, - new$(), - (acc, member) => { return insert(acc, fun(member)); }, - ); -} - -/** - * Creates a new set that contains all members of both given sets. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * union(from_list([1, 2]), from_list([2, 3])) |> to_list - * // -> [1, 2, 3] - * ``` - */ -export function union(first, second) { - let $ = order(first, second); - let larger; - let smaller; - larger = $[0]; - smaller = $[1]; - return fold(smaller, larger, insert); -} - -/** - * Creates a new set that contains members that are present in either set, but - * not both. - * - * ```gleam - * symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) |> to_list - * // -> [1, 2, 4] - * ``` - */ -export function symmetric_difference(first, second) { - return difference(union(first, second), intersection(first, second)); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/string.mjs b/build/dev/javascript/gleam_stdlib/gleam/string.mjs deleted file mode 100644 index d15468e..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/string.mjs +++ /dev/null @@ -1,723 +0,0 @@ -import { - Ok, - Error, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - remainderInt, - divideInt, -} from "../gleam.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $option from "../gleam/option.mjs"; -import { None, Some } from "../gleam/option.mjs"; -import * as $order from "../gleam/order.mjs"; -import * as $string_tree from "../gleam/string_tree.mjs"; -import { - string_length as length, - lowercase, - uppercase, - less_than, - string_grapheme_slice as grapheme_slice, - string_byte_slice as unsafe_byte_slice, - crop_string as crop, - contains_string as contains, - starts_with, - ends_with, - split_once, - trim_start, - trim_end, - pop_grapheme, - graphemes as to_graphemes, - codepoint as unsafe_int_to_utf_codepoint, - string_to_codepoint_integer_list, - utf_codepoint_list_to_string as from_utf_codepoints, - utf_codepoint_to_int, - inspect as do_inspect, - byte_size, -} from "../gleam_stdlib.mjs"; - -export { - byte_size, - contains, - crop, - ends_with, - from_utf_codepoints, - length, - lowercase, - pop_grapheme, - split_once, - starts_with, - to_graphemes, - trim_end, - trim_start, - uppercase, - utf_codepoint_to_int, -}; - -class Leading extends $CustomType {} - -class Trailing extends $CustomType {} - -/** - * Determines if a `String` is empty. - * - * ## Examples - * - * ```gleam - * is_empty("") - * // -> True - * ``` - * - * ```gleam - * is_empty("the world") - * // -> False - * ``` - */ -export function is_empty(str) { - return str === ""; -} - -/** - * Reverses a `String`. - * - * This function has to iterate across the whole `String` so it runs in linear - * time. Avoid using this in a loop. - * - * ## Examples - * - * ```gleam - * reverse("stressed") - * // -> "desserts" - * ``` - */ -export function reverse(string) { - let _pipe = string; - let _pipe$1 = $string_tree.from_string(_pipe); - let _pipe$2 = $string_tree.reverse(_pipe$1); - return $string_tree.to_string(_pipe$2); -} - -/** - * Creates a new `String` by replacing all occurrences of a given substring. - * - * ## Examples - * - * ```gleam - * replace("www.example.com", each: ".", with: "-") - * // -> "www-example-com" - * ``` - * - * ```gleam - * replace("a,b,c,d,e", each: ",", with: "/") - * // -> "a/b/c/d/e" - * ``` - */ -export function replace(string, pattern, substitute) { - let _pipe = string; - let _pipe$1 = $string_tree.from_string(_pipe); - let _pipe$2 = $string_tree.replace(_pipe$1, pattern, substitute); - return $string_tree.to_string(_pipe$2); -} - -/** - * Compares two `String`s to see which is "larger" by comparing their graphemes. - * - * This does not compare the size or length of the given `String`s. - * - * ## Examples - * - * ```gleam - * compare("Anthony", "Anthony") - * // -> order.Eq - * ``` - * - * ```gleam - * compare("A", "B") - * // -> order.Lt - * ``` - */ -export function compare(a, b) { - let $ = a === b; - if ($) { - return new $order.Eq(); - } else { - let $1 = less_than(a, b); - if ($1) { - return new $order.Lt(); - } else { - return new $order.Gt(); - } - } -} - -/** - * Takes a substring given a start grapheme index and a length. Negative indexes - * are taken starting from the *end* of the list. - * - * This function runs in linear time with the size of the index and the - * length. Negative indexes are linear with the size of the input string in - * addition to the other costs. - * - * ## Examples - * - * ```gleam - * slice(from: "gleam", at_index: 1, length: 2) - * // -> "le" - * ``` - * - * ```gleam - * slice(from: "gleam", at_index: 1, length: 10) - * // -> "leam" - * ``` - * - * ```gleam - * slice(from: "gleam", at_index: 10, length: 3) - * // -> "" - * ``` - * - * ```gleam - * slice(from: "gleam", at_index: -2, length: 2) - * // -> "am" - * ``` - * - * ```gleam - * slice(from: "gleam", at_index: -12, length: 2) - * // -> "" - * ``` - */ -export function slice(string, idx, len) { - let $ = len <= 0; - if ($) { - return ""; - } else { - let $1 = idx < 0; - if ($1) { - let translated_idx = length(string) + idx; - let $2 = translated_idx < 0; - if ($2) { - return ""; - } else { - return grapheme_slice(string, translated_idx, len); - } - } else { - return grapheme_slice(string, idx, len); - } - } -} - -/** - * Drops *n* graphemes from the end of a `String`. - * - * This function traverses the full string, so it runs in linear time with the - * size of the string. Avoid using this in a loop. - * - * ## Examples - * - * ```gleam - * drop_end(from: "Cigarette Smoking Man", up_to: 2) - * // -> "Cigarette Smoking M" - * ``` - */ -export function drop_end(string, num_graphemes) { - let $ = num_graphemes <= 0; - if ($) { - return string; - } else { - return slice(string, 0, length(string) - num_graphemes); - } -} - -/** - * Creates a new `String` by joining two `String`s together. - * - * This function typically copies both `String`s and runs in linear time, but - * the exact behaviour will depend on how the runtime you are using optimises - * your code. Benchmark and profile your code if you need to understand its - * performance better. - * - * If you are joining together large string and want to avoid copying any data - * you may want to investigate using the [`string_tree`](../gleam/string_tree.html) - * module. - * - * ## Examples - * - * ```gleam - * append(to: "butter", suffix: "fly") - * // -> "butterfly" - * ``` - */ -export function append(first, second) { - return first + second; -} - -function concat_loop(loop$strings, loop$accumulator) { - while (true) { - let strings = loop$strings; - let accumulator = loop$accumulator; - if (strings instanceof $Empty) { - return accumulator; - } else { - let string = strings.head; - let strings$1 = strings.tail; - loop$strings = strings$1; - loop$accumulator = accumulator + string; - } - } -} - -/** - * Creates a new `String` by joining many `String`s together. - * - * This function copies all the `String`s and runs in linear time. - * - * ## Examples - * - * ```gleam - * concat(["never", "the", "less"]) - * // -> "nevertheless" - * ``` - */ -export function concat(strings) { - return concat_loop(strings, ""); -} - -function repeat_loop(loop$times, loop$doubling_acc, loop$acc) { - while (true) { - let times = loop$times; - let doubling_acc = loop$doubling_acc; - let acc = loop$acc; - let _block; - let $ = times % 2; - if ($ === 0) { - _block = acc; - } else { - _block = acc + doubling_acc; - } - let acc$1 = _block; - let times$1 = globalThis.Math.trunc(times / 2); - let $1 = times$1 <= 0; - if ($1) { - return acc$1; - } else { - loop$times = times$1; - loop$doubling_acc = doubling_acc + doubling_acc; - loop$acc = acc$1; - } - } -} - -/** - * Creates a new `String` by repeating a `String` a given number of times. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * repeat("ha", times: 3) - * // -> "hahaha" - * ``` - */ -export function repeat(string, times) { - let $ = times <= 0; - if ($) { - return ""; - } else { - return repeat_loop(times, string, ""); - } -} - -function join_loop(loop$strings, loop$separator, loop$accumulator) { - while (true) { - let strings = loop$strings; - let separator = loop$separator; - let accumulator = loop$accumulator; - if (strings instanceof $Empty) { - return accumulator; - } else { - let string = strings.head; - let strings$1 = strings.tail; - loop$strings = strings$1; - loop$separator = separator; - loop$accumulator = (accumulator + separator) + string; - } - } -} - -/** - * Joins many `String`s together with a given separator. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * join(["home","evan","Desktop"], with: "/") - * // -> "home/evan/Desktop" - * ``` - */ -export function join(strings, separator) { - if (strings instanceof $Empty) { - return ""; - } else { - let first$1 = strings.head; - let rest = strings.tail; - return join_loop(rest, separator, first$1); - } -} - -function padding(size, pad_string) { - let pad_string_length = length(pad_string); - let num_pads = divideInt(size, pad_string_length); - let extra = remainderInt(size, pad_string_length); - return repeat(pad_string, num_pads) + slice(pad_string, 0, extra); -} - -/** - * Pads the start of a `String` until it has a given length. - * - * ## Examples - * - * ```gleam - * pad_start("121", to: 5, with: ".") - * // -> "..121" - * ``` - * - * ```gleam - * pad_start("121", to: 3, with: ".") - * // -> "121" - * ``` - * - * ```gleam - * pad_start("121", to: 2, with: ".") - * // -> "121" - * ``` - */ -export function pad_start(string, desired_length, pad_string) { - let current_length = length(string); - let to_pad_length = desired_length - current_length; - let $ = to_pad_length <= 0; - if ($) { - return string; - } else { - return padding(to_pad_length, pad_string) + string; - } -} - -/** - * Pads the end of a `String` until it has a given length. - * - * ## Examples - * - * ```gleam - * pad_end("123", to: 5, with: ".") - * // -> "123.." - * ``` - * - * ```gleam - * pad_end("123", to: 3, with: ".") - * // -> "123" - * ``` - * - * ```gleam - * pad_end("123", to: 2, with: ".") - * // -> "123" - * ``` - */ -export function pad_end(string, desired_length, pad_string) { - let current_length = length(string); - let to_pad_length = desired_length - current_length; - let $ = to_pad_length <= 0; - if ($) { - return string; - } else { - return string + padding(to_pad_length, pad_string); - } -} - -/** - * Removes whitespace on both sides of a `String`. - * - * Whitespace in this function is the set of nonbreakable whitespace - * codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1]. - * - * [1]: https://unicode.org/reports/tr31/ - * - * ## Examples - * - * ```gleam - * trim(" hats \n") - * // -> "hats" - * ``` - */ -export function trim(string) { - let _pipe = string; - let _pipe$1 = trim_start(_pipe); - return trim_end(_pipe$1); -} - -function to_graphemes_loop(loop$string, loop$acc) { - while (true) { - let string = loop$string; - let acc = loop$acc; - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let grapheme = $[0][0]; - let rest = $[0][1]; - loop$string = rest; - loop$acc = listPrepend(grapheme, acc); - } else { - return acc; - } - } -} - -/** - * Creates a list of `String`s by splitting a given string on a given substring. - * - * ## Examples - * - * ```gleam - * split("home/gleam/desktop/", on: "/") - * // -> ["home", "gleam", "desktop", ""] - * ``` - */ -export function split(x, substring) { - if (substring === "") { - return to_graphemes(x); - } else { - let _pipe = x; - let _pipe$1 = $string_tree.from_string(_pipe); - let _pipe$2 = $string_tree.split(_pipe$1, substring); - return $list.map(_pipe$2, $string_tree.to_string); - } -} - -function do_to_utf_codepoints(string) { - let _pipe = string; - let _pipe$1 = string_to_codepoint_integer_list(_pipe); - return $list.map(_pipe$1, unsafe_int_to_utf_codepoint); -} - -/** - * Converts a `String` to a `List` of `UtfCodepoint`. - * - * See and - * for an - * explanation on code points. - * - * ## Examples - * - * ```gleam - * "a" |> to_utf_codepoints - * // -> [UtfCodepoint(97)] - * ``` - * - * ```gleam - * // Semantically the same as: - * // ["🏳", "️", "‍", "🌈"] or: - * // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow] - * "🏳️‍🌈" |> to_utf_codepoints - * // -> [ - * // UtfCodepoint(127987), - * // UtfCodepoint(65039), - * // UtfCodepoint(8205), - * // UtfCodepoint(127752), - * // ] - * ``` - */ -export function to_utf_codepoints(string) { - return do_to_utf_codepoints(string); -} - -/** - * Converts an integer to a `UtfCodepoint`. - * - * Returns an `Error` if the integer does not represent a valid UTF codepoint. - */ -export function utf_codepoint(value) { - let i = value; - if (i > 1_114_111) { - return new Error(undefined); - } else { - let i$1 = value; - if ((i$1 >= 55_296) && (i$1 <= 57_343)) { - return new Error(undefined); - } else { - let i$2 = value; - if (i$2 < 0) { - return new Error(undefined); - } else { - let i$3 = value; - return new Ok(unsafe_int_to_utf_codepoint(i$3)); - } - } - } -} - -/** - * Converts a `String` into `Option(String)` where an empty `String` becomes - * `None`. - * - * ## Examples - * - * ```gleam - * to_option("") - * // -> None - * ``` - * - * ```gleam - * to_option("hats") - * // -> Some("hats") - * ``` - */ -export function to_option(string) { - if (string === "") { - return new None(); - } else { - return new Some(string); - } -} - -/** - * Returns the first grapheme cluster in a given `String` and wraps it in a - * `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. - * Otherwise, it returns `Ok(String)`. - * - * ## Examples - * - * ```gleam - * first("") - * // -> Error(Nil) - * ``` - * - * ```gleam - * first("icecream") - * // -> Ok("i") - * ``` - */ -export function first(string) { - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let first$1 = $[0][0]; - return new Ok(first$1); - } else { - return $; - } -} - -/** - * Returns the last grapheme cluster in a given `String` and wraps it in a - * `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. - * Otherwise, it returns `Ok(String)`. - * - * This function traverses the full string, so it runs in linear time with the - * length of the string. Avoid using this in a loop. - * - * ## Examples - * - * ```gleam - * last("") - * // -> Error(Nil) - * ``` - * - * ```gleam - * last("icecream") - * // -> Ok("m") - * ``` - */ -export function last(string) { - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let $1 = $[0][1]; - if ($1 === "") { - let first$1 = $[0][0]; - return new Ok(first$1); - } else { - let rest = $1; - return new Ok(slice(rest, -1, 1)); - } - } else { - return $; - } -} - -/** - * Creates a new `String` with the first grapheme in the input `String` - * converted to uppercase and the remaining graphemes to lowercase. - * - * ## Examples - * - * ```gleam - * capitalise("mamouna") - * // -> "Mamouna" - * ``` - */ -export function capitalise(string) { - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let first$1 = $[0][0]; - let rest = $[0][1]; - return append(uppercase(first$1), lowercase(rest)); - } else { - return ""; - } -} - -/** - * Returns a `String` representation of a term in Gleam syntax. - * - * This may be occasionally useful for quick-and-dirty printing of values in - * scripts. For error reporting and other uses prefer constructing strings by - * pattern matching on the values. - * - * ## Limitations - * - * The output format of this function is not stable and could change at any - * time. The output is not suitable for parsing. - * - * This function works using runtime reflection, so the output may not be - * perfectly accurate for data structures where the runtime structure doesn't - * hold enough information to determine the original syntax. For example, - * tuples with an Erlang atom in the first position will be mistaken for Gleam - * records. - * - * ## Security and safety - * - * There is no limit to how large the strings that this function can produce. - * Be careful not to call this function with large data structures or you - * could use very large amounts of memory, potentially causing runtime - * problems. - */ -export function inspect(term) { - let _pipe = term; - let _pipe$1 = do_inspect(_pipe); - return $string_tree.to_string(_pipe$1); -} - -/** - * Drops *n* graphemes from the start of a `String`. - * - * This function runs in linear time with the number of graphemes to drop. - * - * ## Examples - * - * ```gleam - * drop_start(from: "The Lone Gunmen", up_to: 2) - * // -> "e Lone Gunmen" - * ``` - */ -export function drop_start(string, num_graphemes) { - let $ = num_graphemes <= 0; - if ($) { - return string; - } else { - let prefix = grapheme_slice(string, 0, num_graphemes); - let prefix_size = byte_size(prefix); - return unsafe_byte_slice( - string, - prefix_size, - byte_size(string) - prefix_size, - ); - } -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs b/build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs deleted file mode 100644 index a8b24ce..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs +++ /dev/null @@ -1,133 +0,0 @@ -import { toList, CustomType as $CustomType, isEqual } from "../gleam.mjs"; -import * as $list from "../gleam/list.mjs"; -import { - add as append_tree, - concat as from_strings, - concat, - identity as from_string, - identity as to_string, - length as byte_size, - lowercase, - uppercase, - graphemes as do_to_graphemes, - split, - string_replace as replace, -} from "../gleam_stdlib.mjs"; - -export { - append_tree, - byte_size, - concat, - from_string, - from_strings, - lowercase, - replace, - split, - to_string, - uppercase, -}; - -class All extends $CustomType {} - -/** - * Prepends some `StringTree` onto the start of another. - * - * Runs in constant time. - */ -export function prepend_tree(tree, prefix) { - return append_tree(prefix, tree); -} - -/** - * Create an empty `StringTree`. Useful as the start of a pipe chaining many - * trees together. - */ -export function new$() { - return from_strings(toList([])); -} - -/** - * Prepends a `String` onto the start of some `StringTree`. - * - * Runs in constant time. - */ -export function prepend(tree, prefix) { - return append_tree(from_string(prefix), tree); -} - -/** - * Appends a `String` onto the end of some `StringTree`. - * - * Runs in constant time. - */ -export function append(tree, second) { - return append_tree(tree, from_string(second)); -} - -/** - * Joins the given trees into a new tree separated with the given string. - */ -export function join(trees, sep) { - let _pipe = trees; - let _pipe$1 = $list.intersperse(_pipe, from_string(sep)); - return concat(_pipe$1); -} - -/** - * Converts a `StringTree` to a new one with the contents reversed. - */ -export function reverse(tree) { - let _pipe = tree; - let _pipe$1 = to_string(_pipe); - let _pipe$2 = do_to_graphemes(_pipe$1); - let _pipe$3 = $list.reverse(_pipe$2); - return from_strings(_pipe$3); -} - -/** - * Compares two string trees to determine if they have the same textual - * content. - * - * Comparing two string trees using the `==` operator may return `False` even - * if they have the same content as they may have been build in different ways, - * so using this function is often preferred. - * - * ## Examples - * - * ```gleam - * from_strings(["a", "b"]) == from_string("ab") - * // -> False - * ``` - * - * ```gleam - * is_equal(from_strings(["a", "b"]), from_string("ab")) - * // -> True - * ``` - */ -export function is_equal(a, b) { - return isEqual(a, b); -} - -/** - * Inspects a `StringTree` to determine if it is equivalent to an empty string. - * - * ## Examples - * - * ```gleam - * from_string("ok") |> is_empty - * // -> False - * ``` - * - * ```gleam - * from_string("") |> is_empty - * // -> True - * ``` - * - * ```gleam - * from_strings([]) |> is_empty - * // -> True - * ``` - */ -export function is_empty(tree) { - return isEqual(from_string(""), tree); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam/uri.mjs b/build/dev/javascript/gleam_stdlib/gleam/uri.mjs deleted file mode 100644 index 01f4bba..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam/uri.mjs +++ /dev/null @@ -1,1147 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - isEqual, -} from "../gleam.mjs"; -import * as $int from "../gleam/int.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $option from "../gleam/option.mjs"; -import { None, Some } from "../gleam/option.mjs"; -import * as $string from "../gleam/string.mjs"; -import * as $string_tree from "../gleam/string_tree.mjs"; -import { - pop_codeunit, - string_codeunit_slice as codeunit_slice, - parse_query, - percent_encode, - percent_decode, -} from "../gleam_stdlib.mjs"; - -export { parse_query, percent_decode, percent_encode }; - -export class Uri extends $CustomType { - constructor(scheme, userinfo, host, port, path, query, fragment) { - super(); - this.scheme = scheme; - this.userinfo = userinfo; - this.host = host; - this.port = port; - this.path = path; - this.query = query; - this.fragment = fragment; - } -} -export const Uri$Uri = (scheme, userinfo, host, port, path, query, fragment) => - new Uri(scheme, userinfo, host, port, path, query, fragment); -export const Uri$isUri = (value) => value instanceof Uri; -export const Uri$Uri$scheme = (value) => value.scheme; -export const Uri$Uri$0 = (value) => value.scheme; -export const Uri$Uri$userinfo = (value) => value.userinfo; -export const Uri$Uri$1 = (value) => value.userinfo; -export const Uri$Uri$host = (value) => value.host; -export const Uri$Uri$2 = (value) => value.host; -export const Uri$Uri$port = (value) => value.port; -export const Uri$Uri$3 = (value) => value.port; -export const Uri$Uri$path = (value) => value.path; -export const Uri$Uri$4 = (value) => value.path; -export const Uri$Uri$query = (value) => value.query; -export const Uri$Uri$5 = (value) => value.query; -export const Uri$Uri$fragment = (value) => value.fragment; -export const Uri$Uri$6 = (value) => value.fragment; - -function is_valid_host_within_brackets_char(char) { - return (((((48 >= char) && (char <= 57)) || ((65 >= char) && (char <= 90))) || ((97 >= char) && (char <= 122))) || (char === 58)) || (char === 46); -} - -function parse_fragment(rest, pieces) { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - new Some(rest), - ), - ); -} - -function parse_query_with_question_mark_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string.startsWith("#")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else { - let rest = uri_string.slice(1); - let query = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - new Some(query), - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - new Some(original), - pieces.fragment, - ), - ); - } else { - let $ = pop_codeunit(uri_string); - let rest; - rest = $[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_query_with_question_mark(uri_string, pieces) { - return parse_query_with_question_mark_loop(uri_string, uri_string, pieces, 0); -} - -function parse_path_loop(loop$original, loop$uri_string, loop$pieces, loop$size) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string.startsWith("?")) { - let rest = uri_string.slice(1); - let path = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } else if (uri_string.startsWith("#")) { - let rest = uri_string.slice(1); - let path = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - original, - pieces.query, - pieces.fragment, - ), - ); - } else { - let $ = pop_codeunit(uri_string); - let rest; - rest = $[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_path(uri_string, pieces) { - return parse_path_loop(uri_string, uri_string, pieces, 0); -} - -function parse_port_loop(loop$uri_string, loop$pieces, loop$port) { - while (true) { - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let port = loop$port; - if (uri_string.startsWith("0")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10; - } else if (uri_string.startsWith("1")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 1; - } else if (uri_string.startsWith("2")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 2; - } else if (uri_string.startsWith("3")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 3; - } else if (uri_string.startsWith("4")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 4; - } else if (uri_string.startsWith("5")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 5; - } else if (uri_string.startsWith("6")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 6; - } else if (uri_string.startsWith("7")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 7; - } else if (uri_string.startsWith("8")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 8; - } else if (uri_string.startsWith("9")) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 9; - } else if (uri_string.startsWith("?")) { - let rest = uri_string.slice(1); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } else if (uri_string.startsWith("#")) { - let rest = uri_string.slice(1); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } else if (uri_string.startsWith("/")) { - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_path(uri_string, pieces$1); - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else { - return new Error(undefined); - } - } -} - -function parse_port(uri_string, pieces) { - if (uri_string.startsWith(":0")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 0); - } else if (uri_string.startsWith(":1")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 1); - } else if (uri_string.startsWith(":2")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 2); - } else if (uri_string.startsWith(":3")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 3); - } else if (uri_string.startsWith(":4")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 4); - } else if (uri_string.startsWith(":5")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 5); - } else if (uri_string.startsWith(":6")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 6); - } else if (uri_string.startsWith(":7")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 7); - } else if (uri_string.startsWith(":8")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 8); - } else if (uri_string.startsWith(":9")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 9); - } else if (uri_string === ":") { - return new Ok(pieces); - } else if (uri_string === "") { - return new Ok(pieces); - } else if (uri_string.startsWith("?")) { - let rest = uri_string.slice(1); - return parse_query_with_question_mark(rest, pieces); - } else if (uri_string.startsWith(":?")) { - let rest = uri_string.slice(2); - return parse_query_with_question_mark(rest, pieces); - } else if (uri_string.startsWith("#")) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else if (uri_string.startsWith(":#")) { - let rest = uri_string.slice(2); - return parse_fragment(rest, pieces); - } else if (uri_string.startsWith("/")) { - return parse_path(uri_string, pieces); - } else if (uri_string.startsWith(":")) { - let rest = uri_string.slice(1); - if (rest.startsWith("/")) { - return parse_path(rest, pieces); - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} - -function parse_host_outside_of_brackets_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(original), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else if (uri_string.startsWith(":")) { - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_port(uri_string, pieces$1); - } else if (uri_string.startsWith("/")) { - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_path(uri_string, pieces$1); - } else if (uri_string.startsWith("?")) { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } else if (uri_string.startsWith("#")) { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } else { - let $ = pop_codeunit(uri_string); - let rest; - rest = $[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_host_within_brackets_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(uri_string), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else if (uri_string.startsWith("]")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_port(rest, pieces); - } else { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size + 1); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_port(rest, pieces$1); - } - } else if (uri_string.startsWith("/")) { - if (size === 0) { - return parse_path(uri_string, pieces); - } else { - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_path(uri_string, pieces$1); - } - } else if (uri_string.startsWith("?")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_query_with_question_mark(rest, pieces); - } else { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } - } else if (uri_string.startsWith("#")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } - } else { - let $ = pop_codeunit(uri_string); - let char; - let rest; - char = $[0]; - rest = $[1]; - let $1 = is_valid_host_within_brackets_char(char); - if ($1) { - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } else { - return parse_host_outside_of_brackets_loop( - original, - original, - pieces, - 0, - ); - } - } - } -} - -function parse_host_within_brackets(uri_string, pieces) { - return parse_host_within_brackets_loop(uri_string, uri_string, pieces, 0); -} - -function parse_host_outside_of_brackets(uri_string, pieces) { - return parse_host_outside_of_brackets_loop(uri_string, uri_string, pieces, 0); -} - -function parse_host(uri_string, pieces) { - if (uri_string.startsWith("[")) { - return parse_host_within_brackets(uri_string, pieces); - } else if (uri_string.startsWith(":")) { - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(""), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_port(uri_string, pieces$1); - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(""), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else { - return parse_host_outside_of_brackets(uri_string, pieces); - } -} - -function parse_userinfo_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string.startsWith("@")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_host(rest, pieces); - } else { - let rest = uri_string.slice(1); - let userinfo = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - new Some(userinfo), - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_host(rest, pieces$1); - } - } else if (uri_string === "") { - return parse_host(original, pieces); - } else if (uri_string.startsWith("/")) { - return parse_host(original, pieces); - } else if (uri_string.startsWith("?")) { - return parse_host(original, pieces); - } else if (uri_string.startsWith("#")) { - return parse_host(original, pieces); - } else { - let $ = pop_codeunit(uri_string); - let rest; - rest = $[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_authority_pieces(string, pieces) { - return parse_userinfo_loop(string, string, pieces, 0); -} - -function parse_authority_with_slashes(uri_string, pieces) { - if (uri_string === "//") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(""), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else if (uri_string.startsWith("//")) { - let rest = uri_string.slice(2); - return parse_authority_pieces(rest, pieces); - } else { - return parse_path(uri_string, pieces); - } -} - -function parse_scheme_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string.startsWith("/")) { - if (size === 0) { - return parse_authority_with_slashes(uri_string, pieces); - } else { - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_authority_with_slashes(uri_string, pieces$1); - } - } else if (uri_string.startsWith("?")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_query_with_question_mark(rest, pieces); - } else { - let rest = uri_string.slice(1); - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } - } else if (uri_string.startsWith("#")) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else { - let rest = uri_string.slice(1); - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } - } else if (uri_string.startsWith(":")) { - if (size === 0) { - return new Error(undefined); - } else { - let rest = uri_string.slice(1); - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_authority_with_slashes(rest, pieces$1); - } - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - original, - pieces.query, - pieces.fragment, - ), - ); - } else { - let $ = pop_codeunit(uri_string); - let rest; - rest = $[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function query_pair(pair) { - return $string_tree.from_strings( - toList([percent_encode(pair[0]), "=", percent_encode(pair[1])]), - ); -} - -/** - * Encodes a list of key value pairs as a URI query string. - * - * The opposite operation is `uri.parse_query`. - * - * ## Examples - * - * ```gleam - * query_to_string([#("a", "1"), #("b", "2")]) - * // -> "a=1&b=2" - * ``` - */ -export function query_to_string(query) { - let _pipe = query; - let _pipe$1 = $list.map(_pipe, query_pair); - let _pipe$2 = $list.intersperse(_pipe$1, $string_tree.from_string("&")); - let _pipe$3 = $string_tree.concat(_pipe$2); - return $string_tree.to_string(_pipe$3); -} - -function remove_dot_segments_loop(loop$input, loop$accumulator) { - while (true) { - let input = loop$input; - let accumulator = loop$accumulator; - if (input instanceof $Empty) { - return $list.reverse(accumulator); - } else { - let segment = input.head; - let rest = input.tail; - let _block; - if (segment === "") { - _block = accumulator; - } else if (segment === ".") { - _block = accumulator; - } else if (segment === "..") { - if (accumulator instanceof $Empty) { - _block = accumulator; - } else { - let accumulator$1 = accumulator.tail; - _block = accumulator$1; - } - } else { - let segment$1 = segment; - let accumulator$1 = accumulator; - _block = listPrepend(segment$1, accumulator$1); - } - let accumulator$1 = _block; - loop$input = rest; - loop$accumulator = accumulator$1; - } - } -} - -function remove_dot_segments(input) { - return remove_dot_segments_loop(input, toList([])); -} - -/** - * Splits the path section of a URI into it's constituent segments. - * - * Removes empty segments and resolves dot-segments as specified in - * [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC. - * - * ## Examples - * - * ```gleam - * path_segments("/users/1") - * // -> ["users" ,"1"] - * ``` - */ -export function path_segments(path) { - return remove_dot_segments($string.split(path, "/")); -} - -/** - * Encodes a `Uri` value as a URI string. - * - * The opposite operation is `uri.parse`. - * - * ## Examples - * - * ```gleam - * let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com")) - * to_string(uri) - * // -> "https://example.com" - * ``` - */ -export function to_string(uri) { - let _block; - let $ = uri.fragment; - if ($ instanceof Some) { - let fragment = $[0]; - _block = toList(["#", fragment]); - } else { - _block = toList([]); - } - let parts = _block; - let _block$1; - let $1 = uri.query; - if ($1 instanceof Some) { - let query = $1[0]; - _block$1 = listPrepend("?", listPrepend(query, parts)); - } else { - _block$1 = parts; - } - let parts$1 = _block$1; - let parts$2 = listPrepend(uri.path, parts$1); - let _block$2; - let $2 = uri.host; - let $3 = $string.starts_with(uri.path, "/"); - if ($2 instanceof Some && !$3) { - let host = $2[0]; - if (host !== "") { - _block$2 = listPrepend("/", parts$2); - } else { - _block$2 = parts$2; - } - } else { - _block$2 = parts$2; - } - let parts$3 = _block$2; - let _block$3; - let $4 = uri.host; - let $5 = uri.port; - if ($4 instanceof Some && $5 instanceof Some) { - let port = $5[0]; - _block$3 = listPrepend(":", listPrepend($int.to_string(port), parts$3)); - } else { - _block$3 = parts$3; - } - let parts$4 = _block$3; - let _block$4; - let $6 = uri.scheme; - let $7 = uri.userinfo; - let $8 = uri.host; - if ($6 instanceof Some) { - if ($7 instanceof Some) { - if ($8 instanceof Some) { - let s = $6[0]; - let u = $7[0]; - let h = $8[0]; - _block$4 = listPrepend( - s, - listPrepend( - "://", - listPrepend(u, listPrepend("@", listPrepend(h, parts$4))), - ), - ); - } else { - let s = $6[0]; - _block$4 = listPrepend(s, listPrepend(":", parts$4)); - } - } else if ($8 instanceof Some) { - let s = $6[0]; - let h = $8[0]; - _block$4 = listPrepend(s, listPrepend("://", listPrepend(h, parts$4))); - } else { - let s = $6[0]; - _block$4 = listPrepend(s, listPrepend(":", parts$4)); - } - } else if ($7 instanceof None && $8 instanceof Some) { - let h = $8[0]; - _block$4 = listPrepend("//", listPrepend(h, parts$4)); - } else { - _block$4 = parts$4; - } - let parts$5 = _block$4; - return $string.concat(parts$5); -} - -/** - * Fetches the origin of a URI. - * - * Returns the origin of a uri as defined in - * [RFC 6454](https://tools.ietf.org/html/rfc6454) - * - * The supported URI schemes are `http` and `https`. - * URLs without a scheme will return `Error`. - * - * ## Examples - * - * ```gleam - * let assert Ok(uri) = parse("https://example.com/path?foo#bar") - * origin(uri) - * // -> Ok("https://example.com") - * ``` - */ -export function origin(uri) { - let scheme; - let host; - let port; - scheme = uri.scheme; - host = uri.host; - port = uri.port; - if (host instanceof Some && scheme instanceof Some) { - let $ = scheme[0]; - if ($ === "https" && isEqual(port, new Some(443))) { - let h = host[0]; - return new Ok($string.concat(toList(["https://", h]))); - } else if ($ === "http" && isEqual(port, new Some(80))) { - let h = host[0]; - return new Ok($string.concat(toList(["http://", h]))); - } else { - let s = $; - if ((s === "http") || (s === "https")) { - let h = host[0]; - if (port instanceof Some) { - let p = port[0]; - return new Ok( - $string.concat(toList([s, "://", h, ":", $int.to_string(p)])), - ); - } else { - return new Ok($string.concat(toList([s, "://", h]))); - } - } else { - return new Error(undefined); - } - } - } else { - return new Error(undefined); - } -} - -function drop_last(elements) { - return $list.take(elements, $list.length(elements) - 1); -} - -function join_segments(segments) { - return $string.join(listPrepend("", segments), "/"); -} - -/** - * Resolves a URI with respect to the given base URI. - * - * The base URI must be an absolute URI or this function will return an error. - * The algorithm for merging uris is described in - * [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2). - */ -export function merge(base, relative) { - let $ = base.scheme; - if ($ instanceof Some) { - let $1 = base.host; - if ($1 instanceof Some) { - let $2 = relative.host; - if ($2 instanceof Some) { - let _block; - let _pipe = relative.path; - let _pipe$1 = $string.split(_pipe, "/"); - let _pipe$2 = remove_dot_segments(_pipe$1); - _block = join_segments(_pipe$2); - let path = _block; - let resolved = new Uri( - $option.or(relative.scheme, base.scheme), - new None(), - relative.host, - $option.or(relative.port, base.port), - path, - relative.query, - relative.fragment, - ); - return new Ok(resolved); - } else { - let _block; - let $4 = relative.path; - if ($4 === "") { - _block = [base.path, $option.or(relative.query, base.query)]; - } else { - let _block$1; - let $5 = $string.starts_with(relative.path, "/"); - if ($5) { - _block$1 = $string.split(relative.path, "/"); - } else { - let _pipe = base.path; - let _pipe$1 = $string.split(_pipe, "/"); - let _pipe$2 = drop_last(_pipe$1); - _block$1 = $list.append(_pipe$2, $string.split(relative.path, "/")); - } - let path_segments$1 = _block$1; - let _block$2; - let _pipe = path_segments$1; - let _pipe$1 = remove_dot_segments(_pipe); - _block$2 = join_segments(_pipe$1); - let path = _block$2; - _block = [path, relative.query]; - } - let $3 = _block; - let new_path; - let new_query; - new_path = $3[0]; - new_query = $3[1]; - let resolved = new Uri( - base.scheme, - new None(), - base.host, - base.port, - new_path, - new_query, - relative.fragment, - ); - return new Ok(resolved); - } - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} - -/** - * Constant representing an empty URI, equivalent to "". - * - * ## Examples - * - * ```gleam - * let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com")) - * // -> Uri( - * // scheme: Some("https"), - * // userinfo: None, - * // host: Some("example.com"), - * // port: None, - * // path: "", - * // query: None, - * // fragment: None, - * // ) - * ``` - */ -export const empty = /* @__PURE__ */ new Uri( - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), - "", - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), -); - -/** - * Parses a compliant URI string into the `Uri` Type. - * If the string is not a valid URI string then an error is returned. - * - * The opposite operation is `uri.to_string`. - * - * ## Examples - * - * ```gleam - * parse("https://example.com:1234/a/b?query=true#fragment") - * // -> Ok( - * // Uri( - * // scheme: Some("https"), - * // userinfo: None, - * // host: Some("example.com"), - * // port: Some(1234), - * // path: "/a/b", - * // query: Some("query=true"), - * // fragment: Some("fragment") - * // ) - * // ) - * ``` - */ -export function parse(uri_string) { - return parse_scheme_loop(uri_string, uri_string, empty, 0); -} diff --git a/build/dev/javascript/gleam_stdlib/gleam@bit_array.erl b/build/dev/javascript/gleam_stdlib/gleam@bit_array.erl deleted file mode 100644 index 7df56ce..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@bit_array.erl +++ /dev/null @@ -1,347 +0,0 @@ --module(gleam@bit_array). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bit_array.gleam"). --export([from_string/1, bit_size/1, byte_size/1, pad_to_bytes/1, slice/3, is_utf8/1, to_string/1, concat/1, append/2, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1, inspect/1, compare/2, starts_with/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(" BitArrays are a sequence of binary data of any length.\n"). - --file("src/gleam/bit_array.gleam", 11). -?DOC(" Converts a UTF-8 `String` type into a `BitArray`.\n"). --spec from_string(binary()) -> bitstring(). -from_string(X) -> - gleam_stdlib:identity(X). - --file("src/gleam/bit_array.gleam", 17). -?DOC(" Returns an integer which is the number of bits in the bit array.\n"). --spec bit_size(bitstring()) -> integer(). -bit_size(X) -> - erlang:bit_size(X). - --file("src/gleam/bit_array.gleam", 23). -?DOC(" Returns an integer which is the number of bytes in the bit array.\n"). --spec byte_size(bitstring()) -> integer(). -byte_size(X) -> - erlang:byte_size(X). - --file("src/gleam/bit_array.gleam", 29). -?DOC(" Pads a bit array with zeros so that it is a whole number of bytes.\n"). --spec pad_to_bytes(bitstring()) -> bitstring(). -pad_to_bytes(X) -> - gleam_stdlib:bit_array_pad_to_bytes(X). - --file("src/gleam/bit_array.gleam", 54). -?DOC( - " Extracts a sub-section of a bit array.\n" - "\n" - " The slice will start at given position and continue up to specified\n" - " length.\n" - " A negative length can be used to extract bytes at the end of a bit array.\n" - "\n" - " This function runs in constant time.\n" -). --spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | - {error, nil}. -slice(String, Position, Length) -> - gleam_stdlib:bit_array_slice(String, Position, Length). - --file("src/gleam/bit_array.gleam", 67). --spec is_utf8_loop(bitstring()) -> boolean(). -is_utf8_loop(Bits) -> - case Bits of - <<>> -> - true; - - <<_/utf8, Rest/binary>> -> - is_utf8_loop(Rest); - - _ -> - false - end. - --file("src/gleam/bit_array.gleam", 62). -?DOC(" Tests to see whether a bit array is valid UTF-8.\n"). --spec is_utf8(bitstring()) -> boolean(). -is_utf8(Bits) -> - is_utf8_loop(Bits). - --file("src/gleam/bit_array.gleam", 88). -?DOC( - " Converts a bit array to a string.\n" - "\n" - " Returns an error if the bit array is invalid UTF-8 data.\n" -). --spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. -to_string(Bits) -> - case is_utf8(Bits) of - true -> - {ok, gleam_stdlib:identity(Bits)}; - - false -> - {error, nil} - end. - --file("src/gleam/bit_array.gleam", 109). -?DOC( - " Creates a new bit array by joining multiple binaries.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " concat([from_string(\"butter\"), from_string(\"fly\")])\n" - " // -> from_string(\"butterfly\")\n" - " ```\n" -). --spec concat(list(bitstring())) -> bitstring(). -concat(Bit_arrays) -> - gleam_stdlib:bit_array_concat(Bit_arrays). - --file("src/gleam/bit_array.gleam", 40). -?DOC( - " Creates a new bit array by joining two bit arrays.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " append(to: from_string(\"butter\"), suffix: from_string(\"fly\"))\n" - " // -> from_string(\"butterfly\")\n" - " ```\n" -). --spec append(bitstring(), bitstring()) -> bitstring(). -append(First, Second) -> - gleam_stdlib:bit_array_concat([First, Second]). - --file("src/gleam/bit_array.gleam", 118). -?DOC( - " Encodes a BitArray into a base 64 encoded string.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base64_encode(bitstring(), boolean()) -> binary(). -base64_encode(Input, Padding) -> - gleam_stdlib:base64_encode(Input, Padding). - --file("src/gleam/bit_array.gleam", 122). -?DOC(" Decodes a base 64 encoded string into a `BitArray`.\n"). --spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base64_decode(Encoded) -> - Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of - 0 -> - Encoded; - - N -> - gleam@string:append( - Encoded, - gleam@string:repeat(<<"="/utf8>>, 4 - N) - ) - end, - gleam_stdlib:base64_decode(Padded). - --file("src/gleam/bit_array.gleam", 140). -?DOC( - " Encodes a `BitArray` into a base 64 encoded string with URL and filename\n" - " safe alphabet.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base64_url_encode(bitstring(), boolean()) -> binary(). -base64_url_encode(Input, Padding) -> - _pipe = Input, - _pipe@1 = gleam_stdlib:base64_encode(_pipe, Padding), - _pipe@2 = gleam@string:replace(_pipe@1, <<"+"/utf8>>, <<"-"/utf8>>), - gleam@string:replace(_pipe@2, <<"/"/utf8>>, <<"_"/utf8>>). - --file("src/gleam/bit_array.gleam", 150). -?DOC( - " Decodes a base 64 encoded string with URL and filename safe alphabet into a\n" - " `BitArray`.\n" -). --spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base64_url_decode(Encoded) -> - _pipe = Encoded, - _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>), - _pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>), - base64_decode(_pipe@2). - --file("src/gleam/bit_array.gleam", 164). -?DOC( - " Encodes a `BitArray` into a base 16 encoded string.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base16_encode(bitstring()) -> binary(). -base16_encode(Input) -> - gleam_stdlib:base16_encode(Input). - --file("src/gleam/bit_array.gleam", 170). -?DOC(" Decodes a base 16 encoded string into a `BitArray`.\n"). --spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base16_decode(Input) -> - gleam_stdlib:base16_decode(Input). - --file("src/gleam/bit_array.gleam", 191). --spec inspect_loop(bitstring(), binary()) -> binary(). -inspect_loop(Input, Accumulator) -> - case Input of - <<>> -> - Accumulator; - - <> -> - <<<>/binary, - ":size(1)"/utf8>>; - - <> -> - <<<>/binary, - ":size(2)"/utf8>>; - - <> -> - <<<>/binary, - ":size(3)"/utf8>>; - - <> -> - <<<>/binary, - ":size(4)"/utf8>>; - - <> -> - <<<>/binary, - ":size(5)"/utf8>>; - - <> -> - <<<>/binary, - ":size(6)"/utf8>>; - - <> -> - <<<>/binary, - ":size(7)"/utf8>>; - - <> -> - Suffix = case Rest of - <<>> -> - <<""/utf8>>; - - _ -> - <<", "/utf8>> - end, - Accumulator@1 = <<<>/binary, - Suffix/binary>>, - inspect_loop(Rest, Accumulator@1); - - _ -> - Accumulator - end. - --file("src/gleam/bit_array.gleam", 187). -?DOC( - " Converts a bit array to a string containing the decimal value of each byte.\n" - "\n" - " Use this over `string.inspect` when you have a bit array you want printed\n" - " in the array syntax even if it is valid UTF-8.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " inspect(<<0, 20, 0x20, 255>>)\n" - " // -> \"<<0, 20, 32, 255>>\"\n" - "\n" - " inspect(<<100, 5:3>>)\n" - " // -> \"<<100, 5:size(3)>>\"\n" - " ```\n" -). --spec inspect(bitstring()) -> binary(). -inspect(Input) -> - <<(inspect_loop(Input, <<"<<"/utf8>>))/binary, ">>"/utf8>>. - --file("src/gleam/bit_array.gleam", 232). -?DOC( - " Compare two bit arrays as sequences of bytes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(<<1>>, <<2>>)\n" - " // -> Lt\n" - "\n" - " compare(<<\"AB\":utf8>>, <<\"AA\":utf8>>)\n" - " // -> Gt\n" - "\n" - " compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>)\n" - " // -> Eq\n" - " ```\n" -). --spec compare(bitstring(), bitstring()) -> gleam@order:order(). -compare(A, B) -> - case {A, B} of - {<>, - <>} -> - case {First_byte, Second_byte} of - {F, S} when F > S -> - gt; - - {F@1, S@1} when F@1 < S@1 -> - lt; - - {_, _} -> - compare(First_rest, Second_rest) - end; - - {<<>>, <<>>} -> - eq; - - {_, <<>>} -> - gt; - - {<<>>, _} -> - lt; - - {First, Second} -> - case {gleam_stdlib:bit_array_to_int_and_size(First), - gleam_stdlib:bit_array_to_int_and_size(Second)} of - {{A@1, _}, {B@1, _}} when A@1 > B@1 -> - gt; - - {{A@2, _}, {B@2, _}} when A@2 < B@2 -> - lt; - - {{_, Size_a}, {_, Size_b}} when Size_a > Size_b -> - gt; - - {{_, Size_a@1}, {_, Size_b@1}} when Size_a@1 < Size_b@1 -> - lt; - - {_, _} -> - eq - end - end. - --file("src/gleam/bit_array.gleam", 273). -?DOC( - " Checks whether the first `BitArray` starts with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " starts_with(<<1, 2, 3, 4>>, <<1, 2>>)\n" - " // -> True\n" - " ```\n" -). --spec starts_with(bitstring(), bitstring()) -> boolean(). -starts_with(Bits, Prefix) -> - Prefix_size = erlang:bit_size(Prefix), - case Bits of - <> when Pref =:= Prefix -> - true; - - _ -> - false - end. diff --git a/build/dev/javascript/gleam_stdlib/gleam@bool.erl b/build/dev/javascript/gleam_stdlib/gleam@bool.erl deleted file mode 100644 index 01307b3..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@bool.erl +++ /dev/null @@ -1,352 +0,0 @@ --module(gleam@bool). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bool.gleam"). --export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, to_string/1, guard/3, lazy_guard/3]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " A type with two possible values, `True` and `False`. Used to indicate whether\n" - " things are... true or false!\n" - "\n" - " Often is it clearer and offers more type safety to define a custom type\n" - " than to use `Bool`. For example, rather than having a `is_teacher: Bool`\n" - " field consider having a `role: SchoolRole` field where `SchoolRole` is a custom\n" - " type that can be either `Student` or `Teacher`.\n" -). - --file("src/gleam/bool.gleam", 31). -?DOC( - " Returns the and of two bools, but it evaluates both arguments.\n" - "\n" - " It's the function equivalent of the `&&` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " and(True, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " and(False, True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " False |> and(True)\n" - " // -> False\n" - " ```\n" -). --spec 'and'(boolean(), boolean()) -> boolean(). -'and'(A, B) -> - A andalso B. - --file("src/gleam/bool.gleam", 57). -?DOC( - " Returns the or of two bools, but it evaluates both arguments.\n" - "\n" - " It's the function equivalent of the `||` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " or(True, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " or(False, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " False |> or(True)\n" - " // -> True\n" - " ```\n" -). --spec 'or'(boolean(), boolean()) -> boolean(). -'or'(A, B) -> - A orelse B. - --file("src/gleam/bool.gleam", 77). -?DOC( - " Returns the opposite bool value.\n" - "\n" - " This is the same as the `!` or `not` operators in some other languages.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " negate(False)\n" - " // -> True\n" - " ```\n" -). --spec negate(boolean()) -> boolean(). -negate(Bool) -> - not Bool. - --file("src/gleam/bool.gleam", 105). -?DOC( - " Returns the nor of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " nor(False, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nor(False, True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " nor(True, False)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " nor(True, True)\n" - " // -> False\n" - " ```\n" -). --spec nor(boolean(), boolean()) -> boolean(). -nor(A, B) -> - not (A orelse B). - --file("src/gleam/bool.gleam", 133). -?DOC( - " Returns the nand of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " nand(False, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nand(False, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nand(True, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nand(True, True)\n" - " // -> False\n" - " ```\n" -). --spec nand(boolean(), boolean()) -> boolean(). -nand(A, B) -> - not (A andalso B). - --file("src/gleam/bool.gleam", 161). -?DOC( - " Returns the exclusive or of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " exclusive_or(False, False)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_or(False, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_or(True, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_or(True, True)\n" - " // -> False\n" - " ```\n" -). --spec exclusive_or(boolean(), boolean()) -> boolean(). -exclusive_or(A, B) -> - A /= B. - --file("src/gleam/bool.gleam", 189). -?DOC( - " Returns the exclusive nor of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " exclusive_nor(False, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_nor(False, True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_nor(True, False)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_nor(True, True)\n" - " // -> True\n" - " ```\n" -). --spec exclusive_nor(boolean(), boolean()) -> boolean(). -exclusive_nor(A, B) -> - A =:= B. - --file("src/gleam/bool.gleam", 207). -?DOC( - " Returns a string representation of the given bool.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_string(True)\n" - " // -> \"True\"\n" - " ```\n" - "\n" - " ```gleam\n" - " to_string(False)\n" - " // -> \"False\"\n" - " ```\n" -). --spec to_string(boolean()) -> binary(). -to_string(Bool) -> - case Bool of - false -> - <<"False"/utf8>>; - - true -> - <<"True"/utf8>> - end. - --file("src/gleam/bool.gleam", 266). -?DOC( - " Run a callback function if the given bool is `False`, otherwise return a\n" - " default value.\n" - "\n" - " With a `use` expression this function can simulate the early-return pattern\n" - " found in some other programming languages.\n" - "\n" - " In a procedural language:\n" - "\n" - " ```js\n" - " if (predicate) return value;\n" - " // ...\n" - " ```\n" - "\n" - " In Gleam with a `use` expression:\n" - "\n" - " ```gleam\n" - " use <- guard(when: predicate, return: value)\n" - " // ...\n" - " ```\n" - "\n" - " Like everything in Gleam `use` is an expression, so it short circuits the\n" - " current block, not the entire function. As a result you can assign the value\n" - " to a variable:\n" - "\n" - " ```gleam\n" - " let x = {\n" - " use <- guard(when: predicate, return: value)\n" - " // ...\n" - " }\n" - " ```\n" - "\n" - " Note that unlike in procedural languages the `return` value is evaluated\n" - " even when the predicate is `False`, so it is advisable not to perform\n" - " expensive computation nor side-effects there.\n" - "\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let name = \"\"\n" - " use <- guard(when: name == \"\", return: \"Welcome!\")\n" - " \"Hello, \" <> name\n" - " // -> \"Welcome!\"\n" - " ```\n" - "\n" - " ```gleam\n" - " let name = \"Kamaka\"\n" - " use <- guard(when: name == \"\", return: \"Welcome!\")\n" - " \"Hello, \" <> name\n" - " // -> \"Hello, Kamaka\"\n" - " ```\n" -). --spec guard(boolean(), BSY, fun(() -> BSY)) -> BSY. -guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence; - - false -> - Alternative() - end. - --file("src/gleam/bool.gleam", 307). -?DOC( - " Runs a callback function if the given bool is `True`, otherwise runs an\n" - " alternative callback function.\n" - "\n" - " Useful when further computation should be delayed regardless of the given\n" - " bool's value.\n" - "\n" - " See [`guard`](#guard) for more info.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let name = \"Kamaka\"\n" - " let inquiry = fn() { \"How may we address you?\" }\n" - " use <- lazy_guard(when: name == \"\", return: inquiry)\n" - " \"Hello, \" <> name\n" - " // -> \"Hello, Kamaka\"\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " let name = \"\"\n" - " let greeting = fn() { \"Hello, \" <> name }\n" - " use <- lazy_guard(when: name == \"\", otherwise: greeting)\n" - " let number = int.random(99)\n" - " let name = \"User \" <> int.to_string(number)\n" - " \"Welcome, \" <> name\n" - " // -> \"Welcome, User 54\"\n" - " ```\n" -). --spec lazy_guard(boolean(), fun(() -> BSZ), fun(() -> BSZ)) -> BSZ. -lazy_guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence(); - - false -> - Alternative() - end. diff --git a/build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl b/build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl deleted file mode 100644 index a96eaa2..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl +++ /dev/null @@ -1,211 +0,0 @@ --module(gleam@bytes_tree). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bytes_tree.gleam"). --export([append_tree/2, prepend_tree/2, concat/1, new/0, from_string/1, prepend_string/2, append_string/2, from_string_tree/1, from_bit_array/1, prepend/2, append/2, concat_bit_arrays/1, to_bit_array/1, byte_size/1]). --export_type([bytes_tree/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " `BytesTree` is a type used for efficiently building binary content to be\n" - " written to a file or a socket. Internally it is represented as tree so to\n" - " append or prepend to a bytes tree is a constant time operation that\n" - " allocates a new node in the tree without copying any of the content. When\n" - " writing to an output stream the tree is traversed and the content is sent\n" - " directly rather than copying it into a single buffer beforehand.\n" - "\n" - " If we append one bit array to another the bit arrays must be copied to a\n" - " new location in memory so that they can sit together. This behaviour\n" - " enables efficient reading of the data but copying can be expensive,\n" - " especially if we want to join many bit arrays together.\n" - "\n" - " BytesTree is different in that it can be joined together in constant\n" - " time using minimal memory, and then can be efficiently converted to a\n" - " bit array using the `to_bit_array` function.\n" - "\n" - " Byte trees are always byte aligned, so that a number of bits that is not\n" - " divisible by 8 will be padded with 0s.\n" - "\n" - " On Erlang this type is compatible with Erlang's iolists.\n" -). - --opaque bytes_tree() :: {bytes, bitstring()} | - {text, gleam@string_tree:string_tree()} | - {many, list(bytes_tree())}. - --file("src/gleam/bytes_tree.gleam", 68). -?DOC( - " Appends a bytes tree onto the end of another.\n" - "\n" - " Runs in constant time.\n" -). --spec append_tree(bytes_tree(), bytes_tree()) -> bytes_tree(). -append_tree(First, Second) -> - gleam_stdlib:iodata_append(First, Second). - --file("src/gleam/bytes_tree.gleam", 59). -?DOC( - " Prepends a bytes tree onto the start of another.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend_tree(bytes_tree(), bytes_tree()) -> bytes_tree(). -prepend_tree(Second, First) -> - gleam_stdlib:iodata_append(First, Second). - --file("src/gleam/bytes_tree.gleam", 98). -?DOC( - " Joins a list of bytes trees into a single one.\n" - "\n" - " Runs in constant time.\n" -). --spec concat(list(bytes_tree())) -> bytes_tree(). -concat(Trees) -> - gleam_stdlib:identity(Trees). - --file("src/gleam/bytes_tree.gleam", 35). -?DOC( - " Create an empty `BytesTree`. Useful as the start of a pipe chaining many\n" - " trees together.\n" -). --spec new() -> bytes_tree(). -new() -> - gleam_stdlib:identity([]). - --file("src/gleam/bytes_tree.gleam", 118). -?DOC( - " Creates a new bytes tree from a string.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time otherwise.\n" -). --spec from_string(binary()) -> bytes_tree(). -from_string(String) -> - gleam_stdlib:wrap_list(String). - --file("src/gleam/bytes_tree.gleam", 80). -?DOC( - " Prepends a string onto the start of a bytes tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time with the length of the string otherwise.\n" -). --spec prepend_string(bytes_tree(), binary()) -> bytes_tree(). -prepend_string(Second, First) -> - gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). - --file("src/gleam/bytes_tree.gleam", 89). -?DOC( - " Appends a string onto the end of a bytes tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time with the length of the string otherwise.\n" -). --spec append_string(bytes_tree(), binary()) -> bytes_tree(). -append_string(First, Second) -> - gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). - --file("src/gleam/bytes_tree.gleam", 128). -?DOC( - " Creates a new bytes tree from a string tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time otherwise.\n" -). --spec from_string_tree(gleam@string_tree:string_tree()) -> bytes_tree(). -from_string_tree(Tree) -> - gleam_stdlib:wrap_list(Tree). - --file("src/gleam/bytes_tree.gleam", 136). -?DOC( - " Creates a new bytes tree from a bit array.\n" - "\n" - " Runs in constant time.\n" -). --spec from_bit_array(bitstring()) -> bytes_tree(). -from_bit_array(Bits) -> - _pipe = Bits, - _pipe@1 = gleam_stdlib:bit_array_pad_to_bytes(_pipe), - gleam_stdlib:wrap_list(_pipe@1). - --file("src/gleam/bytes_tree.gleam", 43). -?DOC( - " Prepends a bit array to the start of a bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend(bytes_tree(), bitstring()) -> bytes_tree(). -prepend(Second, First) -> - gleam_stdlib:iodata_append(from_bit_array(First), Second). - --file("src/gleam/bytes_tree.gleam", 51). -?DOC( - " Appends a bit array to the end of a bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec append(bytes_tree(), bitstring()) -> bytes_tree(). -append(First, Second) -> - gleam_stdlib:iodata_append(First, from_bit_array(Second)). - --file("src/gleam/bytes_tree.gleam", 106). -?DOC( - " Joins a list of bit arrays into a single bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec concat_bit_arrays(list(bitstring())) -> bytes_tree(). -concat_bit_arrays(Bits) -> - _pipe = Bits, - _pipe@1 = gleam@list:map(_pipe, fun from_bit_array/1), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/bytes_tree.gleam", 162). --spec to_list(list(list(bytes_tree())), list(bitstring())) -> list(bitstring()). -to_list(Stack, Acc) -> - case Stack of - [] -> - Acc; - - [[] | Remaining_stack] -> - to_list(Remaining_stack, Acc); - - [[{bytes, Bits} | Rest] | Remaining_stack@1] -> - to_list([Rest | Remaining_stack@1], [Bits | Acc]); - - [[{text, Tree} | Rest@1] | Remaining_stack@2] -> - Bits@1 = gleam_stdlib:identity(unicode:characters_to_binary(Tree)), - to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]); - - [[{many, Trees} | Rest@2] | Remaining_stack@3] -> - to_list([Trees, Rest@2 | Remaining_stack@3], Acc) - end. - --file("src/gleam/bytes_tree.gleam", 155). -?DOC( - " Turns a bytes tree into a bit array.\n" - "\n" - " Runs in linear time.\n" - "\n" - " When running on Erlang this function is implemented natively by the\n" - " virtual machine and is highly optimised.\n" -). --spec to_bit_array(bytes_tree()) -> bitstring(). -to_bit_array(Tree) -> - erlang:list_to_bitstring(Tree). - --file("src/gleam/bytes_tree.gleam", 186). -?DOC( - " Returns the size of the bytes tree's content in bytes.\n" - "\n" - " Runs in linear time.\n" -). --spec byte_size(bytes_tree()) -> integer(). -byte_size(Tree) -> - erlang:iolist_size(Tree). diff --git a/build/dev/javascript/gleam_stdlib/gleam@dict.erl b/build/dev/javascript/gleam_stdlib/gleam@dict.erl deleted file mode 100644 index d496afb..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@dict.erl +++ /dev/null @@ -1,561 +0,0 @@ --module(gleam@dict). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dict.gleam"). --export([size/1, is_empty/1, to_list/1, new/0, get/2, has_key/2, insert/3, from_list/1, keys/1, values/1, take/2, merge/2, delete/2, drop/2, upsert/3, fold/3, map_values/2, filter/2, each/2, combine/3]). --export_type([dict/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type dict(KG, KH) :: any() | {gleam_phantom, KG, KH}. - --file("src/gleam/dict.gleam", 36). -?DOC( - " Determines the number of key-value pairs in the dict.\n" - " This function runs in constant time and does not need to iterate the dict.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> size\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"key\", \"value\") |> size\n" - " // -> 1\n" - " ```\n" -). --spec size(dict(any(), any())) -> integer(). -size(Dict) -> - maps:size(Dict). - --file("src/gleam/dict.gleam", 52). -?DOC( - " Determines whether or not the dict is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> is_empty\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"b\", 1) |> is_empty\n" - " // -> False\n" - " ```\n" -). --spec is_empty(dict(any(), any())) -> boolean(). -is_empty(Dict) -> - maps:size(Dict) =:= 0. - --file("src/gleam/dict.gleam", 80). -?DOC( - " Converts the dict to a list of 2-element tuples `#(key, value)`, one for\n" - " each key-value pair in the dict.\n" - "\n" - " The tuples in the list have no specific order.\n" - "\n" - " ## Examples\n" - "\n" - " Calling `to_list` on an empty `dict` returns an empty list.\n" - "\n" - " ```gleam\n" - " new() |> to_list\n" - " // -> []\n" - " ```\n" - "\n" - " The ordering of elements in the resulting list is an implementation detail\n" - " that should not be relied upon.\n" - "\n" - " ```gleam\n" - " new() |> insert(\"b\", 1) |> insert(\"a\", 0) |> insert(\"c\", 2) |> to_list\n" - " // -> [#(\"a\", 0), #(\"b\", 1), #(\"c\", 2)]\n" - " ```\n" -). --spec to_list(dict(KQ, KR)) -> list({KQ, KR}). -to_list(Dict) -> - maps:to_list(Dict). - --file("src/gleam/dict.gleam", 129). -?DOC(" Creates a fresh dict that contains no values.\n"). --spec new() -> dict(any(), any()). -new() -> - maps:new(). - --file("src/gleam/dict.gleam", 150). -?DOC( - " Fetches a value from a dict for a given key.\n" - "\n" - " The dict may not have a value for the key, so the value is wrapped in a\n" - " `Result`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> get(\"a\")\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> get(\"b\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec get(dict(LT, LU), LT) -> {ok, LU} | {error, nil}. -get(From, Get) -> - gleam_stdlib:map_get(From, Get). - --file("src/gleam/dict.gleam", 116). -?DOC( - " Determines whether or not a value present in the dict for a given key.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> has_key(\"a\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> has_key(\"b\")\n" - " // -> False\n" - " ```\n" -). --spec has_key(dict(LH, any()), LH) -> boolean(). -has_key(Dict, Key) -> - maps:is_key(Key, Dict). - --file("src/gleam/dict.gleam", 169). -?DOC( - " Inserts a value into the dict with the given key.\n" - "\n" - " If the dict already has a value for the given key then the value is\n" - " replaced with the new value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0)\n" - " // -> from_list([#(\"a\", 0)])\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> insert(\"a\", 5)\n" - " // -> from_list([#(\"a\", 5)])\n" - " ```\n" -). --spec insert(dict(LZ, MA), LZ, MA) -> dict(LZ, MA). -insert(Dict, Key, Value) -> - maps:put(Key, Value, Dict). - --file("src/gleam/dict.gleam", 92). --spec from_list_loop(list({LA, LB}), dict(LA, LB)) -> dict(LA, LB). -from_list_loop(List, Initial) -> - case List of - [] -> - Initial; - - [{Key, Value} | Rest] -> - from_list_loop(Rest, insert(Initial, Key, Value)) - end. - --file("src/gleam/dict.gleam", 88). -?DOC( - " Converts a list of 2-element tuples `#(key, value)` to a dict.\n" - "\n" - " If two tuples have the same key the last one in the list will be the one\n" - " that is present in the dict.\n" -). --spec from_list(list({KV, KW})) -> dict(KV, KW). -from_list(List) -> - maps:from_list(List). - --file("src/gleam/dict.gleam", 223). --spec reverse_and_concat(list(NJ), list(NJ)) -> list(NJ). -reverse_and_concat(Remaining, Accumulator) -> - case Remaining of - [] -> - Accumulator; - - [First | Rest] -> - reverse_and_concat(Rest, [First | Accumulator]) - end. - --file("src/gleam/dict.gleam", 216). --spec do_keys_loop(list({NE, any()}), list(NE)) -> list(NE). -do_keys_loop(List, Acc) -> - case List of - [] -> - reverse_and_concat(Acc, []); - - [{Key, _} | Rest] -> - do_keys_loop(Rest, [Key | Acc]) - end. - --file("src/gleam/dict.gleam", 212). -?DOC( - " Gets a list of all keys in a given dict.\n" - "\n" - " Dicts are not ordered so the keys are not returned in any specific order. Do\n" - " not write code that relies on the order keys are returned by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> keys\n" - " // -> [\"a\", \"b\"]\n" - " ```\n" -). --spec keys(dict(MZ, any())) -> list(MZ). -keys(Dict) -> - maps:keys(Dict). - --file("src/gleam/dict.gleam", 249). --spec do_values_loop(list({any(), NT}), list(NT)) -> list(NT). -do_values_loop(List, Acc) -> - case List of - [] -> - reverse_and_concat(Acc, []); - - [{_, Value} | Rest] -> - do_values_loop(Rest, [Value | Acc]) - end. - --file("src/gleam/dict.gleam", 244). -?DOC( - " Gets a list of all values in a given dict.\n" - "\n" - " Dicts are not ordered so the values are not returned in any specific order. Do\n" - " not write code that relies on the order values are returned by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> values\n" - " // -> [0, 1]\n" - " ```\n" -). --spec values(dict(any(), NO)) -> list(NO). -values(Dict) -> - maps:values(Dict). - --file("src/gleam/dict.gleam", 318). --spec do_take_loop(dict(OX, OY), list(OX), dict(OX, OY)) -> dict(OX, OY). -do_take_loop(Dict, Desired_keys, Acc) -> - Insert = fun(Taken, Key) -> case gleam_stdlib:map_get(Dict, Key) of - {ok, Value} -> - insert(Taken, Key, Value); - - {error, _} -> - Taken - end end, - case Desired_keys of - [] -> - Acc; - - [First | Rest] -> - do_take_loop(Dict, Rest, Insert(Acc, First)) - end. - --file("src/gleam/dict.gleam", 309). -?DOC( - " Creates a new dict from a given dict, only including any entries for which the\n" - " keys are in a given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> take([\"b\"])\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> take([\"a\", \"b\", \"c\"])\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec take(dict(OJ, OK), list(OJ)) -> dict(OJ, OK). -take(Dict, Desired_keys) -> - maps:with(Desired_keys, Dict). - --file("src/gleam/dict.gleam", 363). --spec insert_pair(dict(PV, PW), {PV, PW}) -> dict(PV, PW). -insert_pair(Dict, Pair) -> - insert(Dict, erlang:element(1, Pair), erlang:element(2, Pair)). - --file("src/gleam/dict.gleam", 356). --spec fold_inserts(list({PO, PP}), dict(PO, PP)) -> dict(PO, PP). -fold_inserts(New_entries, Dict) -> - case New_entries of - [] -> - Dict; - - [First | Rest] -> - fold_inserts(Rest, insert_pair(Dict, First)) - end. - --file("src/gleam/dict.gleam", 350). -?DOC( - " Creates a new dict from a pair of given dicts by combining their entries.\n" - "\n" - " If there are entries with the same keys in both dicts the entry from the\n" - " second dict takes precedence.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " let b = from_list([#(\"b\", 2), #(\"c\", 3)])\n" - " merge(a, b)\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 2), #(\"c\", 3)])\n" - " ```\n" -). --spec merge(dict(PG, PH), dict(PG, PH)) -> dict(PG, PH). -merge(Dict, New_entries) -> - maps:merge(Dict, New_entries). - --file("src/gleam/dict.gleam", 382). -?DOC( - " Creates a new dict from a given dict with all the same entries except for the\n" - " one with a given key, if it exists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"a\")\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"c\")\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec delete(dict(QB, QC), QB) -> dict(QB, QC). -delete(Dict, Key) -> - maps:remove(Key, Dict). - --file("src/gleam/dict.gleam", 410). -?DOC( - " Creates a new dict from a given dict with all the same entries except any with\n" - " keys found in a given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\"])\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"c\"])\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\", \"b\", \"c\"])\n" - " // -> from_list([])\n" - " ```\n" -). --spec drop(dict(QN, QO), list(QN)) -> dict(QN, QO). -drop(Dict, Disallowed_keys) -> - case Disallowed_keys of - [] -> - Dict; - - [First | Rest] -> - drop(delete(Dict, First), Rest) - end. - --file("src/gleam/dict.gleam", 440). -?DOC( - " Creates a new dict with one entry inserted or updated using a given function.\n" - "\n" - " If there was not an entry in the dict for the given key then the function\n" - " gets `None` as its argument, otherwise it gets `Some(value)`.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " let dict = from_list([#(\"a\", 0)])\n" - " let increment = fn(x) {\n" - " case x {\n" - " Some(i) -> i + 1\n" - " None -> 0\n" - " }\n" - " }\n" - "\n" - " upsert(dict, \"a\", increment)\n" - " // -> from_list([#(\"a\", 1)])\n" - "\n" - " upsert(dict, \"b\", increment)\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 0)])\n" - " ```\n" -). --spec upsert(dict(QU, QV), QU, fun((gleam@option:option(QV)) -> QV)) -> dict(QU, QV). -upsert(Dict, Key, Fun) -> - case gleam_stdlib:map_get(Dict, Key) of - {ok, Value} -> - insert(Dict, Key, Fun({some, Value})); - - {error, _} -> - insert(Dict, Key, Fun(none)) - end. - --file("src/gleam/dict.gleam", 484). --spec fold_loop(list({RG, RH}), RJ, fun((RJ, RG, RH) -> RJ)) -> RJ. -fold_loop(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [{K, V} | Rest] -> - fold_loop(Rest, Fun(Initial, K, V), Fun) - end. - --file("src/gleam/dict.gleam", 476). -?DOC( - " Combines all entries into a single value by calling a given function on each\n" - " one.\n" - "\n" - " Dicts are not ordered so the values are not returned in any specific order. Do\n" - " not write code that relies on the order entries are used by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n" - " fold(dict, 0, fn(accumulator, key, value) { accumulator + value })\n" - " // -> 13\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/string\n" - "\n" - " let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n" - " fold(dict, \"\", fn(accumulator, key, value) {\n" - " string.append(accumulator, key)\n" - " })\n" - " // -> \"abc\"\n" - " ```\n" -). --spec fold(dict(RB, RC), RF, fun((RF, RB, RC) -> RF)) -> RF. -fold(Dict, Initial, Fun) -> - fold_loop(maps:to_list(Dict), Initial, Fun). - --file("src/gleam/dict.gleam", 188). -?DOC( - " Updates all values in a given dict by calling a given function on each key\n" - " and value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(3, 3), #(2, 4)])\n" - " |> map_values(fn(key, value) { key * value })\n" - " // -> from_list([#(3, 9), #(2, 8)])\n" - " ```\n" -). --spec map_values(dict(ML, MM), fun((ML, MM) -> MP)) -> dict(ML, MP). -map_values(Dict, Fun) -> - maps:map(Fun, Dict). - --file("src/gleam/dict.gleam", 273). -?DOC( - " Creates a new dict from a given dict, minus any entries that a given function\n" - " returns `False` for.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> filter(fn(key, value) { value != 0 })\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> filter(fn(key, value) { True })\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec filter(dict(NX, NY), fun((NX, NY) -> boolean())) -> dict(NX, NY). -filter(Dict, Predicate) -> - maps:filter(Predicate, Dict). - --file("src/gleam/dict.gleam", 517). -?DOC( - " Calls a function for each key and value in a dict, discarding the return\n" - " value.\n" - "\n" - " Useful for producing a side effect for every item of a dict.\n" - "\n" - " ```gleam\n" - " import gleam/io\n" - "\n" - " let dict = from_list([#(\"a\", \"apple\"), #(\"b\", \"banana\"), #(\"c\", \"cherry\")])\n" - "\n" - " each(dict, fn(k, v) {\n" - " io.println(key <> \" => \" <> value)\n" - " })\n" - " // -> Nil\n" - " // a => apple\n" - " // b => banana\n" - " // c => cherry\n" - " ```\n" - "\n" - " The order of elements in the iteration is an implementation detail that\n" - " should not be relied upon.\n" -). --spec each(dict(RK, RL), fun((RK, RL) -> any())) -> nil. -each(Dict, Fun) -> - fold( - Dict, - nil, - fun(Nil, K, V) -> - Fun(K, V), - Nil - end - ). - --file("src/gleam/dict.gleam", 538). -?DOC( - " Creates a new dict from a pair of given dicts by combining their entries.\n" - "\n" - " If there are entries with the same keys in both dicts the given function is\n" - " used to determine the new value to use in the resulting dict.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " let b = from_list([#(\"a\", 2), #(\"c\", 3)])\n" - " combine(a, b, fn(one, other) { one + other })\n" - " // -> from_list([#(\"a\", 2), #(\"b\", 1), #(\"c\", 3)])\n" - " ```\n" -). --spec combine(dict(RP, RQ), dict(RP, RQ), fun((RQ, RQ) -> RQ)) -> dict(RP, RQ). -combine(Dict, Other, Fun) -> - fold( - Dict, - Other, - fun(Acc, Key, Value) -> case gleam_stdlib:map_get(Acc, Key) of - {ok, Other_value} -> - insert(Acc, Key, Fun(Value, Other_value)); - - {error, _} -> - insert(Acc, Key, Value) - end end - ). diff --git a/build/dev/javascript/gleam_stdlib/gleam@dynamic.erl b/build/dev/javascript/gleam_stdlib/gleam@dynamic.erl deleted file mode 100644 index f057ca2..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@dynamic.erl +++ /dev/null @@ -1,106 +0,0 @@ --module(gleam@dynamic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dynamic.gleam"). --export([classify/1, bool/1, string/1, float/1, int/1, bit_array/1, list/1, array/1, properties/1, nil/0]). --export_type([dynamic_/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type dynamic_() :: any(). - --file("src/gleam/dynamic.gleam", 30). -?DOC( - " Return a string indicating the type of the dynamic value.\n" - "\n" - " This function may be useful for constructing error messages or logs. If you\n" - " want to turn dynamic data into well typed data then you want the\n" - " `gleam/dynamic/decode` module.\n" - "\n" - " ```gleam\n" - " classify(string(\"Hello\"))\n" - " // -> \"String\"\n" - " ```\n" -). --spec classify(dynamic_()) -> binary(). -classify(Data) -> - gleam_stdlib:classify_dynamic(Data). - --file("src/gleam/dynamic.gleam", 36). -?DOC(" Create a dynamic value from a bool.\n"). --spec bool(boolean()) -> dynamic_(). -bool(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 44). -?DOC( - " Create a dynamic value from a string.\n" - "\n" - " On Erlang this will be a binary string rather than a character list.\n" -). --spec string(binary()) -> dynamic_(). -string(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 50). -?DOC(" Create a dynamic value from a float.\n"). --spec float(float()) -> dynamic_(). -float(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 56). -?DOC(" Create a dynamic value from an int.\n"). --spec int(integer()) -> dynamic_(). -int(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 62). -?DOC(" Create a dynamic value from a bit array.\n"). --spec bit_array(bitstring()) -> dynamic_(). -bit_array(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 68). -?DOC(" Create a dynamic value from a list.\n"). --spec list(list(dynamic_())) -> dynamic_(). -list(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 77). -?DOC( - " Create a dynamic value from a list, converting it to a sequential runtime\n" - " format rather than the regular list format.\n" - "\n" - " On Erlang this will be a tuple, on JavaScript this will be an array.\n" -). --spec array(list(dynamic_())) -> dynamic_(). -array(A) -> - erlang:list_to_tuple(A). - --file("src/gleam/dynamic.gleam", 85). -?DOC( - " Create a dynamic value made an unordered series of keys and values, where\n" - " the keys are unique.\n" - "\n" - " On Erlang this will be a map, on JavaScript this will be a Gleam dict\n" - " object.\n" -). --spec properties(list({dynamic_(), dynamic_()})) -> dynamic_(). -properties(Entries) -> - gleam_stdlib:identity(maps:from_list(Entries)). - --file("src/gleam/dynamic.gleam", 94). -?DOC( - " A dynamic value representing nothing.\n" - "\n" - " On Erlang this will be the atom `nil`, on JavaScript this will be\n" - " `undefined`.\n" -). --spec nil() -> dynamic_(). -nil() -> - gleam_stdlib:identity(nil). diff --git a/build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl b/build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl deleted file mode 100644 index bf4b951..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl +++ /dev/null @@ -1,1088 +0,0 @@ --module(gleam@dynamic@decode). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dynamic/decode.gleam"). --export([run/2, success/1, decode_dynamic/1, map/2, map_errors/2, then/2, one_of/2, recursive/1, optional/1, decode_error/2, decode_bool/1, decode_int/1, decode_float/1, decode_bit_array/1, collapse_errors/2, failure/2, new_primitive_decoder/2, decode_string/1, dict/2, list/1, subfield/3, at/2, field/3, optional_field/4, optionally_at/3]). --export_type([decode_error/0, decoder/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " The `Dynamic` type is used to represent dynamically typed data. That is, data\n" - " that we don't know the precise type of yet, so we need to introspect the data to\n" - " see if it is of the desired type before we can use it. Typically data like this\n" - " would come from user input or from untyped languages such as Erlang or JavaScript.\n" - "\n" - " This module provides the `Decoder` type and associated functions, which provides\n" - " a type-safe and composable way to convert dynamic data into some desired type,\n" - " or into errors if the data doesn't have the desired structure.\n" - "\n" - " The `Decoder` type is generic and has 1 type parameter, which is the type that\n" - " it attempts to decode. A `Decoder(String)` can be used to decode strings, and a\n" - " `Decoder(Option(Int))` can be used to decode `Option(Int)`s\n" - "\n" - " Decoders work using _runtime reflection_ and the data structures of the target\n" - " platform. Differences between Erlang and JavaScript data structures may impact\n" - " your decoders, so it is important to test your decoders on all supported\n" - " platforms.\n" - "\n" - " The decoding technique used by this module was inspired by Juraj Petráš'\n" - " [Toy](https://github.com/Hackder/toy), Go's `encoding/json`, and Elm's\n" - " `Json.Decode`. Thank you to them!\n" - "\n" - " # Examples\n" - "\n" - " Dynamic data may come from various sources and so many different syntaxes could\n" - " be used to describe or construct them. In these examples a pseudocode\n" - " syntax is used to describe the data.\n" - "\n" - " ## Simple types\n" - "\n" - " This module defines decoders for simple data types such as [`string`](#string),\n" - " [`int`](#int), [`float`](#float), [`bit_array`](#bit_array), and [`bool`](#bool).\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // \"Hello, Joe!\"\n" - "\n" - " let result = decode.run(data, decode.string)\n" - " assert result == Ok(\"Hello, Joe!\")\n" - " ```\n" - "\n" - " ## Lists\n" - "\n" - " The [`list`](#list) decoder decodes `List`s. To use it you must construct it by\n" - " passing in another decoder into the `list` function, which is the decoder that\n" - " is to be used for the elements of the list, type checking both the list and its\n" - " elements.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // [1, 2, 3, 4]\n" - "\n" - " let result = decode.run(data, decode.list(decode.int))\n" - " assert result == Ok([1, 2, 3, 4])\n" - " ```\n" - "\n" - " On Erlang this decoder can decode from lists, and on JavaScript it can\n" - " decode from lists as well as JavaScript arrays.\n" - "\n" - " ## Options\n" - "\n" - " The [`optional`](#optional) decoder is used to decode values that may or may not\n" - " be present. In other environment these might be called \"nullable\" values.\n" - "\n" - " Like the `list` decoder, the `optional` decoder takes another decoder,\n" - " which is used to decode the value if it is present.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // 12.45\n" - "\n" - " let result = decode.run(data, decode.optional(decode.float))\n" - " assert result == Ok(option.Some(12.45))\n" - " ```\n" - " ```gleam\n" - " // Data:\n" - " // null\n" - "\n" - " let result = decode.run(data, decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" - "\n" - " This decoder knows how to handle multiple different runtime representations of\n" - " absent values, including `Nil`, `None`, `null`, and `undefined`.\n" - "\n" - " ## Dicts\n" - "\n" - " The [`dict`](#dict) decoder decodes `Dicts` and contains two other decoders, one\n" - " for the keys, one for the values.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // { \"Lucy\" -> 10, \"Nubi\" -> 20 }\n" - "\n" - " let result = decode.run(data, decode.dict(decode.string, decode.int))\n" - " assert result == Ok(dict.from_list([\n" - " #(\"Lucy\", 10),\n" - " #(\"Nubi\", 20),\n" - " ]))\n" - " ```\n" - "\n" - " ## Indexing objects\n" - "\n" - " The [`at`](#at) decoder can be used to decode a value that is nested within\n" - " key-value containers such as Gleam dicts, Erlang maps, or JavaScript objects.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // { \"one\" -> { \"two\" -> 123 } }\n" - "\n" - " let result = decode.run(data, decode.at([\"one\", \"two\"], decode.int))\n" - " assert result == Ok(123)\n" - " ```\n" - "\n" - " ## Indexing arrays\n" - "\n" - " If you use ints as keys then the [`at`](#at) decoder can be used to index into\n" - " array-like containers such as Gleam or Erlang tuples, or JavaScript arrays.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // [\"one\", \"two\", \"three\"]\n" - "\n" - " let result = decode.run(data, decode.at([1], decode.string))\n" - " assert result == Ok(\"two\")\n" - " ```\n" - "\n" - " ## Records\n" - "\n" - " Decoding records from dynamic data is more complex and requires combining a\n" - " decoder for each field and a special constructor that builds your records with\n" - " the decoded field values.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // {\n" - " // \"score\" -> 180,\n" - " // \"name\" -> \"Mel Smith\",\n" - " // \"is-admin\" -> false,\n" - " // \"enrolled\" -> true,\n" - " // \"colour\" -> \"Red\",\n" - " // }\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use score <- decode.field(\"score\", decode.int)\n" - " use colour <- decode.field(\"colour\", decode.string)\n" - " use enrolled <- decode.field(\"enrolled\", decode.bool)\n" - " decode.success(Player(name:, score:, colour:, enrolled:))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(Player(\"Mel Smith\", 180, \"Red\", True))\n" - " ```\n" - "\n" - " ## Enum variants\n" - "\n" - " Imagine you have a custom type where all the variants do not contain any values.\n" - "\n" - " ```gleam\n" - " pub type PocketMonsterType {\n" - " Fire\n" - " Water\n" - " Grass\n" - " Electric\n" - " }\n" - " ```\n" - "\n" - " You might choose to encode these variants as strings, `\"fire\"` for `Fire`,\n" - " `\"water\"` for `Water`, and so on. To decode them you'll need to decode the dynamic\n" - " data as a string, but then you'll need to decode it further still as not all\n" - " strings are valid values for the enum. This can be done with the `then`\n" - " function, which enables running a second decoder after the first one\n" - " succeeds.\n" - "\n" - " ```gleam\n" - " let decoder = {\n" - " use decoded_string <- decode.then(decode.string)\n" - " case decoded_string {\n" - " // Return succeeding decoders for valid strings\n" - " \"fire\" -> decode.success(Fire)\n" - " \"water\" -> decode.success(Water)\n" - " \"grass\" -> decode.success(Grass)\n" - " \"electric\" -> decode.success(Electric)\n" - " // Return a failing decoder for any other strings\n" - " _ -> decode.failure(Fire, \"PocketMonsterType\")\n" - " }\n" - " }\n" - "\n" - " let result = decode.run(dynamic.string(\"water\"), decoder)\n" - " assert result == Ok(Water)\n" - "\n" - " let result = decode.run(dynamic.string(\"wobble\"), decoder)\n" - " assert result == Error([DecodeError(\"PocketMonsterType\", \"String\", [])])\n" - " ```\n" - "\n" - " ## Record variants\n" - "\n" - " Decoding type variants that contain other values is done by combining the\n" - " techniques from the \"enum variants\" and \"records\" examples. Imagine you have\n" - " this custom type that you want to decode:\n" - "\n" - " ```gleam\n" - " pub type PocketMonsterPerson {\n" - " Trainer(name: String, badge_count: Int)\n" - " GymLeader(name: String, speciality: PocketMonsterType)\n" - " }\n" - " ```\n" - " And you would like to be able to decode these from dynamic data like this:\n" - " ```erlang\n" - " {\n" - " \"type\" -> \"trainer\",\n" - " \"name\" -> \"Ash\",\n" - " \"badge-count\" -> 1,\n" - " }\n" - " ```\n" - " ```erlang\n" - " {\n" - " \"type\" -> \"gym-leader\",\n" - " \"name\" -> \"Misty\",\n" - " \"speciality\" -> \"water\",\n" - " }\n" - " ```\n" - "\n" - " Notice how both documents have a `\"type\"` field, which is used to indicate which\n" - " variant the data is for.\n" - "\n" - " First, define decoders for each of the variants:\n" - "\n" - " ```gleam\n" - " let trainer_decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use badge_count <- decode.field(\"badge-count\", decode.int)\n" - " decode.success(Trainer(name, badge_count))\n" - " }\n" - "\n" - " let gym_leader_decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use speciality <- decode.field(\"speciality\", pocket_monster_type_decoder)\n" - " decode.success(GymLeader(name, speciality))\n" - " }\n" - " ```\n" - "\n" - " A third decoder can be used to extract and decode the `\"type\"` field, and the\n" - " expression can evaluate to whichever decoder is suitable for the document.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // {\n" - " // \"type\" -> \"gym-leader\",\n" - " // \"name\" -> \"Misty\",\n" - " // \"speciality\" -> \"water\",\n" - " // }\n" - "\n" - " let decoder = {\n" - " use tag <- decode.field(\"type\", decode.string)\n" - " case tag {\n" - " \"gym-leader\" -> gym_leader_decoder\n" - " _ -> trainer_decoder\n" - " }\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(GymLeader(\"Misty\", Water))\n" - " ```\n" -). - --type decode_error() :: {decode_error, binary(), binary(), list(binary())}. - --opaque decoder(BUW) :: {decoder, - fun((gleam@dynamic:dynamic_()) -> {BUW, list(decode_error())})}. - --file("src/gleam/dynamic/decode.gleam", 356). -?DOC( - " Run a decoder on a `Dynamic` value, decoding the value if it is of the\n" - " desired type, or returning errors.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = {\n" - " use name <- decode.field(\"email\", decode.string)\n" - " use email <- decode.field(\"password\", decode.string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " decode.run(data, decoder)\n" - " ```\n" -). --spec run(gleam@dynamic:dynamic_(), decoder(BVE)) -> {ok, BVE} | - {error, list(decode_error())}. -run(Data, Decoder) -> - {Maybe_invalid_data, Errors} = (erlang:element(2, Decoder))(Data), - case Errors of - [] -> - {ok, Maybe_invalid_data}; - - [_ | _] -> - {error, Errors} - end. - --file("src/gleam/dynamic/decode.gleam", 479). -?DOC( - " Finalise a decoder having successfully extracted a value.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.field(\"email\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" -). --spec success(BWF) -> decoder(BWF). -success(Data) -> - {decoder, fun(_) -> {Data, []} end}. - --file("src/gleam/dynamic/decode.gleam", 718). --spec decode_dynamic(gleam@dynamic:dynamic_()) -> {gleam@dynamic:dynamic_(), - list(decode_error())}. -decode_dynamic(Data) -> - {Data, []}. - --file("src/gleam/dynamic/decode.gleam", 875). -?DOC( - " Apply a transformation function to any value decoded by the decoder.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.int |> decode.map(int.to_string)\n" - " let result = decode.run(dynamic.int(1000), decoder)\n" - " assert result == Ok(\"1000\")\n" - " ```\n" -). --spec map(decoder(BZC), fun((BZC) -> BZE)) -> decoder(BZE). -map(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Transformer(Data), Errors} - end}. - --file("src/gleam/dynamic/decode.gleam", 884). -?DOC(" Apply a transformation function to any errors returned by the decoder.\n"). --spec map_errors( - decoder(BZG), - fun((list(decode_error())) -> list(decode_error())) -) -> decoder(BZG). -map_errors(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Data, Transformer(Errors)} - end}. - --file("src/gleam/dynamic/decode.gleam", 922). -?DOC( - " Create a new decoder based upon the value of a previous decoder.\n" - "\n" - " This may be useful to run one previous decoder to use in further decoding.\n" -). --spec then(decoder(BZO), fun((BZO) -> decoder(BZQ))) -> decoder(BZQ). -then(Decoder, Next) -> - {decoder, - fun(Dynamic_data) -> - {Data, Errors} = (erlang:element(2, Decoder))(Dynamic_data), - Decoder@1 = Next(Data), - {Data@1, _} = Layer = (erlang:element(2, Decoder@1))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - {Data@1, Errors} - end - end}. - --file("src/gleam/dynamic/decode.gleam", 965). --spec run_decoders( - gleam@dynamic:dynamic_(), - {BZY, list(decode_error())}, - list(decoder(BZY)) -) -> {BZY, list(decode_error())}. -run_decoders(Data, Failure, Decoders) -> - case Decoders of - [] -> - Failure; - - [Decoder | Decoders@1] -> - {_, Errors} = Layer = (erlang:element(2, Decoder))(Data), - case Errors of - [] -> - Layer; - - [_ | _] -> - run_decoders(Data, Failure, Decoders@1) - end - end. - --file("src/gleam/dynamic/decode.gleam", 952). -?DOC( - " Create a new decoder from several other decoders. Each of the inner\n" - " decoders is run in turn, and the value from the first to succeed is used.\n" - "\n" - " If no decoder succeeds then the errors from the first decoder is used.\n" - " If you wish for different errors then you may wish to use the\n" - " `collapse_errors` or `map_errors` functions.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.one_of(decode.string, or: [\n" - " decode.int |> decode.map(int.to_string),\n" - " decode.float |> decode.map(float.to_string),\n" - " ])\n" - " decode.run(dynamic.int(1000), decoder)\n" - " // -> Ok(\"1000\")\n" - " ```\n" -). --spec one_of(decoder(BZT), list(decoder(BZT))) -> decoder(BZT). -one_of(First, Alternatives) -> - {decoder, - fun(Dynamic_data) -> - {_, Errors} = Layer = (erlang:element(2, First))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - run_decoders(Dynamic_data, Layer, Alternatives) - end - end}. - --file("src/gleam/dynamic/decode.gleam", 1048). -?DOC( - " Create a decoder that can refer to itself, useful for decoding deeply\n" - " nested data.\n" - "\n" - " Attempting to create a recursive decoder without this function could result\n" - " in an infinite loop. If you are using `field` or other `use`able functions\n" - " then you may not need to use this function.\n" - "\n" - " ```gleam\n" - " type Nested {\n" - " Nested(List(Nested))\n" - " Value(String)\n" - " }\n" - "\n" - " fn nested_decoder() -> decode.Decoder(Nested) {\n" - " use <- decode.recursive\n" - " decode.one_of(decode.string |> decode.map(Value), [\n" - " decode.list(nested_decoder()) |> decode.map(Nested),\n" - " ])\n" - " }\n" - " ```\n" -). --spec recursive(fun(() -> decoder(CAJ))) -> decoder(CAJ). -recursive(Inner) -> - {decoder, - fun(Data) -> - Decoder = Inner(), - (erlang:element(2, Decoder))(Data) - end}. - --file("src/gleam/dynamic/decode.gleam", 853). -?DOC( - " A decoder that decodes nullable values of a type decoded by with a given\n" - " decoder.\n" - "\n" - " This function can handle common representations of null on all runtimes, such as\n" - " `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on\n" - " JavaScript.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.int(100), decode.optional(decode.int))\n" - " assert result == Ok(option.Some(100))\n" - " ```\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.nil(), decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" -). --spec optional(decoder(BYY)) -> decoder(gleam@option:option(BYY)). -optional(Inner) -> - {decoder, fun(Data) -> case gleam_stdlib:is_null(Data) of - true -> - {none, []}; - - false -> - {Data@1, Errors} = (erlang:element(2, Inner))(Data), - {{some, Data@1}, Errors} - end end}. - --file("src/gleam/dynamic/decode.gleam", 485). -?DOC(" Construct a decode error for some unexpected dynamic data.\n"). --spec decode_error(binary(), gleam@dynamic:dynamic_()) -> list(decode_error()). -decode_error(Expected, Found) -> - [{decode_error, Expected, gleam_stdlib:classify_dynamic(Found), []}]. - --file("src/gleam/dynamic/decode.gleam", 609). --spec run_dynamic_function( - gleam@dynamic:dynamic_(), - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, BWZ} | {error, BWZ}) -) -> {BWZ, list(decode_error())}. -run_dynamic_function(Data, Name, F) -> - case F(Data) of - {ok, Data@1} -> - {Data@1, []}; - - {error, Zero} -> - {Zero, - [{decode_error, Name, gleam_stdlib:classify_dynamic(Data), []}]} - end. - --file("src/gleam/dynamic/decode.gleam", 658). --spec decode_bool(gleam@dynamic:dynamic_()) -> {boolean(), list(decode_error())}. -decode_bool(Data) -> - case gleam_stdlib:identity(true) =:= Data of - true -> - {true, []}; - - false -> - case gleam_stdlib:identity(false) =:= Data of - true -> - {false, []}; - - false -> - {false, decode_error(<<"Bool"/utf8>>, Data)} - end - end. - --file("src/gleam/dynamic/decode.gleam", 680). --spec decode_int(gleam@dynamic:dynamic_()) -> {integer(), list(decode_error())}. -decode_int(Data) -> - run_dynamic_function(Data, <<"Int"/utf8>>, fun gleam_stdlib:int/1). - --file("src/gleam/dynamic/decode.gleam", 699). --spec decode_float(gleam@dynamic:dynamic_()) -> {float(), list(decode_error())}. -decode_float(Data) -> - run_dynamic_function(Data, <<"Float"/utf8>>, fun gleam_stdlib:float/1). - --file("src/gleam/dynamic/decode.gleam", 733). --spec decode_bit_array(gleam@dynamic:dynamic_()) -> {bitstring(), - list(decode_error())}. -decode_bit_array(Data) -> - run_dynamic_function( - Data, - <<"BitArray"/utf8>>, - fun gleam_stdlib:bit_array/1 - ). - --file("src/gleam/dynamic/decode.gleam", 908). -?DOC( - " Replace all errors produced by a decoder with one single error for a named\n" - " expected type.\n" - "\n" - " This function may be useful if you wish to simplify errors before\n" - " presenting them to a user, particularly when using the `one_of` function.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.string |> decode.collapse_errors(\"MyThing\")\n" - " let result = decode.run(dynamic.int(1000), decoder)\n" - " assert result == Error([DecodeError(\"MyThing\", \"Int\", [])])\n" - " ```\n" -). --spec collapse_errors(decoder(BZL), binary()) -> decoder(BZL). -collapse_errors(Decoder, Name) -> - {decoder, - fun(Dynamic_data) -> - {Data, Errors} = Layer = (erlang:element(2, Decoder))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - {Data, decode_error(Name, Dynamic_data)} - end - end}. - --file("src/gleam/dynamic/decode.gleam", 986). -?DOC( - " Define a decoder that always fails. The parameter for this function is the\n" - " name of the type that has failed to decode.\n" -). --spec failure(CAD, binary()) -> decoder(CAD). -failure(Zero, Expected) -> - {decoder, fun(D) -> {Zero, decode_error(Expected, D)} end}. - --file("src/gleam/dynamic/decode.gleam", 1015). -?DOC( - " Create a decoder for a new data type from a decoding function.\n" - "\n" - " This function is used for new primitive types. For example, you might\n" - " define a decoder for Erlang's pid type.\n" - "\n" - " A default \"zero\" value is also required to make a decoder. When this\n" - " decoder is used as part of a larger decoder this zero value used as\n" - " a placeholder so that the rest of the decoder can continue to run and\n" - " collect all decoding errors.\n" - "\n" - " If you were to make a decoder for the `String` type (rather than using the\n" - " build-in `string` decoder) you would define it like so:\n" - "\n" - " ```gleam\n" - " pub fn string_decoder() -> decode.Decoder(String) {\n" - " let default = \"\"\n" - " decode.new_primitive_decoder(\"String\", fn(data) {\n" - " case dynamic.string(data) {\n" - " Ok(x) -> Ok(x)\n" - " Error(_) -> Error(default)\n" - " }\n" - " })\n" - " }\n" - " ```\n" -). --spec new_primitive_decoder( - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, CAF} | {error, CAF}) -) -> decoder(CAF). -new_primitive_decoder(Name, Decoding_function) -> - {decoder, fun(D) -> case Decoding_function(D) of - {ok, T} -> - {T, []}; - - {error, Zero} -> - {Zero, - [{decode_error, - Name, - gleam_stdlib:classify_dynamic(D), - []}]} - end end}. - --file("src/gleam/dynamic/decode.gleam", 636). --spec dynamic_string(gleam@dynamic:dynamic_()) -> {ok, binary()} | - {error, binary()}. -dynamic_string(Data) -> - case gleam_stdlib:bit_array(Data) of - {ok, Data@1} -> - case gleam@bit_array:to_string(Data@1) of - {ok, String} -> - {ok, String}; - - {error, _} -> - {error, <<""/utf8>>} - end; - - {error, _} -> - {error, <<""/utf8>>} - end. - --file("src/gleam/dynamic/decode.gleam", 631). --spec decode_string(gleam@dynamic:dynamic_()) -> {binary(), - list(decode_error())}. -decode_string(Data) -> - run_dynamic_function(Data, <<"String"/utf8>>, fun dynamic_string/1). - --file("src/gleam/dynamic/decode.gleam", 807). --spec fold_dict( - {gleam@dict:dict(BYK, BYL), list(decode_error())}, - gleam@dynamic:dynamic_(), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_()) -> {BYK, list(decode_error())}), - fun((gleam@dynamic:dynamic_()) -> {BYL, list(decode_error())}) -) -> {gleam@dict:dict(BYK, BYL), list(decode_error())}. -fold_dict(Acc, Key, Value, Key_decoder, Value_decoder) -> - case Key_decoder(Key) of - {Key@1, []} -> - case Value_decoder(Value) of - {Value@1, []} -> - Dict = gleam@dict:insert( - erlang:element(1, Acc), - Key@1, - Value@1 - ), - {Dict, erlang:element(2, Acc)}; - - {_, Errors} -> - push_path({maps:new(), Errors}, [<<"values"/utf8>>]) - end; - - {_, Errors@1} -> - push_path({maps:new(), Errors@1}, [<<"keys"/utf8>>]) - end. - --file("src/gleam/dynamic/decode.gleam", 787). -?DOC( - " A decoder that decodes dicts where all keys and vales are decoded with\n" - " given decoders.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let values = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.int(1)),\n" - " #(dynamic.string(\"two\"), dynamic.int(2)),\n" - " ])\n" - "\n" - " let result =\n" - " decode.run(values, decode.dict(decode.string, decode.int))\n" - " assert result == Ok(values)\n" - " ```\n" -). --spec dict(decoder(BYD), decoder(BYF)) -> decoder(gleam@dict:dict(BYD, BYF)). -dict(Key, Value) -> - {decoder, fun(Data) -> case gleam_stdlib:dict(Data) of - {error, _} -> - {maps:new(), decode_error(<<"Dict"/utf8>>, Data)}; - - {ok, Dict} -> - gleam@dict:fold( - Dict, - {maps:new(), []}, - fun(A, K, V) -> case erlang:element(2, A) of - [] -> - fold_dict( - A, - K, - V, - erlang:element(2, Key), - erlang:element(2, Value) - ); - - [_ | _] -> - A - end end - ) - end end}. - --file("src/gleam/dynamic/decode.gleam", 755). -?DOC( - " A decoder that decodes lists where all elements are decoded with a given\n" - " decoder.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let result =\n" - " [1, 2, 3]\n" - " |> list.map(dynamic.int)\n" - " |> dynamic.list\n" - " |> decode.run(decode.list(of: decode.int))\n" - " assert result == Ok([1, 2, 3])\n" - " ```\n" -). --spec list(decoder(BXR)) -> decoder(list(BXR)). -list(Inner) -> - {decoder, - fun(Data) -> - gleam_stdlib:list( - Data, - erlang:element(2, Inner), - fun(P, K) -> push_path(P, [K]) end, - 0, - [] - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 439). --spec push_path({BWA, list(decode_error())}, list(any())) -> {BWA, - list(decode_error())}. -push_path(Layer, Path) -> - Decoder = one_of( - {decoder, fun decode_string/1}, - [begin - _pipe = {decoder, fun decode_int/1}, - map(_pipe, fun erlang:integer_to_binary/1) - end] - ), - Path@1 = gleam@list:map( - Path, - fun(Key) -> - Key@1 = gleam_stdlib:identity(Key), - case run(Key@1, Decoder) of - {ok, Key@2} -> - Key@2; - - {error, _} -> - <<<<"<"/utf8, - (gleam_stdlib:classify_dynamic(Key@1))/binary>>/binary, - ">"/utf8>> - end - end - ), - Errors = gleam@list:map( - erlang:element(2, Layer), - fun(Error) -> - {decode_error, - erlang:element(2, Error), - erlang:element(3, Error), - lists:append(Path@1, erlang:element(4, Error))} - end - ), - {erlang:element(1, Layer), Errors}. - --file("src/gleam/dynamic/decode.gleam", 403). --spec index( - list(BVO), - list(BVO), - fun((gleam@dynamic:dynamic_()) -> {BVR, list(decode_error())}), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_(), list(BVO)) -> {BVR, list(decode_error())}) -) -> {BVR, list(decode_error())}. -index(Path, Position, Inner, Data, Handle_miss) -> - case Path of - [] -> - _pipe = Data, - _pipe@1 = Inner(_pipe), - push_path(_pipe@1, lists:reverse(Position)); - - [Key | Path@1] -> - case gleam_stdlib:index(Data, Key) of - {ok, {some, Data@1}} -> - index(Path@1, [Key | Position], Inner, Data@1, Handle_miss); - - {ok, none} -> - Handle_miss(Data, [Key | Position]); - - {error, Kind} -> - {Default, _} = Inner(Data), - _pipe@2 = {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]}, - push_path(_pipe@2, lists:reverse(Position)) - end - end. - --file("src/gleam/dynamic/decode.gleam", 324). -?DOC( - " The same as [`field`](#field), except taking a path to the value rather\n" - " than a field name.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"data\"), dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ])\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.subfield([\"data\", \"name\"], decode.string)\n" - " use email <- decode.subfield([\"data\", \"email\"], decode.string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" -). --spec subfield(list(any()), decoder(BUZ), fun((BUZ) -> decoder(BVB))) -> decoder(BVB). -subfield(Field_path, Field_decoder, Next) -> - {decoder, - fun(Data) -> - {Out, Errors1} = index( - Field_path, - [], - erlang:element(2, Field_decoder), - Data, - fun(Data@1, Position) -> - {Default, _} = (erlang:element(2, Field_decoder))(Data@1), - _pipe = {Default, - [{decode_error, - <<"Field"/utf8>>, - <<"Nothing"/utf8>>, - []}]}, - push_path(_pipe, lists:reverse(Position)) - end - ), - {Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data), - {Out@1, lists:append(Errors1, Errors2)} - end}. - --file("src/gleam/dynamic/decode.gleam", 393). -?DOC( - " A decoder that decodes a value that is nested within other values. For\n" - " example, decoding a value that is within some deeply nested JSON objects.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.at([\"one\", \"two\"], decode.int)\n" - "\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.properties([\n" - " #(dynamic.string(\"two\"), dynamic.int(1000)),\n" - " ])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(1000)\n" - " ```\n" - "\n" - " ```gleam\n" - " dynamic.nil()\n" - " |> decode.run(decode.optional(decode.int))\n" - " // -> Ok(option.None)\n" - " ```\n" -). --spec at(list(any()), decoder(BVL)) -> decoder(BVL). -at(Path, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(Data@1, Position) -> - {Default, _} = (erlang:element(2, Inner))(Data@1), - _pipe = {Default, - [{decode_error, - <<"Field"/utf8>>, - <<"Nothing"/utf8>>, - []}]}, - push_path(_pipe, lists:reverse(Position)) - end - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 524). -?DOC( - " Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n" - " of the desired type, or returning errors. An error is returned if there is\n" - " no field for the specified key.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.field(\"email\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" - "\n" - " If you wish to decode a value that is more deeply nested within the dynamic\n" - " data, see [`subfield`](#subfield) and [`at`](#at).\n" - "\n" - " If you wish to return a default in the event that a field is not present,\n" - " see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at).\n" -). --spec field(any(), decoder(BWJ), fun((BWJ) -> decoder(BWL))) -> decoder(BWL). -field(Field_name, Field_decoder, Next) -> - subfield([Field_name], Field_decoder, Next). - --file("src/gleam/dynamic/decode.gleam", 557). -?DOC( - " Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n" - " of the desired type, or returning errors. The given default value is\n" - " returned if there is no field for the specified key.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.optional_field(\"email\", \"n/a\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"n/a\"))\n" - " ```\n" -). --spec optional_field(any(), BWP, decoder(BWP), fun((BWP) -> decoder(BWR))) -> decoder(BWR). -optional_field(Key, Default, Field_decoder, Next) -> - {decoder, - fun(Data) -> - {Out, Errors1} = begin - _pipe = case gleam_stdlib:index(Data, Key) of - {ok, {some, Data@1}} -> - (erlang:element(2, Field_decoder))(Data@1); - - {ok, none} -> - {Default, []}; - - {error, Kind} -> - {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]} - end, - push_path(_pipe, [Key]) - end, - {Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data), - {Out@1, lists:append(Errors1, Errors2)} - end}. - --file("src/gleam/dynamic/decode.gleam", 599). -?DOC( - " A decoder that decodes a value that is nested within other values. For\n" - " example, decoding a value that is within some deeply nested JSON objects.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.optionally_at([\"one\", \"two\"], 100, decode.int)\n" - "\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.properties([])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(100)\n" - " ```\n" -). --spec optionally_at(list(any()), BWW, decoder(BWW)) -> decoder(BWW). -optionally_at(Path, Default, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(_, _) -> {Default, []} end - ) - end}. diff --git a/build/dev/javascript/gleam_stdlib/gleam@float.erl b/build/dev/javascript/gleam_stdlib/gleam@float.erl deleted file mode 100644 index 6b55b47..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@float.erl +++ /dev/null @@ -1,744 +0,0 @@ --module(gleam@float). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/float.gleam"). --export([parse/1, to_string/1, compare/2, min/2, max/2, clamp/3, ceiling/1, floor/1, truncate/1, absolute_value/1, loosely_compare/3, loosely_equals/3, power/2, square_root/1, negate/1, round/1, to_precision/2, sum/1, product/1, random/0, modulo/2, divide/2, add/2, multiply/2, subtract/2, logarithm/1, exponential/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Functions for working with floats.\n" - "\n" - " ## Float representation\n" - "\n" - " Floats are represented as 64 bit floating point numbers on both the Erlang\n" - " and JavaScript runtimes. The floating point behaviour is native to their\n" - " respective runtimes, so their exact behaviour will be slightly different on\n" - " the two runtimes.\n" - "\n" - " ### Infinity and NaN\n" - "\n" - " Under the JavaScript runtime, exceeding the maximum (or minimum)\n" - " representable value for a floating point value will result in Infinity (or\n" - " -Infinity). Should you try to divide two infinities you will get NaN as a\n" - " result.\n" - "\n" - " When running on BEAM, exceeding the maximum (or minimum) representable\n" - " value for a floating point value will raise an error.\n" - "\n" - " ## Division by zero\n" - "\n" - " Gleam runs on the Erlang virtual machine, which does not follow the IEEE\n" - " 754 standard for floating point arithmetic and does not have an `Infinity`\n" - " value. In Erlang division by zero results in a crash, however Gleam does\n" - " not have partial functions and operators in core so instead division by zero\n" - " returns zero, a behaviour taken from Pony, Coq, and Lean.\n" - "\n" - " This may seem unexpected at first, but it is no less mathematically valid\n" - " than crashing or returning a special value. Division by zero is undefined\n" - " in mathematics.\n" -). - --file("src/gleam/float.gleam", 51). -?DOC( - " Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was\n" - " not possible.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse(\"2.3\")\n" - " // -> Ok(2.3)\n" - " ```\n" - "\n" - " ```gleam\n" - " parse(\"ABC\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec parse(binary()) -> {ok, float()} | {error, nil}. -parse(String) -> - gleam_stdlib:parse_float(String). - --file("src/gleam/float.gleam", 64). -?DOC( - " Returns the string representation of the provided `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_string(2.3)\n" - " // -> \"2.3\"\n" - " ```\n" -). --spec to_string(float()) -> binary(). -to_string(X) -> - gleam_stdlib:float_to_string(X). - --file("src/gleam/float.gleam", 95). -?DOC( - " Compares two `Float`s, returning an `Order`:\n" - " `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(2.0, 2.3)\n" - " // -> Lt\n" - " ```\n" - "\n" - " To handle\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems)\n" - " you may use [`loosely_compare`](#loosely_compare) instead.\n" -). --spec compare(float(), float()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - false -> - case A < B of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/float.gleam", 176). -?DOC( - " Compares two `Float`s, returning the smaller of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " min(2.0, 2.3)\n" - " // -> 2.0\n" - " ```\n" -). --spec min(float(), float()) -> float(). -min(A, B) -> - case A < B of - true -> - A; - - false -> - B - end. - --file("src/gleam/float.gleam", 192). -?DOC( - " Compares two `Float`s, returning the larger of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " max(2.0, 2.3)\n" - " // -> 2.3\n" - " ```\n" -). --spec max(float(), float()) -> float(). -max(A, B) -> - case A > B of - true -> - A; - - false -> - B - end. - --file("src/gleam/float.gleam", 75). -?DOC( - " Restricts a `Float` between a lower and upper bound.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " clamp(1.2, min: 1.4, max: 1.6)\n" - " // -> 1.4\n" - " ```\n" -). --spec clamp(float(), float(), float()) -> float(). -clamp(X, Min_bound, Max_bound) -> - _pipe = X, - _pipe@1 = min(_pipe, Max_bound), - max(_pipe@1, Min_bound). - --file("src/gleam/float.gleam", 210). -?DOC( - " Rounds the value to the next highest whole number as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " ceiling(2.3)\n" - " // -> 3.0\n" - " ```\n" -). --spec ceiling(float()) -> float(). -ceiling(X) -> - math:ceil(X). - --file("src/gleam/float.gleam", 223). -?DOC( - " Rounds the value to the next lowest whole number as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " floor(2.3)\n" - " // -> 2.0\n" - " ```\n" -). --spec floor(float()) -> float(). -floor(X) -> - math:floor(X). - --file("src/gleam/float.gleam", 261). -?DOC( - " Returns the value as an `Int`, truncating all decimal digits.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " truncate(2.4343434847383438)\n" - " // -> 2\n" - " ```\n" -). --spec truncate(float()) -> integer(). -truncate(X) -> - erlang:trunc(X). - --file("src/gleam/float.gleam", 311). -?DOC( - " Returns the absolute value of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " absolute_value(-12.5)\n" - " // -> 12.5\n" - " ```\n" - "\n" - " ```gleam\n" - " absolute_value(10.2)\n" - " // -> 10.2\n" - " ```\n" -). --spec absolute_value(float()) -> float(). -absolute_value(X) -> - case X >= +0.0 of - true -> - X; - - false -> - +0.0 - X - end. - --file("src/gleam/float.gleam", 125). -?DOC( - " Compares two `Float`s within a tolerance, returning an `Order`:\n" - " `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n" - "\n" - " This function allows Float comparison while handling\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n" - "\n" - " Notice: For `Float`s the tolerance won't be exact:\n" - " `5.3 - 5.0` is not exactly `0.3`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " loosely_compare(5.0, with: 5.3, tolerating: 0.5)\n" - " // -> Eq\n" - " ```\n" - "\n" - " If you want to check only for equality you may use\n" - " [`loosely_equals`](#loosely_equals) instead.\n" -). --spec loosely_compare(float(), float(), float()) -> gleam@order:order(). -loosely_compare(A, B, Tolerance) -> - Difference = absolute_value(A - B), - case Difference =< Tolerance of - true -> - eq; - - false -> - compare(A, B) - end. - --file("src/gleam/float.gleam", 158). -?DOC( - " Checks for equality of two `Float`s within a tolerance,\n" - " returning an `Bool`.\n" - "\n" - " This function allows Float comparison while handling\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n" - "\n" - " Notice: For `Float`s the tolerance won't be exact:\n" - " `5.3 - 5.0` is not exactly `0.3`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " loosely_equals(5.0, with: 5.3, tolerating: 0.5)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " loosely_equals(5.0, with: 5.1, tolerating: 0.1)\n" - " // -> False\n" - " ```\n" -). --spec loosely_equals(float(), float(), float()) -> boolean(). -loosely_equals(A, B, Tolerance) -> - Difference = absolute_value(A - B), - Difference =< Tolerance. - --file("src/gleam/float.gleam", 348). -?DOC( - " Returns the results of the base being raised to the power of the\n" - " exponent, as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " power(2.0, -1.0)\n" - " // -> Ok(0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(2.0, 2.0)\n" - " // -> Ok(4.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(8.0, 1.5)\n" - " // -> Ok(22.627416997969522)\n" - " ```\n" - "\n" - " ```gleam\n" - " 4.0 |> power(of: 2.0)\n" - " // -> Ok(16.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(-1.0, 0.5)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec power(float(), float()) -> {ok, float()} | {error, nil}. -power(Base, Exponent) -> - Fractional = (math:ceil(Exponent) - Exponent) > +0.0, - case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent - < +0.0)) of - true -> - {error, nil}; - - false -> - {ok, math:pow(Base, Exponent)} - end. - --file("src/gleam/float.gleam", 380). -?DOC( - " Returns the square root of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " square_root(4.0)\n" - " // -> Ok(2.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " square_root(-16.0)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec square_root(float()) -> {ok, float()} | {error, nil}. -square_root(X) -> - power(X, 0.5). - --file("src/gleam/float.gleam", 393). -?DOC( - " Returns the negative of the value provided.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(1.0)\n" - " // -> -1.0\n" - " ```\n" -). --spec negate(float()) -> float(). -negate(X) -> - -1.0 * X. - --file("src/gleam/float.gleam", 240). -?DOC( - " Rounds the value to the nearest whole number as an `Int`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " round(2.3)\n" - " // -> 2\n" - " ```\n" - "\n" - " ```gleam\n" - " round(2.5)\n" - " // -> 3\n" - " ```\n" -). --spec round(float()) -> integer(). -round(X) -> - erlang:round(X). - --file("src/gleam/float.gleam", 280). -?DOC( - " Converts the value to a given precision as a `Float`.\n" - " The precision is the number of allowed decimal places.\n" - " Negative precisions are allowed and force rounding\n" - " to the nearest tenth, hundredth, thousandth etc.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_precision(2.43434348473, precision: 2)\n" - " // -> 2.43\n" - " ```\n" - "\n" - " ```gleam\n" - " to_precision(547890.453444, precision: -3)\n" - " // -> 548000.0\n" - " ```\n" -). --spec to_precision(float(), integer()) -> float(). -to_precision(X, Precision) -> - case Precision =< 0 of - true -> - Factor = math:pow(10.0, erlang:float(- Precision)), - erlang:float(erlang:round(case Factor of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> X / Gleam@denominator - end)) * Factor; - - false -> - Factor@1 = math:pow(10.0, erlang:float(Precision)), - case Factor@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> erlang:float(erlang:round(X * Factor@1)) - / Gleam@denominator@1 - end - end. - --file("src/gleam/float.gleam", 410). --spec sum_loop(list(float()), float()) -> float(). -sum_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - sum_loop(Rest, First + Initial); - - [] -> - Initial - end. - --file("src/gleam/float.gleam", 406). -?DOC( - " Sums a list of `Float`s.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " sum([1.0, 2.2, 3.3])\n" - " // -> 6.5\n" - " ```\n" -). --spec sum(list(float())) -> float(). -sum(Numbers) -> - sum_loop(Numbers, +0.0). - --file("src/gleam/float.gleam", 430). --spec product_loop(list(float()), float()) -> float(). -product_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - product_loop(Rest, First * Initial); - - [] -> - Initial - end. - --file("src/gleam/float.gleam", 426). -?DOC( - " Multiplies a list of `Float`s and returns the product.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " product([2.5, 3.2, 4.2])\n" - " // -> 33.6\n" - " ```\n" -). --spec product(list(float())) -> float(). -product(Numbers) -> - product_loop(Numbers, 1.0). - --file("src/gleam/float.gleam", 452). -?DOC( - " Generates a random float between the given zero (inclusive) and one\n" - " (exclusive).\n" - "\n" - " On Erlang this updates the random state in the process dictionary.\n" - " See: \n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " random()\n" - " // -> 0.646355926896028\n" - " ```\n" -). --spec random() -> float(). -random() -> - rand:uniform(). - --file("src/gleam/float.gleam", 481). -?DOC( - " Computes the modulo of an float division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " modulo(13.3, by: 3.3)\n" - " // -> Ok(0.1)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(-13.3, by: 3.3)\n" - " // -> Ok(3.2)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(13.3, by: -3.3)\n" - " // -> Ok(-3.2)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(-13.3, by: -3.3)\n" - " // -> Ok(-0.1)\n" - " ```\n" -). --spec modulo(float(), float()) -> {ok, float()} | {error, nil}. -modulo(Dividend, Divisor) -> - case Divisor of - +0.0 -> - {error, nil}; - - _ -> - {ok, Dividend - (math:floor(case Divisor of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> Dividend / Gleam@denominator - end) * Divisor)} - end. - --file("src/gleam/float.gleam", 502). -?DOC( - " Returns division of the inputs as a `Result`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " divide(0.0, 1.0)\n" - " // -> Ok(0.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(1.0, 0.0)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec divide(float(), float()) -> {ok, float()} | {error, nil}. -divide(A, B) -> - case B of - +0.0 -> - {error, nil}; - - B@1 -> - {ok, case B@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> A / Gleam@denominator - end} - end. - --file("src/gleam/float.gleam", 533). -?DOC( - " Adds two floats together.\n" - "\n" - " It's the function equivalent of the `+.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " add(1.0, 2.0)\n" - " // -> 3.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([1.0, 2.0, 3.0], 0.0, add)\n" - " // -> 6.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> add(2.0)\n" - " // -> 5.0\n" - " ```\n" -). --spec add(float(), float()) -> float(). -add(A, B) -> - A + B. - --file("src/gleam/float.gleam", 561). -?DOC( - " Multiplies two floats together.\n" - "\n" - " It's the function equivalent of the `*.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " multiply(2.0, 4.0)\n" - " // -> 8.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([2.0, 3.0, 4.0], 1.0, multiply)\n" - " // -> 24.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> multiply(2.0)\n" - " // -> 6.0\n" - " ```\n" -). --spec multiply(float(), float()) -> float(). -multiply(A, B) -> - A * B. - --file("src/gleam/float.gleam", 594). -?DOC( - " Subtracts one float from another.\n" - "\n" - " It's the function equivalent of the `-.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " subtract(3.0, 1.0)\n" - " // -> 2.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([1.0, 2.0, 3.0], 10.0, subtract)\n" - " // -> 4.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> subtract(_, 2.0)\n" - " // -> 1.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> subtract(2.0, _)\n" - " // -> -1.0\n" - " ```\n" -). --spec subtract(float(), float()) -> float(). -subtract(A, B) -> - A - B. - --file("src/gleam/float.gleam", 623). -?DOC( - " Returns the natural logarithm (base e) of the given as a `Result`. If the\n" - " input is less than or equal to 0, returns `Error(Nil)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " logarithm(1.0)\n" - " // -> Ok(0.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " logarithm(2.718281828459045) // e\n" - " // -> Ok(1.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " logarithm(0.0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " logarithm(-1.0)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec logarithm(float()) -> {ok, float()} | {error, nil}. -logarithm(X) -> - case X =< +0.0 of - true -> - {error, nil}; - - false -> - {ok, math:log(X)} - end. - --file("src/gleam/float.gleam", 661). -?DOC( - " Returns e (Euler's number) raised to the power of the given exponent, as\n" - " a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " exponential(0.0)\n" - " // -> Ok(1.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " exponential(1.0)\n" - " // -> Ok(2.718281828459045)\n" - " ```\n" - "\n" - " ```gleam\n" - " exponential(-1.0)\n" - " // -> Ok(0.36787944117144233)\n" - " ```\n" -). --spec exponential(float()) -> float(). -exponential(X) -> - math:exp(X). diff --git a/build/dev/javascript/gleam_stdlib/gleam@function.erl b/build/dev/javascript/gleam_stdlib/gleam@function.erl deleted file mode 100644 index a6dec81..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@function.erl +++ /dev/null @@ -1,30 +0,0 @@ --module(gleam@function). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/function.gleam"). --export([identity/1, tap/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/function.gleam", 3). -?DOC(" Takes a single argument and always returns its input value.\n"). --spec identity(CLA) -> CLA. -identity(X) -> - X. - --file("src/gleam/function.gleam", 12). -?DOC( - " Takes an argument and a single function, calls that function with that\n" - " argument and returns that argument instead of the function return value.\n" - "\n" - " Useful for running synchronous side effects in a pipeline.\n" -). --spec tap(CLB, fun((CLB) -> any())) -> CLB. -tap(Arg, Effect) -> - Effect(Arg), - Arg. diff --git a/build/dev/javascript/gleam_stdlib/gleam@int.erl b/build/dev/javascript/gleam_stdlib/gleam@int.erl deleted file mode 100644 index 5e298da..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@int.erl +++ /dev/null @@ -1,986 +0,0 @@ --module(gleam@int). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/int.gleam"). --export([absolute_value/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, to_float/1, power/2, square_root/1, compare/2, min/2, max/2, clamp/3, is_even/1, is_odd/1, negate/1, sum/1, product/1, digits/2, undigits/2, random/1, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Functions for working with integers.\n" - "\n" - " ## Division by zero\n" - "\n" - " In Erlang division by zero results in a crash, however Gleam does not have\n" - " partial functions and operators in core so instead division by zero returns\n" - " zero, a behaviour taken from Pony, Coq, and Lean.\n" - "\n" - " This may seem unexpected at first, but it is no less mathematically valid\n" - " than crashing or returning a special value. Division by zero is undefined\n" - " in mathematics.\n" -). - --file("src/gleam/int.gleam", 30). -?DOC( - " Returns the absolute value of the input.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " absolute_value(-12)\n" - " // -> 12\n" - " ```\n" - "\n" - " ```gleam\n" - " absolute_value(10)\n" - " // -> 10\n" - " ```\n" -). --spec absolute_value(integer()) -> integer(). -absolute_value(X) -> - case X >= 0 of - true -> - X; - - false -> - X * -1 - end. - --file("src/gleam/int.gleam", 109). -?DOC( - " Parses a given string as an int if possible.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse(\"2\")\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " parse(\"ABC\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec parse(binary()) -> {ok, integer()} | {error, nil}. -parse(String) -> - gleam_stdlib:parse_int(String). - --file("src/gleam/int.gleam", 141). -?DOC( - " Parses a given string as an int in a given base if possible.\n" - " Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " base_parse(\"10\", 2)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"30\", 16)\n" - " // -> Ok(48)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"1C\", 36)\n" - " // -> Ok(48)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"48\", 1)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"48\", 37)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}. -base_parse(String, Base) -> - case (Base >= 2) andalso (Base =< 36) of - true -> - gleam_stdlib:int_from_base_string(String, Base); - - false -> - {error, nil} - end. - --file("src/gleam/int.gleam", 163). -?DOC( - " Prints a given int to a string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_string(2)\n" - " // -> \"2\"\n" - " ```\n" -). --spec to_string(integer()) -> binary(). -to_string(X) -> - erlang:integer_to_binary(X). - --file("src/gleam/int.gleam", 196). -?DOC( - " Prints a given int to a string using the base number provided.\n" - " Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n" - " For common bases (2, 8, 16, 36), use the `to_baseN` functions.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base_string(2, 2)\n" - " // -> Ok(\"10\")\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 16)\n" - " // -> Ok(\"30\")\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 36)\n" - " // -> Ok(\"1C\")\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 1)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 37)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec to_base_string(integer(), integer()) -> {ok, binary()} | {error, nil}. -to_base_string(X, Base) -> - case (Base >= 2) andalso (Base =< 36) of - true -> - {ok, erlang:integer_to_binary(X, Base)}; - - false -> - {error, nil} - end. - --file("src/gleam/int.gleam", 216). -?DOC( - " Prints a given int to a string using base-2.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base2(2)\n" - " // -> \"10\"\n" - " ```\n" -). --spec to_base2(integer()) -> binary(). -to_base2(X) -> - erlang:integer_to_binary(X, 2). - --file("src/gleam/int.gleam", 229). -?DOC( - " Prints a given int to a string using base-8.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base8(15)\n" - " // -> \"17\"\n" - " ```\n" -). --spec to_base8(integer()) -> binary(). -to_base8(X) -> - erlang:integer_to_binary(X, 8). - --file("src/gleam/int.gleam", 242). -?DOC( - " Prints a given int to a string using base-16.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base16(48)\n" - " // -> \"30\"\n" - " ```\n" -). --spec to_base16(integer()) -> binary(). -to_base16(X) -> - erlang:integer_to_binary(X, 16). - --file("src/gleam/int.gleam", 255). -?DOC( - " Prints a given int to a string using base-36.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base36(48)\n" - " // -> \"1C\"\n" - " ```\n" -). --spec to_base36(integer()) -> binary(). -to_base36(X) -> - erlang:integer_to_binary(X, 36). - --file("src/gleam/int.gleam", 280). -?DOC( - " Takes an int and returns its value as a float.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_float(5)\n" - " // -> 5.0\n" - " ```\n" - "\n" - " ```gleam\n" - " to_float(0)\n" - " // -> 0.0\n" - " ```\n" - "\n" - " ```gleam\n" - " to_float(-3)\n" - " // -> -3.0\n" - " ```\n" -). --spec to_float(integer()) -> float(). -to_float(X) -> - erlang:float(X). - --file("src/gleam/int.gleam", 67). -?DOC( - " Returns the results of the base being raised to the power of the\n" - " exponent, as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " power(2, -1.0)\n" - " // -> Ok(0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(2, 2.0)\n" - " // -> Ok(4.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(8, 1.5)\n" - " // -> Ok(22.627416997969522)\n" - " ```\n" - "\n" - " ```gleam\n" - " 4 |> power(of: 2.0)\n" - " // -> Ok(16.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(-1, 0.5)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec power(integer(), float()) -> {ok, float()} | {error, nil}. -power(Base, Exponent) -> - _pipe = Base, - _pipe@1 = erlang:float(_pipe), - gleam@float:power(_pipe@1, Exponent). - --file("src/gleam/int.gleam", 87). -?DOC( - " Returns the square root of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " square_root(4)\n" - " // -> Ok(2.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " square_root(-16)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec square_root(integer()) -> {ok, float()} | {error, nil}. -square_root(X) -> - _pipe = X, - _pipe@1 = erlang:float(_pipe), - gleam@float:square_root(_pipe@1). - --file("src/gleam/int.gleam", 316). -?DOC( - " Compares two ints, returning an order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(2, 3)\n" - " // -> Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " compare(4, 3)\n" - " // -> Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " compare(3, 3)\n" - " // -> Eq\n" - " ```\n" -). --spec compare(integer(), integer()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - false -> - case A < B of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/int.gleam", 336). -?DOC( - " Compares two ints, returning the smaller of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " min(2, 3)\n" - " // -> 2\n" - " ```\n" -). --spec min(integer(), integer()) -> integer(). -min(A, B) -> - case A < B of - true -> - A; - - false -> - B - end. - --file("src/gleam/int.gleam", 352). -?DOC( - " Compares two ints, returning the larger of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " max(2, 3)\n" - " // -> 3\n" - " ```\n" -). --spec max(integer(), integer()) -> integer(). -max(A, B) -> - case A > B of - true -> - A; - - false -> - B - end. - --file("src/gleam/int.gleam", 291). -?DOC( - " Restricts an int between a lower and upper bound.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " clamp(40, min: 50, max: 60)\n" - " // -> 50\n" - " ```\n" -). --spec clamp(integer(), integer(), integer()) -> integer(). -clamp(X, Min_bound, Max_bound) -> - _pipe = X, - _pipe@1 = min(_pipe, Max_bound), - max(_pipe@1, Min_bound). - --file("src/gleam/int.gleam", 373). -?DOC( - " Returns whether the value provided is even.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_even(2)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_even(3)\n" - " // -> False\n" - " ```\n" -). --spec is_even(integer()) -> boolean(). -is_even(X) -> - (X rem 2) =:= 0. - --file("src/gleam/int.gleam", 391). -?DOC( - " Returns whether the value provided is odd.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_odd(3)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_odd(2)\n" - " // -> False\n" - " ```\n" -). --spec is_odd(integer()) -> boolean(). -is_odd(X) -> - (X rem 2) /= 0. - --file("src/gleam/int.gleam", 404). -?DOC( - " Returns the negative of the value provided.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(1)\n" - " // -> -1\n" - " ```\n" -). --spec negate(integer()) -> integer(). -negate(X) -> - -1 * X. - --file("src/gleam/int.gleam", 421). --spec sum_loop(list(integer()), integer()) -> integer(). -sum_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - sum_loop(Rest, First + Initial); - - [] -> - Initial - end. - --file("src/gleam/int.gleam", 417). -?DOC( - " Sums a list of ints.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " sum([1, 2, 3])\n" - " // -> 6\n" - " ```\n" -). --spec sum(list(integer())) -> integer(). -sum(Numbers) -> - sum_loop(Numbers, 0). - --file("src/gleam/int.gleam", 441). --spec product_loop(list(integer()), integer()) -> integer(). -product_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - product_loop(Rest, First * Initial); - - [] -> - Initial - end. - --file("src/gleam/int.gleam", 437). -?DOC( - " Multiplies a list of ints and returns the product.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " product([2, 3, 4])\n" - " // -> 24\n" - " ```\n" -). --spec product(list(integer())) -> integer(). -product(Numbers) -> - product_loop(Numbers, 1). - --file("src/gleam/int.gleam", 456). --spec digits_loop(integer(), integer(), list(integer())) -> list(integer()). -digits_loop(X, Base, Acc) -> - case absolute_value(X) < Base of - true -> - [X | Acc]; - - false -> - digits_loop(case Base of - 0 -> 0; - Gleam@denominator -> X div Gleam@denominator - end, Base, [case Base of - 0 -> 0; - Gleam@denominator@1 -> X rem Gleam@denominator@1 - end | Acc]) - end. - --file("src/gleam/int.gleam", 449). --spec digits(integer(), integer()) -> {ok, list(integer())} | {error, nil}. -digits(X, Base) -> - case Base < 2 of - true -> - {error, nil}; - - false -> - {ok, digits_loop(X, Base, [])} - end. - --file("src/gleam/int.gleam", 471). --spec undigits_loop(list(integer()), integer(), integer()) -> {ok, integer()} | - {error, nil}. -undigits_loop(Numbers, Base, Acc) -> - case Numbers of - [] -> - {ok, Acc}; - - [Digit | _] when Digit >= Base -> - {error, nil}; - - [Digit@1 | Rest] -> - undigits_loop(Rest, Base, (Acc * Base) + Digit@1) - end. - --file("src/gleam/int.gleam", 464). --spec undigits(list(integer()), integer()) -> {ok, integer()} | {error, nil}. -undigits(Numbers, Base) -> - case Base < 2 of - true -> - {error, nil}; - - false -> - undigits_loop(Numbers, Base, 0) - end. - --file("src/gleam/int.gleam", 500). -?DOC( - " Generates a random int between zero and the given maximum.\n" - "\n" - " The lower number is inclusive, the upper number is exclusive.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " random(10)\n" - " // -> 4\n" - " ```\n" - "\n" - " ```gleam\n" - " random(1)\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " random(-1)\n" - " // -> -1\n" - " ```\n" -). --spec random(integer()) -> integer(). -random(Max) -> - _pipe = (rand:uniform() * erlang:float(Max)), - _pipe@1 = math:floor(_pipe), - erlang:round(_pipe@1). - --file("src/gleam/int.gleam", 533). -?DOC( - " Performs a truncated integer division.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " divide(0, 1)\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(5, 2)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(-99, 2)\n" - " // -> Ok(-49)\n" - " ```\n" -). --spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}. -divide(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend div Gleam@denominator - end} - end. - --file("src/gleam/int.gleam", 585). -?DOC( - " Computes the remainder of an integer division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " Most the time you will want to use the `%` operator instead of this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " remainder(3, 2)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(10, -1)\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(13, by: 3)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(-13, by: 3)\n" - " // -> Ok(-1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(13, by: -3)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(-13, by: -3)\n" - " // -> Ok(-1)\n" - " ```\n" -). --spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}. -remainder(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end} - end. - --file("src/gleam/int.gleam", 627). -?DOC( - " Computes the modulo of an integer division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " Most the time you will want to use the `%` operator instead of this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " modulo(3, 2)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(10, -1)\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(13, by: 3)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(-13, by: 3)\n" - " // -> Ok(2)\n" - " ```\n" -). --spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}. -modulo(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - _ -> - Remainder = case Divisor of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end, - case (Remainder * Divisor) < 0 of - true -> - {ok, Remainder + Divisor}; - - false -> - {ok, Remainder} - end - end. - --file("src/gleam/int.gleam", 671). -?DOC( - " Performs a *floored* integer division, which means that the result will\n" - " always be rounded towards negative infinity.\n" - "\n" - " If you want to perform truncated integer division (rounding towards zero),\n" - " use `int.divide()` or the `/` operator instead.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " floor_divide(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " floor_divide(5, 2)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " floor_divide(6, -4)\n" - " // -> Ok(-2)\n" - " ```\n" - "\n" - " ```gleam\n" - " floor_divide(-99, 2)\n" - " // -> Ok(-50)\n" - " ```\n" -). --spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}. -floor_divide(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end) /= 0) of - true -> - {ok, (case Divisor@1 of - 0 -> 0; - Gleam@denominator@1 -> Dividend div Gleam@denominator@1 - end) - 1}; - - false -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator@2 -> Dividend div Gleam@denominator@2 - end} - end - end. - --file("src/gleam/int.gleam", 705). -?DOC( - " Adds two integers together.\n" - "\n" - " It's the function equivalent of the `+` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " add(1, 2)\n" - " // -> 3\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - " list.fold([1, 2, 3], 0, add)\n" - " // -> 6\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> add(2)\n" - " // -> 5\n" - " ```\n" -). --spec add(integer(), integer()) -> integer(). -add(A, B) -> - A + B. - --file("src/gleam/int.gleam", 733). -?DOC( - " Multiplies two integers together.\n" - "\n" - " It's the function equivalent of the `*` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " multiply(2, 4)\n" - " // -> 8\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([2, 3, 4], 1, multiply)\n" - " // -> 24\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> multiply(2)\n" - " // -> 6\n" - " ```\n" -). --spec multiply(integer(), integer()) -> integer(). -multiply(A, B) -> - A * B. - --file("src/gleam/int.gleam", 766). -?DOC( - " Subtracts one int from another.\n" - "\n" - " It's the function equivalent of the `-` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " subtract(3, 1)\n" - " // -> 2\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([1, 2, 3], 10, subtract)\n" - " // -> 4\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> subtract(2)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> subtract(2, _)\n" - " // -> -1\n" - " ```\n" -). --spec subtract(integer(), integer()) -> integer(). -subtract(A, B) -> - A - B. - --file("src/gleam/int.gleam", 778). -?DOC( - " Calculates the bitwise AND of its arguments.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_and(integer(), integer()) -> integer(). -bitwise_and(X, Y) -> - erlang:'band'(X, Y). - --file("src/gleam/int.gleam", 788). -?DOC( - " Calculates the bitwise NOT of its argument.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_not(integer()) -> integer(). -bitwise_not(X) -> - erlang:'bnot'(X). - --file("src/gleam/int.gleam", 798). -?DOC( - " Calculates the bitwise OR of its arguments.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_or(integer(), integer()) -> integer(). -bitwise_or(X, Y) -> - erlang:'bor'(X, Y). - --file("src/gleam/int.gleam", 808). -?DOC( - " Calculates the bitwise XOR of its arguments.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_exclusive_or(integer(), integer()) -> integer(). -bitwise_exclusive_or(X, Y) -> - erlang:'bxor'(X, Y). - --file("src/gleam/int.gleam", 818). -?DOC( - " Calculates the result of an arithmetic left bitshift.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_shift_left(integer(), integer()) -> integer(). -bitwise_shift_left(X, Y) -> - erlang:'bsl'(X, Y). - --file("src/gleam/int.gleam", 828). -?DOC( - " Calculates the result of an arithmetic right bitshift.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_shift_right(integer(), integer()) -> integer(). -bitwise_shift_right(X, Y) -> - erlang:'bsr'(X, Y). diff --git a/build/dev/javascript/gleam_stdlib/gleam@io.erl b/build/dev/javascript/gleam_stdlib/gleam@io.erl deleted file mode 100644 index e60295e..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@io.erl +++ /dev/null @@ -1,80 +0,0 @@ --module(gleam@io). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/io.gleam"). --export([print/1, print_error/1, println/1, println_error/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/io.gleam", 15). -?DOC( - " Writes a string to standard output (stdout).\n" - "\n" - " If you want your output to be printed on its own line see `println`.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " io.print(\"Hi mum\")\n" - " // -> Nil\n" - " // Hi mum\n" - " ```\n" -). --spec print(binary()) -> nil. -print(String) -> - gleam_stdlib:print(String). - --file("src/gleam/io.gleam", 31). -?DOC( - " Writes a string to standard error (stderr).\n" - "\n" - " If you want your output to be printed on its own line see `println_error`.\n" - "\n" - " ## Example\n" - "\n" - " ```\n" - " io.print_error(\"Hi pop\")\n" - " // -> Nil\n" - " // Hi pop\n" - " ```\n" -). --spec print_error(binary()) -> nil. -print_error(String) -> - gleam_stdlib:print_error(String). - --file("src/gleam/io.gleam", 45). -?DOC( - " Writes a string to standard output (stdout), appending a newline to the end.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " io.println(\"Hi mum\")\n" - " // -> Nil\n" - " // Hi mum\n" - " ```\n" -). --spec println(binary()) -> nil. -println(String) -> - gleam_stdlib:println(String). - --file("src/gleam/io.gleam", 59). -?DOC( - " Writes a string to standard error (stderr), appending a newline to the end.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " io.println_error(\"Hi pop\")\n" - " // -> Nil\n" - " // Hi pop\n" - " ```\n" -). --spec println_error(binary()) -> nil. -println_error(String) -> - gleam_stdlib:println_error(String). diff --git a/build/dev/javascript/gleam_stdlib/gleam@list.erl b/build/dev/javascript/gleam_stdlib/gleam@list.erl deleted file mode 100644 index 0c96ecb..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@list.erl +++ /dev/null @@ -1,2873 +0,0 @@ --module(gleam@list). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/list.gleam"). --export([length/1, count/2, reverse/1, is_empty/1, contains/2, first/1, rest/1, group/2, filter/2, filter_map/2, map/2, map2/3, map_fold/3, index_map/2, try_map/2, drop/2, take/2, new/0, wrap/1, append/2, prepend/2, flatten/1, flat_map/2, fold/3, fold_right/3, index_fold/3, try_fold/3, fold_until/3, find/2, find_map/2, all/2, any/2, zip/2, strict_zip/2, unzip/1, intersperse/2, unique/1, sort/2, range/2, repeat/2, split/2, split_while/2, key_find/2, key_filter/2, key_pop/2, key_set/3, each/2, try_each/2, partition/2, window/2, window_by_2/1, drop_while/2, take_while/2, chunk/2, sized_chunk/2, reduce/2, scan/3, last/1, combinations/2, combination_pairs/1, transpose/1, interleave/1, shuffle/1, max/2, sample/2, permutations/1]). --export_type([continue_or_stop/1, sorting/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Lists are an ordered sequence of elements and are one of the most common\n" - " data types in Gleam.\n" - "\n" - " New elements can be added and removed from the front of a list in\n" - " constant time, while adding and removing from the end requires traversing\n" - " and copying the whole list, so keep this in mind when designing your\n" - " programs.\n" - "\n" - " There is a dedicated syntax for prefixing to a list:\n" - "\n" - " ```gleam\n" - " let new_list = [1, 2, ..existing_list]\n" - " ```\n" - "\n" - " And a matching syntax for getting the first elements of a list:\n" - "\n" - " ```gleam\n" - " case list {\n" - " [first_element, ..rest] -> first_element\n" - " _ -> \"this pattern matches when the list is empty\"\n" - " }\n" - " ```\n" - "\n" -). - --type continue_or_stop(XG) :: {continue, XG} | {stop, XG}. - --type sorting() :: ascending | descending. - --file("src/gleam/list.gleam", 60). --spec length_loop(list(any()), integer()) -> integer(). -length_loop(List, Count) -> - case List of - [_ | List@1] -> - length_loop(List@1, Count + 1); - - [] -> - Count - end. - --file("src/gleam/list.gleam", 56). -?DOC( - " Counts the number of elements in a given list.\n" - "\n" - " This function has to traverse the list to determine the number of elements,\n" - " so it runs in linear time.\n" - "\n" - " This function is natively implemented by the virtual machine and is highly\n" - " optimised.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " length([])\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " length([1])\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " length([1, 2])\n" - " // -> 2\n" - " ```\n" -). --spec length(list(any())) -> integer(). -length(List) -> - erlang:length(List). - --file("src/gleam/list.gleam", 93). --spec count_loop(list(XN), fun((XN) -> boolean()), integer()) -> integer(). -count_loop(List, Predicate, Acc) -> - case List of - [] -> - Acc; - - [First | Rest] -> - case Predicate(First) of - true -> - count_loop(Rest, Predicate, Acc + 1); - - false -> - count_loop(Rest, Predicate, Acc) - end - end. - --file("src/gleam/list.gleam", 89). -?DOC( - " Counts the number of elements in a given list satisfying a given predicate.\n" - "\n" - " This function has to traverse the list to determine the number of elements,\n" - " so it runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " count([], fn(a) { a > 0 })\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " count([1], fn(a) { a > 0 })\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " count([1, 2, 3], int.is_odd)\n" - " // -> 2\n" - " ```\n" -). --spec count(list(XL), fun((XL) -> boolean())) -> integer(). -count(List, Predicate) -> - count_loop(List, Predicate, 0). - --file("src/gleam/list.gleam", 131). -?DOC( - " Creates a new list from a given list containing the same elements but in the\n" - " opposite order.\n" - "\n" - " This function has to traverse the list to create the new reversed list, so\n" - " it runs in linear time.\n" - "\n" - " This function is natively implemented by the virtual machine and is highly\n" - " optimised.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " reverse([])\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " reverse([1])\n" - " // -> [1]\n" - " ```\n" - "\n" - " ```gleam\n" - " reverse([1, 2])\n" - " // -> [2, 1]\n" - " ```\n" -). --spec reverse(list(XP)) -> list(XP). -reverse(List) -> - lists:reverse(List). - --file("src/gleam/list.gleam", 168). -?DOC( - " Determines whether or not the list is empty.\n" - "\n" - " This function runs in constant time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_empty([])\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_empty([1])\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_empty([1, 1])\n" - " // -> False\n" - " ```\n" -). --spec is_empty(list(any())) -> boolean(). -is_empty(List) -> - List =:= []. - --file("src/gleam/list.gleam", 204). -?DOC( - " Determines whether or not a given element exists within a given list.\n" - "\n" - " This function traverses the list to find the element, so it runs in linear\n" - " time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [] |> contains(any: 0)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " [0] |> contains(any: 0)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " [1] |> contains(any: 0)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 1] |> contains(any: 0)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 0] |> contains(any: 0)\n" - " // -> True\n" - " ```\n" -). --spec contains(list(XY), XY) -> boolean(). -contains(List, Elem) -> - case List of - [] -> - false; - - [First | _] when First =:= Elem -> - true; - - [_ | Rest] -> - contains(Rest, Elem) - end. - --file("src/gleam/list.gleam", 231). -?DOC( - " Gets the first element from the start of the list, if there is one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " first([])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " first([0])\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " first([1, 2])\n" - " // -> Ok(1)\n" - " ```\n" -). --spec first(list(YA)) -> {ok, YA} | {error, nil}. -first(List) -> - case List of - [] -> - {error, nil}; - - [First | _] -> - {ok, First} - end. - --file("src/gleam/list.gleam", 260). -?DOC( - " Returns the list minus the first element. If the list is empty, `Error(Nil)` is\n" - " returned.\n" - "\n" - " This function runs in constant time and does not make a copy of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " rest([])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " rest([0])\n" - " // -> Ok([])\n" - " ```\n" - "\n" - " ```gleam\n" - " rest([1, 2])\n" - " // -> Ok([2])\n" - " ```\n" -). --spec rest(list(YE)) -> {ok, list(YE)} | {error, nil}. -rest(List) -> - case List of - [] -> - {error, nil}; - - [_ | Rest] -> - {ok, Rest} - end. - --file("src/gleam/list.gleam", 302). --spec group_loop(list(YP), fun((YP) -> YR), gleam@dict:dict(YR, list(YP))) -> gleam@dict:dict(YR, list(YP)). -group_loop(List, To_key, Groups) -> - case List of - [] -> - Groups; - - [First | Rest] -> - Key = To_key(First), - Groups@1 = case gleam_stdlib:map_get(Groups, Key) of - {error, _} -> - gleam@dict:insert(Groups, Key, [First]); - - {ok, Existing} -> - gleam@dict:insert(Groups, Key, [First | Existing]) - end, - group_loop(Rest, To_key, Groups@1) - end. - --file("src/gleam/list.gleam", 298). -?DOC( - " Groups the elements from the given list by the given key function.\n" - "\n" - " Does not preserve the initial value order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/dict\n" - "\n" - " [Ok(3), Error(\"Wrong\"), Ok(200), Ok(73)]\n" - " |> group(by: fn(i) {\n" - " case i {\n" - " Ok(_) -> \"Successful\"\n" - " Error(_) -> \"Failed\"\n" - " }\n" - " })\n" - " |> dict.to_list\n" - " // -> [\n" - " // #(\"Failed\", [Error(\"Wrong\")]),\n" - " // #(\"Successful\", [Ok(73), Ok(200), Ok(3)])\n" - " // ]\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/dict\n" - "\n" - " group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 })\n" - " |> dict.to_list\n" - " // -> [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])]\n" - " ```\n" -). --spec group(list(YJ), fun((YJ) -> YL)) -> gleam@dict:dict(YL, list(YJ)). -group(List, Key) -> - group_loop(List, Key, maps:new()). - --file("src/gleam/list.gleam", 339). --spec filter_loop(list(AAB), fun((AAB) -> boolean()), list(AAB)) -> list(AAB). -filter_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - New_acc = case Fun(First) of - true -> - [First | Acc]; - - false -> - Acc - end, - filter_loop(Rest, Fun, New_acc) - end. - --file("src/gleam/list.gleam", 335). -?DOC( - " Returns a new list containing only the elements from the first list for\n" - " which the given functions returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " filter([2, 4, 6, 1], fn(x) { x > 2 })\n" - " // -> [4, 6]\n" - " ```\n" - "\n" - " ```gleam\n" - " filter([2, 4, 6, 1], fn(x) { x > 6 })\n" - " // -> []\n" - " ```\n" -). --spec filter(list(YY), fun((YY) -> boolean())) -> list(YY). -filter(List, Predicate) -> - filter_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 371). --spec filter_map_loop( - list(AAM), - fun((AAM) -> {ok, AAO} | {error, any()}), - list(AAO) -) -> list(AAO). -filter_map_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - New_acc = case Fun(First) of - {ok, First@1} -> - [First@1 | Acc]; - - {error, _} -> - Acc - end, - filter_map_loop(Rest, Fun, New_acc) - end. - --file("src/gleam/list.gleam", 367). -?DOC( - " Returns a new list containing only the elements from the first list for\n" - " which the given functions returns `Ok(_)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " filter_map([2, 4, 6, 1], Error)\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) })\n" - " // -> [3, 5, 7, 2]\n" - " ```\n" -). --spec filter_map(list(AAF), fun((AAF) -> {ok, AAH} | {error, any()})) -> list(AAH). -filter_map(List, Fun) -> - filter_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 402). --spec map_loop(list(AAY), fun((AAY) -> ABA), list(ABA)) -> list(ABA). -map_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - map_loop(Rest, Fun, [Fun(First) | Acc]) - end. - --file("src/gleam/list.gleam", 398). -?DOC( - " Returns a new list containing only the elements of the first list after the\n" - " function has been applied to each one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map([2, 4, 6], fn(x) { x * 2 })\n" - " // -> [4, 8, 12]\n" - " ```\n" -). --spec map(list(AAU), fun((AAU) -> AAW)) -> list(AAW). -map(List, Fun) -> - map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 429). --spec map2_loop(list(ABJ), list(ABL), fun((ABJ, ABL) -> ABN), list(ABN)) -> list(ABN). -map2_loop(List1, List2, Fun, Acc) -> - case {List1, List2} of - {[], _} -> - lists:reverse(Acc); - - {_, []} -> - lists:reverse(Acc); - - {[A | As_], [B | Bs]} -> - map2_loop(As_, Bs, Fun, [Fun(A, B) | Acc]) - end. - --file("src/gleam/list.gleam", 425). -?DOC( - " Combines two lists into a single list using the given function.\n" - "\n" - " If a list is longer than the other the extra elements are dropped.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y })\n" - " // -> [5, 7, 9]\n" - " ```\n" - "\n" - " ```gleam\n" - " map2([1, 2], [\"a\", \"b\", \"c\"], fn(i, x) { #(i, x) })\n" - " // -> [#(1, \"a\"), #(2, \"b\")]\n" - " ```\n" -). --spec map2(list(ABD), list(ABF), fun((ABD, ABF) -> ABH)) -> list(ABH). -map2(List1, List2, Fun) -> - map2_loop(List1, List2, Fun, []). - --file("src/gleam/list.gleam", 462). --spec map_fold_loop(list(ABV), fun((ABX, ABV) -> {ABX, ABY}), ABX, list(ABY)) -> {ABX, - list(ABY)}. -map_fold_loop(List, Fun, Acc, List_acc) -> - case List of - [] -> - {Acc, lists:reverse(List_acc)}; - - [First | Rest] -> - {Acc@1, First@1} = Fun(Acc, First), - map_fold_loop(Rest, Fun, Acc@1, [First@1 | List_acc]) - end. - --file("src/gleam/list.gleam", 454). -?DOC( - " Similar to `map` but also lets you pass around an accumulated value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map_fold(\n" - " over: [1, 2, 3],\n" - " from: 100,\n" - " with: fn(memo, i) { #(memo + i, i * 2) }\n" - " )\n" - " // -> #(106, [2, 4, 6])\n" - " ```\n" -). --spec map_fold(list(ABQ), ABS, fun((ABS, ABQ) -> {ABS, ABT})) -> {ABS, - list(ABT)}. -map_fold(List, Initial, Fun) -> - map_fold_loop(List, Fun, Initial, []). - --file("src/gleam/list.gleam", 494). --spec index_map_loop( - list(ACF), - fun((ACF, integer()) -> ACH), - integer(), - list(ACH) -) -> list(ACH). -index_map_loop(List, Fun, Index, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - Acc@1 = [Fun(First, Index) | Acc], - index_map_loop(Rest, Fun, Index + 1, Acc@1) - end. - --file("src/gleam/list.gleam", 490). -?DOC( - " Returns a new list containing only the elements of the first list after the\n" - " function has been applied to each one and their index.\n" - "\n" - " The index starts at 0, so the first element is 0, the second is 1, and so\n" - " on.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " index_map([\"a\", \"b\"], fn(x, i) { #(i, x) })\n" - " // -> [#(0, \"a\"), #(1, \"b\")]\n" - " ```\n" -). --spec index_map(list(ACB), fun((ACB, integer()) -> ACD)) -> list(ACD). -index_map(List, Fun) -> - index_map_loop(List, Fun, 0, []). - --file("src/gleam/list.gleam", 548). --spec try_map_loop(list(ACT), fun((ACT) -> {ok, ACV} | {error, ACW}), list(ACV)) -> {ok, - list(ACV)} | - {error, ACW}. -try_map_loop(List, Fun, Acc) -> - case List of - [] -> - {ok, lists:reverse(Acc)}; - - [First | Rest] -> - case Fun(First) of - {ok, First@1} -> - try_map_loop(Rest, Fun, [First@1 | Acc]); - - {error, Error} -> - {error, Error} - end - end. - --file("src/gleam/list.gleam", 541). -?DOC( - " Takes a function that returns a `Result` and applies it to each element in a\n" - " given list in turn.\n" - "\n" - " If the function returns `Ok(new_value)` for all elements in the list then a\n" - " list of the new values is returned.\n" - "\n" - " If the function returns `Error(reason)` for any of the elements then it is\n" - " returned immediately. None of the elements in the list are processed after\n" - " one returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " try_map([1, 2, 3], fn(x) { Ok(x + 2) })\n" - " // -> Ok([3, 4, 5])\n" - " ```\n" - "\n" - " ```gleam\n" - " try_map([1, 2, 3], fn(_) { Error(0) })\n" - " // -> Error(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " try_map([[1], [2, 3]], first)\n" - " // -> Ok([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " try_map([[1], [], [2]], first)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec try_map(list(ACK), fun((ACK) -> {ok, ACM} | {error, ACN})) -> {ok, - list(ACM)} | - {error, ACN}. -try_map(List, Fun) -> - try_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 583). -?DOC( - " Returns a list that is the given list with up to the given number of\n" - " elements removed from the front of the list.\n" - "\n" - " If the element has less than the number of elements an empty list is\n" - " returned.\n" - "\n" - " This function runs in linear time but does not copy the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop([1, 2, 3, 4], 2)\n" - " // -> [3, 4]\n" - " ```\n" - "\n" - " ```gleam\n" - " drop([1, 2, 3, 4], 9)\n" - " // -> []\n" - " ```\n" -). --spec drop(list(ADD), integer()) -> list(ADD). -drop(List, N) -> - case N =< 0 of - true -> - List; - - false -> - case List of - [] -> - []; - - [_ | Rest] -> - drop(Rest, N - 1) - end - end. - --file("src/gleam/list.gleam", 618). --spec take_loop(list(ADJ), integer(), list(ADJ)) -> list(ADJ). -take_loop(List, N, Acc) -> - case N =< 0 of - true -> - lists:reverse(Acc); - - false -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - take_loop(Rest, N - 1, [First | Acc]) - end - end. - --file("src/gleam/list.gleam", 614). -?DOC( - " Returns a list containing the first given number of elements from the given\n" - " list.\n" - "\n" - " If the element has less than the number of elements then the full list is\n" - " returned.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " take([1, 2, 3, 4], 2)\n" - " // -> [1, 2]\n" - " ```\n" - "\n" - " ```gleam\n" - " take([1, 2, 3, 4], 9)\n" - " // -> [1, 2, 3, 4]\n" - " ```\n" -). --spec take(list(ADG), integer()) -> list(ADG). -take(List, N) -> - take_loop(List, N, []). - --file("src/gleam/list.gleam", 638). -?DOC( - " Returns a new empty list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " // -> []\n" - " ```\n" -). --spec new() -> list(any()). -new() -> - []. - --file("src/gleam/list.gleam", 658). -?DOC( - " Returns the given item wrapped in a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " wrap(1)\n" - " // -> [1]\n" - "\n" - " wrap([\"a\", \"b\", \"c\"])\n" - " // -> [[\"a\", \"b\", \"c\"]]\n" - "\n" - " wrap([[]])\n" - " // -> [[[]]]\n" - " ```\n" -). --spec wrap(ADP) -> list(ADP). -wrap(Item) -> - [Item]. - --file("src/gleam/list.gleam", 679). --spec append_loop(list(ADV), list(ADV)) -> list(ADV). -append_loop(First, Second) -> - case First of - [] -> - Second; - - [First@1 | Rest] -> - append_loop(Rest, [First@1 | Second]) - end. - --file("src/gleam/list.gleam", 675). -?DOC( - " Joins one list onto the end of another.\n" - "\n" - " This function runs in linear time, and it traverses and copies the first\n" - " list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " append([1, 2], [3])\n" - " // -> [1, 2, 3]\n" - " ```\n" -). --spec append(list(ADR), list(ADR)) -> list(ADR). -append(First, Second) -> - lists:append(First, Second). - --file("src/gleam/list.gleam", 699). -?DOC( - " Prefixes an item to a list. This can also be done using the dedicated\n" - " syntax instead\n" - "\n" - " ```gleam\n" - " let existing_list = [2, 3, 4]\n" - "\n" - " [1, ..existing_list]\n" - " // -> [1, 2, 3, 4]\n" - "\n" - " prepend(to: existing_list, this: 1)\n" - " // -> [1, 2, 3, 4]\n" - " ```\n" -). --spec prepend(list(ADZ), ADZ) -> list(ADZ). -prepend(List, Item) -> - [Item | List]. - --file("src/gleam/list.gleam", 720). --spec flatten_loop(list(list(AEG)), list(AEG)) -> list(AEG). -flatten_loop(Lists, Acc) -> - case Lists of - [] -> - lists:reverse(Acc); - - [List | Further_lists] -> - flatten_loop(Further_lists, lists:reverse(List, Acc)) - end. - --file("src/gleam/list.gleam", 716). -?DOC( - " Joins a list of lists into a single list.\n" - "\n" - " This function traverses all elements twice on the JavaScript target.\n" - " This function traverses all elements once on the Erlang target.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flatten([[1], [2, 3], []])\n" - " // -> [1, 2, 3]\n" - " ```\n" -). --spec flatten(list(list(AEC))) -> list(AEC). -flatten(Lists) -> - lists:append(Lists). - --file("src/gleam/list.gleam", 737). -?DOC( - " Maps the list with the given function into a list of lists, and then flattens it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flat_map([2, 4, 6], fn(x) { [x, x + 1] })\n" - " // -> [2, 3, 4, 5, 6, 7]\n" - " ```\n" -). --spec flat_map(list(AEL), fun((AEL) -> list(AEN))) -> list(AEN). -flat_map(List, Fun) -> - lists:append(map(List, Fun)). - --file("src/gleam/list.gleam", 749). -?DOC( - " Reduces a list of elements into a single value by calling a given function\n" - " on each element, going from left to right.\n" - "\n" - " `fold([1, 2, 3], 0, add)` is the equivalent of\n" - " `add(add(add(0, 1), 2), 3)`.\n" - "\n" - " This function runs in linear time.\n" -). --spec fold(list(AEQ), AES, fun((AES, AEQ) -> AES)) -> AES. -fold(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - fold(Rest, Fun(Initial, First), Fun) - end. - --file("src/gleam/list.gleam", 771). -?DOC( - " Reduces a list of elements into a single value by calling a given function\n" - " on each element, going from right to left.\n" - "\n" - " `fold_right([1, 2, 3], 0, add)` is the equivalent of\n" - " `add(add(add(0, 3), 2), 1)`.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " Unlike `fold` this function is not tail recursive. Where possible use\n" - " `fold` instead as it will use less memory.\n" -). --spec fold_right(list(AET), AEV, fun((AEV, AET) -> AEV)) -> AEV. -fold_right(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - Fun(fold_right(Rest, Initial, Fun), First) - end. - --file("src/gleam/list.gleam", 808). --spec index_fold_loop( - list(AEZ), - AFB, - fun((AFB, AEZ, integer()) -> AFB), - integer() -) -> AFB. -index_fold_loop(Over, Acc, With, Index) -> - case Over of - [] -> - Acc; - - [First | Rest] -> - index_fold_loop(Rest, With(Acc, First, Index), With, Index + 1) - end. - --file("src/gleam/list.gleam", 800). -?DOC( - " Like fold but the folding function also receives the index of the current element.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [\"a\", \"b\", \"c\"]\n" - " |> index_fold(\"\", fn(acc, item, index) {\n" - " acc <> int.to_string(index) <> \":\" <> item <> \" \"\n" - " })\n" - " // -> \"0:a 1:b 2:c\"\n" - " ```\n" - "\n" - " ```gleam\n" - " [10, 20, 30]\n" - " |> index_fold(0, fn(acc, item, index) { acc + item * index })\n" - " // -> 80\n" - " ```\n" -). --spec index_fold(list(AEW), AEY, fun((AEY, AEW, integer()) -> AEY)) -> AEY. -index_fold(List, Initial, Fun) -> - index_fold_loop(List, Initial, Fun, 0). - --file("src/gleam/list.gleam", 840). -?DOC( - " A variant of fold that might fail.\n" - "\n" - " The folding function should return `Result(accumulator, error)`.\n" - " If the returned value is `Ok(accumulator)` try_fold will try the next value in the list.\n" - " If the returned value is `Error(error)` try_fold will stop and return that error.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4]\n" - " |> try_fold(0, fn(acc, i) {\n" - " case i < 3 {\n" - " True -> Ok(acc + i)\n" - " False -> Error(Nil)\n" - " }\n" - " })\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec try_fold(list(AFC), AFE, fun((AFE, AFC) -> {ok, AFE} | {error, AFF})) -> {ok, - AFE} | - {error, AFF}. -try_fold(List, Initial, Fun) -> - case List of - [] -> - {ok, Initial}; - - [First | Rest] -> - case Fun(Initial, First) of - {ok, Result} -> - try_fold(Rest, Result, Fun); - - {error, _} = Error -> - Error - end - end. - --file("src/gleam/list.gleam", 879). -?DOC( - " A variant of fold that allows to stop folding earlier.\n" - "\n" - " The folding function should return `ContinueOrStop(accumulator)`.\n" - " If the returned value is `Continue(accumulator)` fold_until will try the next value in the list.\n" - " If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4]\n" - " |> fold_until(0, fn(acc, i) {\n" - " case i < 3 {\n" - " True -> Continue(acc + i)\n" - " False -> Stop(acc)\n" - " }\n" - " })\n" - " // -> 3\n" - " ```\n" -). --spec fold_until(list(AFK), AFM, fun((AFM, AFK) -> continue_or_stop(AFM))) -> AFM. -fold_until(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - case Fun(Initial, First) of - {continue, Next_accumulator} -> - fold_until(Rest, Next_accumulator, Fun); - - {stop, B} -> - B - end - end. - --file("src/gleam/list.gleam", 916). -?DOC( - " Finds the first element in a given list for which the given function returns\n" - " `True`.\n" - "\n" - " Returns `Error(Nil)` if no such element is found.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " find([1, 2, 3], fn(x) { x > 2 })\n" - " // -> Ok(3)\n" - " ```\n" - "\n" - " ```gleam\n" - " find([1, 2, 3], fn(x) { x > 4 })\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " find([], fn(_) { True })\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec find(list(AFO), fun((AFO) -> boolean())) -> {ok, AFO} | {error, nil}. -find(List, Is_desired) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - case Is_desired(First) of - true -> - {ok, First}; - - false -> - find(Rest, Is_desired) - end - end. - --file("src/gleam/list.gleam", 952). -?DOC( - " Finds the first element in a given list for which the given function returns\n" - " `Ok(new_value)`, then returns the wrapped `new_value`.\n" - "\n" - " Returns `Error(Nil)` if no such element is found.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " find_map([[], [2], [3]], first)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " find_map([[], []], first)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " find_map([], first)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec find_map(list(AFS), fun((AFS) -> {ok, AFU} | {error, any()})) -> {ok, AFU} | - {error, nil}. -find_map(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - case Fun(First) of - {ok, First@1} -> - {ok, First@1}; - - {error, _} -> - find_map(Rest, Fun) - end - end. - --file("src/gleam/list.gleam", 987). -?DOC( - " Returns `True` if the given function returns `True` for all the elements in\n" - " the given list. If the function returns `False` for any of the elements it\n" - " immediately returns `False` without checking the rest of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " all([], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " all([4, 5], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " all([4, 3], fn(x) { x > 3 })\n" - " // -> False\n" - " ```\n" -). --spec all(list(AGA), fun((AGA) -> boolean())) -> boolean(). -all(List, Predicate) -> - case List of - [] -> - true; - - [First | Rest] -> - case Predicate(First) of - true -> - all(Rest, Predicate); - - false -> - false - end - end. - --file("src/gleam/list.gleam", 1024). -?DOC( - " Returns `True` if the given function returns `True` for any the elements in\n" - " the given list. If the function returns `True` for any of the elements it\n" - " immediately returns `True` without checking the rest of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " any([], fn(x) { x > 3 })\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " any([4, 5], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " any([4, 3], fn(x) { x > 4 })\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " any([3, 4], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" -). --spec any(list(AGC), fun((AGC) -> boolean())) -> boolean(). -any(List, Predicate) -> - case List of - [] -> - false; - - [First | Rest] -> - case Predicate(First) of - true -> - true; - - false -> - any(Rest, Predicate) - end - end. - --file("src/gleam/list.gleam", 1066). --spec zip_loop(list(AGJ), list(AGL), list({AGJ, AGL})) -> list({AGJ, AGL}). -zip_loop(One, Other, Acc) -> - case {One, Other} of - {[First_one | Rest_one], [First_other | Rest_other]} -> - zip_loop(Rest_one, Rest_other, [{First_one, First_other} | Acc]); - - {_, _} -> - lists:reverse(Acc) - end. - --file("src/gleam/list.gleam", 1062). -?DOC( - " Takes two lists and returns a single list of 2-element tuples.\n" - "\n" - " If one of the lists is longer than the other, the remaining elements from\n" - " the longer list are not used.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " zip([], [])\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " zip([1, 2], [3])\n" - " // -> [#(1, 3)]\n" - " ```\n" - "\n" - " ```gleam\n" - " zip([1], [3, 4])\n" - " // -> [#(1, 3)]\n" - " ```\n" - "\n" - " ```gleam\n" - " zip([1, 2], [3, 4])\n" - " // -> [#(1, 3), #(2, 4)]\n" - " ```\n" -). --spec zip(list(AGE), list(AGG)) -> list({AGE, AGG}). -zip(List, Other) -> - zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1107). --spec strict_zip_loop(list(AGW), list(AGY), list({AGW, AGY})) -> {ok, - list({AGW, AGY})} | - {error, nil}. -strict_zip_loop(One, Other, Acc) -> - case {One, Other} of - {[], []} -> - {ok, lists:reverse(Acc)}; - - {[], _} -> - {error, nil}; - - {_, []} -> - {error, nil}; - - {[First_one | Rest_one], [First_other | Rest_other]} -> - strict_zip_loop( - Rest_one, - Rest_other, - [{First_one, First_other} | Acc] - ) - end. - --file("src/gleam/list.gleam", 1100). -?DOC( - " Takes two lists and returns a single list of 2-element tuples.\n" - "\n" - " If one of the lists is longer than the other, an `Error` is returned.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " strict_zip([], [])\n" - " // -> Ok([])\n" - " ```\n" - "\n" - " ```gleam\n" - " strict_zip([1, 2], [3])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " strict_zip([1], [3, 4])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " strict_zip([1, 2], [3, 4])\n" - " // -> Ok([#(1, 3), #(2, 4)])\n" - " ```\n" -). --spec strict_zip(list(AGP), list(AGR)) -> {ok, list({AGP, AGR})} | {error, nil}. -strict_zip(List, Other) -> - strict_zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1138). --spec unzip_loop(list({AHJ, AHK}), list(AHJ), list(AHK)) -> {list(AHJ), - list(AHK)}. -unzip_loop(Input, One, Other) -> - case Input of - [] -> - {lists:reverse(One), lists:reverse(Other)}; - - [{First_one, First_other} | Rest] -> - unzip_loop(Rest, [First_one | One], [First_other | Other]) - end. - --file("src/gleam/list.gleam", 1134). -?DOC( - " Takes a single list of 2-element tuples and returns two lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unzip([#(1, 2), #(3, 4)])\n" - " // -> #([1, 3], [2, 4])\n" - " ```\n" - "\n" - " ```gleam\n" - " unzip([])\n" - " // -> #([], [])\n" - " ```\n" -). --spec unzip(list({AHE, AHF})) -> {list(AHE), list(AHF)}. -unzip(Input) -> - unzip_loop(Input, [], []). - --file("src/gleam/list.gleam", 1173). --spec intersperse_loop(list(AHT), AHT, list(AHT)) -> list(AHT). -intersperse_loop(List, Separator, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - intersperse_loop(Rest, Separator, [First, Separator | Acc]) - end. - --file("src/gleam/list.gleam", 1166). -?DOC( - " Inserts a given value between each existing element in a given list.\n" - "\n" - " This function runs in linear time and copies the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " intersperse([1, 1, 1], 2)\n" - " // -> [1, 2, 1, 2, 1]\n" - " ```\n" - "\n" - " ```gleam\n" - " intersperse([], 2)\n" - " // -> []\n" - " ```\n" -). --spec intersperse(list(AHQ), AHQ) -> list(AHQ). -intersperse(List, Elem) -> - case List of - [] -> - List; - - [_] -> - List; - - [First | Rest] -> - intersperse_loop(Rest, Elem, [First]) - end. - --file("src/gleam/list.gleam", 1196). --spec unique_loop(list(AIA), gleam@dict:dict(AIA, nil), list(AIA)) -> list(AIA). -unique_loop(List, Seen, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - case gleam@dict:has_key(Seen, First) of - true -> - unique_loop(Rest, Seen, Acc); - - false -> - unique_loop( - Rest, - gleam@dict:insert(Seen, First, nil), - [First | Acc] - ) - end - end. - --file("src/gleam/list.gleam", 1192). -?DOC( - " Removes any duplicate elements from a given list.\n" - "\n" - " This function returns in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unique([1, 1, 1, 4, 7, 3, 3, 4])\n" - " // -> [1, 4, 7, 3]\n" - " ```\n" -). --spec unique(list(AHX)) -> list(AHX). -unique(List) -> - unique_loop(List, maps:new(), []). - --file("src/gleam/list.gleam", 1282). -?DOC( - " Given a list it returns slices of it that are locally sorted in ascending\n" - " order.\n" - "\n" - " Imagine you have this list:\n" - "\n" - " ```\n" - " [1, 2, 3, 2, 1, 0]\n" - " ^^^^^^^ ^^^^^^^ This is a slice in descending order\n" - " |\n" - " | This is a slice that is sorted in ascending order\n" - " ```\n" - "\n" - " So the produced result will contain these two slices, each one sorted in\n" - " ascending order: `[[1, 2, 3], [0, 1, 2]]`.\n" - "\n" - " - `growing` is an accumulator with the current slice being grown\n" - " - `direction` is the growing direction of the slice being grown, it could\n" - " either be ascending or strictly descending\n" - " - `prev` is the previous element that needs to be added to the growing slice\n" - " it is carried around to check whether we have to keep growing the current\n" - " slice or not\n" - " - `acc` is the accumulator containing the slices sorted in ascending order\n" -). --spec sequences( - list(AIJ), - fun((AIJ, AIJ) -> gleam@order:order()), - list(AIJ), - sorting(), - AIJ, - list(list(AIJ)) -) -> list(list(AIJ)). -sequences(List, Compare, Growing, Direction, Prev, Acc) -> - Growing@1 = [Prev | Growing], - case List of - [] -> - case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end; - - [New | Rest] -> - case {Compare(Prev, New), Direction} of - {gt, descending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {lt, ascending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {eq, ascending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {gt, ascending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end; - - {lt, descending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end; - - {eq, descending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end - end - end. - --file("src/gleam/list.gleam", 1430). -?DOC( - " Merges two lists sorted in ascending order into a single list sorted in\n" - " descending order according to the given comparator function.\n" - "\n" - " This reversing of the sort order is not avoidable if we want to implement\n" - " merge as a tail recursive function. We could reverse the accumulator before\n" - " returning it but that would end up being less efficient; so the merging\n" - " algorithm has to play around this.\n" -). --spec merge_ascendings( - list(AJG), - list(AJG), - fun((AJG, AJG) -> gleam@order:order()), - list(AJG) -) -> list(AJG). -merge_ascendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - lists:reverse(List, Acc); - - {List, []} -> - lists:reverse(List, Acc); - - {[First1 | Rest1], [First2 | Rest2]} -> - case Compare(First1, First2) of - lt -> - merge_ascendings(Rest1, List2, Compare, [First1 | Acc]); - - gt -> - merge_ascendings(List1, Rest2, Compare, [First2 | Acc]); - - eq -> - merge_ascendings(List1, Rest2, Compare, [First2 | Acc]) - end - end. - --file("src/gleam/list.gleam", 1383). -?DOC( - " Given a list of ascending lists, it merges adjacent pairs into a single\n" - " descending list, halving their number.\n" - " It returns a list of the remaining descending lists.\n" -). --spec merge_ascending_pairs( - list(list(AIU)), - fun((AIU, AIU) -> gleam@order:order()), - list(list(AIU)) -) -> list(list(AIU)). -merge_ascending_pairs(Sequences, Compare, Acc) -> - case Sequences of - [] -> - lists:reverse(Acc); - - [Sequence] -> - lists:reverse([lists:reverse(Sequence) | Acc]); - - [Ascending1, Ascending2 | Rest] -> - Descending = merge_ascendings(Ascending1, Ascending2, Compare, []), - merge_ascending_pairs(Rest, Compare, [Descending | Acc]) - end. - --file("src/gleam/list.gleam", 1457). -?DOC( - " This is exactly the same as merge_ascendings but mirrored: it merges two\n" - " lists sorted in descending order into a single list sorted in ascending\n" - " order according to the given comparator function.\n" - "\n" - " This reversing of the sort order is not avoidable if we want to implement\n" - " merge as a tail recursive function. We could reverse the accumulator before\n" - " returning it but that would end up being less efficient; so the merging\n" - " algorithm has to play around this.\n" -). --spec merge_descendings( - list(AJL), - list(AJL), - fun((AJL, AJL) -> gleam@order:order()), - list(AJL) -) -> list(AJL). -merge_descendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - lists:reverse(List, Acc); - - {List, []} -> - lists:reverse(List, Acc); - - {[First1 | Rest1], [First2 | Rest2]} -> - case Compare(First1, First2) of - lt -> - merge_descendings(List1, Rest2, Compare, [First2 | Acc]); - - gt -> - merge_descendings(Rest1, List2, Compare, [First1 | Acc]); - - eq -> - merge_descendings(Rest1, List2, Compare, [First1 | Acc]) - end - end. - --file("src/gleam/list.gleam", 1405). -?DOC(" This is the same as merge_ascending_pairs but flipped for descending lists.\n"). --spec merge_descending_pairs( - list(list(AJA)), - fun((AJA, AJA) -> gleam@order:order()), - list(list(AJA)) -) -> list(list(AJA)). -merge_descending_pairs(Sequences, Compare, Acc) -> - case Sequences of - [] -> - lists:reverse(Acc); - - [Sequence] -> - lists:reverse([lists:reverse(Sequence) | Acc]); - - [Descending1, Descending2 | Rest] -> - Ascending = merge_descendings(Descending1, Descending2, Compare, []), - merge_descending_pairs(Rest, Compare, [Ascending | Acc]) - end. - --file("src/gleam/list.gleam", 1349). -?DOC( - " Given some some sorted sequences (assumed to be sorted in `direction`) it\n" - " merges them all together until we're left with just a list sorted in\n" - " ascending order.\n" -). --spec merge_all( - list(list(AIQ)), - sorting(), - fun((AIQ, AIQ) -> gleam@order:order()) -) -> list(AIQ). -merge_all(Sequences, Direction, Compare) -> - case {Sequences, Direction} of - {[], _} -> - []; - - {[Sequence], ascending} -> - Sequence; - - {[Sequence@1], descending} -> - lists:reverse(Sequence@1); - - {_, ascending} -> - Sequences@1 = merge_ascending_pairs(Sequences, Compare, []), - merge_all(Sequences@1, descending, Compare); - - {_, descending} -> - Sequences@2 = merge_descending_pairs(Sequences, Compare, []), - merge_all(Sequences@2, ascending, Compare) - end. - --file("src/gleam/list.gleam", 1220). -?DOC( - " Sorts from smallest to largest based upon the ordering specified by a given\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " sort([4, 3, 6, 5, 4, 1, 2], by: int.compare)\n" - " // -> [1, 2, 3, 4, 4, 5, 6]\n" - " ```\n" -). --spec sort(list(AIG), fun((AIG, AIG) -> gleam@order:order())) -> list(AIG). -sort(List, Compare) -> - case List of - [] -> - []; - - [X] -> - [X]; - - [X@1, Y | Rest] -> - Direction = case Compare(X@1, Y) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - Sequences = sequences(Rest, Compare, [X@1], Direction, Y, []), - merge_all(Sequences, ascending, Compare) - end. - --file("src/gleam/list.gleam", 1497). --spec range_loop(integer(), integer(), list(integer())) -> list(integer()). -range_loop(Start, Stop, Acc) -> - case gleam@int:compare(Start, Stop) of - eq -> - [Stop | Acc]; - - gt -> - range_loop(Start, Stop + 1, [Stop | Acc]); - - lt -> - range_loop(Start, Stop - 1, [Stop | Acc]) - end. - --file("src/gleam/list.gleam", 1493). -?DOC( - " Creates a list of ints ranging from a given start and finish.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " range(0, 0)\n" - " // -> [0]\n" - " ```\n" - "\n" - " ```gleam\n" - " range(0, 5)\n" - " // -> [0, 1, 2, 3, 4, 5]\n" - " ```\n" - "\n" - " ```gleam\n" - " range(1, -5)\n" - " // -> [1, 0, -1, -2, -3, -4, -5]\n" - " ```\n" -). --spec range(integer(), integer()) -> list(integer()). -range(Start, Stop) -> - range_loop(Start, Stop, []). - --file("src/gleam/list.gleam", 1523). --spec repeat_loop(AJV, integer(), list(AJV)) -> list(AJV). -repeat_loop(Item, Times, Acc) -> - case Times =< 0 of - true -> - Acc; - - false -> - repeat_loop(Item, Times - 1, [Item | Acc]) - end. - --file("src/gleam/list.gleam", 1519). -?DOC( - " Builds a list of a given value a given number of times.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " repeat(\"a\", times: 0)\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " repeat(\"a\", times: 5)\n" - " // -> [\"a\", \"a\", \"a\", \"a\", \"a\"]\n" - " ```\n" -). --spec repeat(AJT, integer()) -> list(AJT). -repeat(A, Times) -> - repeat_loop(A, Times, []). - --file("src/gleam/list.gleam", 1556). --spec split_loop(list(AKC), integer(), list(AKC)) -> {list(AKC), list(AKC)}. -split_loop(List, N, Taken) -> - case N =< 0 of - true -> - {lists:reverse(Taken), List}; - - false -> - case List of - [] -> - {lists:reverse(Taken), []}; - - [First | Rest] -> - split_loop(Rest, N - 1, [First | Taken]) - end - end. - --file("src/gleam/list.gleam", 1552). -?DOC( - " Splits a list in two before the given index.\n" - "\n" - " If the list is not long enough to have the given index the before list will\n" - " be the input list, and the after list will be empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split([6, 7, 8, 9], 0)\n" - " // -> #([], [6, 7, 8, 9])\n" - " ```\n" - "\n" - " ```gleam\n" - " split([6, 7, 8, 9], 2)\n" - " // -> #([6, 7], [8, 9])\n" - " ```\n" - "\n" - " ```gleam\n" - " split([6, 7, 8, 9], 4)\n" - " // -> #([6, 7, 8, 9], [])\n" - " ```\n" -). --spec split(list(AJY), integer()) -> {list(AJY), list(AJY)}. -split(List, Index) -> - split_loop(List, Index, []). - --file("src/gleam/list.gleam", 1592). --spec split_while_loop(list(AKL), fun((AKL) -> boolean()), list(AKL)) -> {list(AKL), - list(AKL)}. -split_while_loop(List, F, Acc) -> - case List of - [] -> - {lists:reverse(Acc), []}; - - [First | Rest] -> - case F(First) of - true -> - split_while_loop(Rest, F, [First | Acc]); - - false -> - {lists:reverse(Acc), List} - end - end. - --file("src/gleam/list.gleam", 1585). -?DOC( - " Splits a list in two before the first element that a given function returns\n" - " `False` for.\n" - "\n" - " If the function returns `True` for all elements the first list will be the\n" - " input list, and the second list will be empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 })\n" - " // -> #([1, 2, 3], [4, 5])\n" - " ```\n" - "\n" - " ```gleam\n" - " split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 })\n" - " // -> #([1, 2, 3, 4, 5], [])\n" - " ```\n" -). --spec split_while(list(AKH), fun((AKH) -> boolean())) -> {list(AKH), list(AKH)}. -split_while(List, Predicate) -> - split_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1632). -?DOC( - " Given a list of 2-element tuples, finds the first tuple that has a given\n" - " key as the first element and returns the second element.\n" - "\n" - " If no tuple is found with the given key then `Error(Nil)` is returned.\n" - "\n" - " This function may be useful for interacting with Erlang code where lists of\n" - " tuples are common.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_find([#(\"a\", 0), #(\"b\", 1)], \"a\")\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " key_find([#(\"a\", 0), #(\"b\", 1)], \"b\")\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " key_find([#(\"a\", 0), #(\"b\", 1)], \"c\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec key_find(list({AKQ, AKR}), AKQ) -> {ok, AKR} | {error, nil}. -key_find(Keyword_list, Desired_key) -> - find_map( - Keyword_list, - fun(Keyword) -> - {Key, Value} = Keyword, - case Key =:= Desired_key of - true -> - {ok, Value}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/list.gleam", 1663). -?DOC( - " Given a list of 2-element tuples, finds all tuples that have a given\n" - " key as the first element and returns the second element.\n" - "\n" - " This function may be useful for interacting with Erlang code where lists of\n" - " tuples are common.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_filter([#(\"a\", 0), #(\"b\", 1), #(\"a\", 2)], \"a\")\n" - " // -> [0, 2]\n" - " ```\n" - "\n" - " ```gleam\n" - " key_filter([#(\"a\", 0), #(\"b\", 1)], \"c\")\n" - " // -> []\n" - " ```\n" -). --spec key_filter(list({AKV, AKW}), AKV) -> list(AKW). -key_filter(Keyword_list, Desired_key) -> - filter_map( - Keyword_list, - fun(Keyword) -> - {Key, Value} = Keyword, - case Key =:= Desired_key of - true -> - {ok, Value}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/list.gleam", 1703). --spec key_pop_loop(list({ALF, ALG}), ALF, list({ALF, ALG})) -> {ok, - {ALG, list({ALF, ALG})}} | - {error, nil}. -key_pop_loop(List, Key, Checked) -> - case List of - [] -> - {error, nil}; - - [{K, V} | Rest] when K =:= Key -> - {ok, {V, lists:reverse(Checked, Rest)}}; - - [First | Rest@1] -> - key_pop_loop(Rest@1, Key, [First | Checked]) - end. - --file("src/gleam/list.gleam", 1699). -?DOC( - " Given a list of 2-element tuples, finds the first tuple that has a given\n" - " key as the first element. This function will return the second element\n" - " of the found tuple and list with tuple removed.\n" - "\n" - " If no tuple is found with the given key then `Error(Nil)` is returned.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_pop([#(\"a\", 0), #(\"b\", 1)], \"a\")\n" - " // -> Ok(#(0, [#(\"b\", 1)]))\n" - " ```\n" - "\n" - " ```gleam\n" - " key_pop([#(\"a\", 0), #(\"b\", 1)], \"b\")\n" - " // -> Ok(#(1, [#(\"a\", 0)]))\n" - " ```\n" - "\n" - " ```gleam\n" - " key_pop([#(\"a\", 0), #(\"b\", 1)], \"c\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec key_pop(list({AKZ, ALA}), AKZ) -> {ok, {ALA, list({AKZ, ALA})}} | - {error, nil}. -key_pop(List, Key) -> - key_pop_loop(List, Key, []). - --file("src/gleam/list.gleam", 1737). --spec key_set_loop(list({ALQ, ALR}), ALQ, ALR, list({ALQ, ALR})) -> list({ALQ, - ALR}). -key_set_loop(List, Key, Value, Inspected) -> - case List of - [{K, _} | Rest] when K =:= Key -> - lists:reverse(Inspected, [{K, Value} | Rest]); - - [First | Rest@1] -> - key_set_loop(Rest@1, Key, Value, [First | Inspected]); - - [] -> - lists:reverse([{Key, Value} | Inspected]) - end. - --file("src/gleam/list.gleam", 1733). -?DOC( - " Given a list of 2-element tuples, inserts a key and value into the list.\n" - "\n" - " If there was already a tuple with the key then it is replaced, otherwise it\n" - " is added to the end of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_set([#(5, 0), #(4, 1)], 4, 100)\n" - " // -> [#(5, 0), #(4, 100)]\n" - " ```\n" - "\n" - " ```gleam\n" - " key_set([#(5, 0), #(4, 1)], 1, 100)\n" - " // -> [#(5, 0), #(4, 1), #(1, 100)]\n" - " ```\n" -). --spec key_set(list({ALM, ALN}), ALM, ALN) -> list({ALM, ALN}). -key_set(List, Key, Value) -> - key_set_loop(List, Key, Value, []). - --file("src/gleam/list.gleam", 1765). -?DOC( - " Calls a function for each element in a list, discarding the return value.\n" - "\n" - " Useful for calling a side effect for every item of a list.\n" - "\n" - " ```gleam\n" - " import gleam/io\n" - "\n" - " each([\"1\", \"2\", \"3\"], io.println)\n" - " // -> Nil\n" - " // 1\n" - " // 2\n" - " // 3\n" - " ```\n" -). --spec each(list(ALV), fun((ALV) -> any())) -> nil. -each(List, F) -> - case List of - [] -> - nil; - - [First | Rest] -> - F(First), - each(Rest, F) - end. - --file("src/gleam/list.gleam", 1791). -?DOC( - " Calls a `Result` returning function for each element in a list, discarding\n" - " the return value. If the function returns `Error` then the iteration is\n" - " stopped and the error is returned.\n" - "\n" - " Useful for calling a side effect for every item of a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " try_each(\n" - " over: [1, 2, 3],\n" - " with: function_that_might_fail,\n" - " )\n" - " // -> Ok(Nil)\n" - " ```\n" -). --spec try_each(list(ALY), fun((ALY) -> {ok, any()} | {error, AMB})) -> {ok, nil} | - {error, AMB}. -try_each(List, Fun) -> - case List of - [] -> - {ok, nil}; - - [First | Rest] -> - case Fun(First) of - {ok, _} -> - try_each(Rest, Fun); - - {error, E} -> - {error, E} - end - end. - --file("src/gleam/list.gleam", 1824). --spec partition_loop(list(BFR), fun((BFR) -> boolean()), list(BFR), list(BFR)) -> {list(BFR), - list(BFR)}. -partition_loop(List, Categorise, Trues, Falses) -> - case List of - [] -> - {lists:reverse(Trues), lists:reverse(Falses)}; - - [First | Rest] -> - case Categorise(First) of - true -> - partition_loop(Rest, Categorise, [First | Trues], Falses); - - false -> - partition_loop(Rest, Categorise, Trues, [First | Falses]) - end - end. - --file("src/gleam/list.gleam", 1817). -?DOC( - " Partitions a list into a tuple/pair of lists\n" - " by a given categorisation function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " [1, 2, 3, 4, 5] |> partition(int.is_odd)\n" - " // -> #([1, 3, 5], [2, 4])\n" - " ```\n" -). --spec partition(list(AMG), fun((AMG) -> boolean())) -> {list(AMG), list(AMG)}. -partition(List, Categorise) -> - partition_loop(List, Categorise, [], []). - --file("src/gleam/list.gleam", 1904). --spec window_loop(list(list(ANN)), list(ANN), integer()) -> list(list(ANN)). -window_loop(Acc, List, N) -> - Window = take(List, N), - case erlang:length(Window) =:= N of - true -> - window_loop([Window | Acc], drop(List, 1), N); - - false -> - lists:reverse(Acc) - end. - --file("src/gleam/list.gleam", 1897). -?DOC( - " Returns a list of sliding windows.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " window([1,2,3,4,5], 3)\n" - " // -> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]\n" - " ```\n" - "\n" - " ```gleam\n" - " window([1, 2], 4)\n" - " // -> []\n" - " ```\n" -). --spec window(list(ANJ), integer()) -> list(list(ANJ)). -window(List, N) -> - case N =< 0 of - true -> - []; - - false -> - window_loop([], List, N) - end. - --file("src/gleam/list.gleam", 1927). -?DOC( - " Returns a list of tuples containing two contiguous elements.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " window_by_2([1,2,3,4])\n" - " // -> [#(1, 2), #(2, 3), #(3, 4)]\n" - " ```\n" - "\n" - " ```gleam\n" - " window_by_2([1])\n" - " // -> []\n" - " ```\n" -). --spec window_by_2(list(ANT)) -> list({ANT, ANT}). -window_by_2(List) -> - zip(List, drop(List, 1)). - --file("src/gleam/list.gleam", 1940). -?DOC( - " Drops the first elements in a given list for which the predicate function returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop_while([1, 2, 3, 4], fn (x) { x < 3 })\n" - " // -> [3, 4]\n" - " ```\n" -). --spec drop_while(list(ANW), fun((ANW) -> boolean())) -> list(ANW). -drop_while(List, Predicate) -> - case List of - [] -> - []; - - [First | Rest] -> - case Predicate(First) of - true -> - drop_while(Rest, Predicate); - - false -> - [First | Rest] - end - end. - --file("src/gleam/list.gleam", 1970). --spec take_while_loop(list(AOC), fun((AOC) -> boolean()), list(AOC)) -> list(AOC). -take_while_loop(List, Predicate, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - case Predicate(First) of - true -> - take_while_loop(Rest, Predicate, [First | Acc]); - - false -> - lists:reverse(Acc) - end - end. - --file("src/gleam/list.gleam", 1963). -?DOC( - " Takes the first elements in a given list for which the predicate function returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " take_while([1, 2, 3, 2, 4], fn (x) { x < 3 })\n" - " // -> [1, 2]\n" - " ```\n" -). --spec take_while(list(ANZ), fun((ANZ) -> boolean())) -> list(ANZ). -take_while(List, Predicate) -> - take_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 2002). --spec chunk_loop(list(AOL), fun((AOL) -> AON), AON, list(AOL), list(list(AOL))) -> list(list(AOL)). -chunk_loop(List, F, Previous_key, Current_chunk, Acc) -> - case List of - [First | Rest] -> - Key = F(First), - case Key =:= Previous_key of - true -> - chunk_loop(Rest, F, Key, [First | Current_chunk], Acc); - - false -> - New_acc = [lists:reverse(Current_chunk) | Acc], - chunk_loop(Rest, F, Key, [First], New_acc) - end; - - [] -> - lists:reverse([lists:reverse(Current_chunk) | Acc]) - end. - --file("src/gleam/list.gleam", 1995). -?DOC( - " Returns a list of chunks in which\n" - " the return value of calling `f` on each element is the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 })\n" - " // -> [[1], [2, 2], [3], [4, 4, 6], [7, 7]]\n" - " ```\n" -). --spec chunk(list(AOG), fun((AOG) -> any())) -> list(list(AOG)). -chunk(List, F) -> - case List of - [] -> - []; - - [First | Rest] -> - chunk_loop(Rest, F, F(First), [First], []) - end. - --file("src/gleam/list.gleam", 2047). --spec sized_chunk_loop( - list(AOX), - integer(), - integer(), - list(AOX), - list(list(AOX)) -) -> list(list(AOX)). -sized_chunk_loop(List, Count, Left, Current_chunk, Acc) -> - case List of - [] -> - case Current_chunk of - [] -> - lists:reverse(Acc); - - Remaining -> - lists:reverse([lists:reverse(Remaining) | Acc]) - end; - - [First | Rest] -> - Chunk = [First | Current_chunk], - case Left > 1 of - true -> - sized_chunk_loop(Rest, Count, Left - 1, Chunk, Acc); - - false -> - sized_chunk_loop( - Rest, - Count, - Count, - [], - [lists:reverse(Chunk) | Acc] - ) - end - end. - --file("src/gleam/list.gleam", 2043). -?DOC( - " Returns a list of chunks containing `count` elements each.\n" - "\n" - " If the last chunk does not have `count` elements, it is instead\n" - " a partial chunk, with less than `count` elements.\n" - "\n" - " For any `count` less than 1 this function behaves as if it was set to 1.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2)\n" - " // -> [[1, 2], [3, 4], [5, 6]]\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3)\n" - " // -> [[1, 2, 3], [4, 5, 6], [7, 8]]\n" - " ```\n" -). --spec sized_chunk(list(AOT), integer()) -> list(list(AOT)). -sized_chunk(List, Count) -> - sized_chunk_loop(List, Count, Count, [], []). - --file("src/gleam/list.gleam", 2091). -?DOC( - " This function acts similar to fold, but does not take an initial state.\n" - " Instead, it starts from the first element in the list\n" - " and combines it with each subsequent element in turn using the given\n" - " function. The function is called as `fun(accumulator, current_element)`.\n" - "\n" - " Returns `Ok` to indicate a successful run, and `Error` if called on an\n" - " empty list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [] |> reduce(fn(acc, x) { acc + x })\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x })\n" - " // -> Ok(15)\n" - " ```\n" -). --spec reduce(list(APE), fun((APE, APE) -> APE)) -> {ok, APE} | {error, nil}. -reduce(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, fold(Rest, First, Fun)} - end. - --file("src/gleam/list.gleam", 2115). --spec scan_loop(list(APM), APO, list(APO), fun((APO, APM) -> APO)) -> list(APO). -scan_loop(List, Accumulator, Accumulated, Fun) -> - case List of - [] -> - lists:reverse(Accumulated); - - [First | Rest] -> - Next = Fun(Accumulator, First), - scan_loop(Rest, Next, [Next | Accumulated], Fun) - end. - --file("src/gleam/list.gleam", 2107). -?DOC( - " Similar to `fold`, but yields the state of the accumulator at each stage.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i })\n" - " // -> [101, 103, 106]\n" - " ```\n" -). --spec scan(list(API), APK, fun((APK, API) -> APK)) -> list(APK). -scan(List, Initial, Fun) -> - scan_loop(List, Initial, [], Fun). - --file("src/gleam/list.gleam", 2148). -?DOC( - " Returns the last element in the given list.\n" - "\n" - " Returns `Error(Nil)` if the list is empty.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " last([])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " last([1, 2, 3, 4, 5])\n" - " // -> Ok(5)\n" - " ```\n" -). --spec last(list(APR)) -> {ok, APR} | {error, nil}. -last(List) -> - case List of - [] -> - {error, nil}; - - [Last] -> - {ok, Last}; - - [_ | Rest] -> - last(Rest) - end. - --file("src/gleam/list.gleam", 2170). -?DOC( - " Return unique combinations of elements in the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " combinations([1, 2, 3], 2)\n" - " // -> [[1, 2], [1, 3], [2, 3]]\n" - " ```\n" - "\n" - " ```gleam\n" - " combinations([1, 2, 3, 4], 3)\n" - " // -> [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]\n" - " ```\n" -). --spec combinations(list(APV), integer()) -> list(list(APV)). -combinations(Items, N) -> - case {N, Items} of - {0, _} -> - [[]]; - - {_, []} -> - []; - - {_, [First | Rest]} -> - _pipe = Rest, - _pipe@1 = combinations(_pipe, N - 1), - _pipe@2 = map( - _pipe@1, - fun(Combination) -> [First | Combination] end - ), - _pipe@3 = lists:reverse(_pipe@2), - fold(_pipe@3, combinations(Rest, N), fun(Acc, C) -> [C | Acc] end) - end. - --file("src/gleam/list.gleam", 2196). --spec combination_pairs_loop(list(AQC), list({AQC, AQC})) -> list({AQC, AQC}). -combination_pairs_loop(Items, Acc) -> - case Items of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - First_combinations = map(Rest, fun(Other) -> {First, Other} end), - Acc@1 = lists:reverse(First_combinations, Acc), - combination_pairs_loop(Rest, Acc@1) - end. - --file("src/gleam/list.gleam", 2192). -?DOC( - " Return unique pair combinations of elements in the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " combination_pairs([1, 2, 3])\n" - " // -> [#(1, 2), #(1, 3), #(2, 3)]\n" - " ```\n" -). --spec combination_pairs(list(APZ)) -> list({APZ, APZ}). -combination_pairs(Items) -> - combination_pairs_loop(Items, []). - --file("src/gleam/list.gleam", 2252). --spec take_firsts(list(list(AQW)), list(AQW), list(list(AQW))) -> {list(AQW), - list(list(AQW))}. -take_firsts(Rows, Column, Remaining_rows) -> - case Rows of - [] -> - {lists:reverse(Column), lists:reverse(Remaining_rows)}; - - [[] | Rest] -> - take_firsts(Rest, Column, Remaining_rows); - - [[First | Remaining_row] | Rest_rows] -> - Remaining_rows@1 = [Remaining_row | Remaining_rows], - take_firsts(Rest_rows, [First | Column], Remaining_rows@1) - end. - --file("src/gleam/list.gleam", 2239). --spec transpose_loop(list(list(AQP)), list(list(AQP))) -> list(list(AQP)). -transpose_loop(Rows, Columns) -> - case Rows of - [] -> - lists:reverse(Columns); - - _ -> - {Column, Rest} = take_firsts(Rows, [], []), - case Column of - [_ | _] -> - transpose_loop(Rest, [Column | Columns]); - - [] -> - transpose_loop(Rest, Columns) - end - end. - --file("src/gleam/list.gleam", 2235). -?DOC( - " Transpose rows and columns of the list of lists.\n" - "\n" - " Notice: This function is not tail recursive,\n" - " and thus may exceed stack size if called,\n" - " with large lists (on the JavaScript target).\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " transpose([[1, 2, 3], [101, 102, 103]])\n" - " // -> [[1, 101], [2, 102], [3, 103]]\n" - " ```\n" -). --spec transpose(list(list(AQK))) -> list(list(AQK)). -transpose(List_of_lists) -> - transpose_loop(List_of_lists, []). - --file("src/gleam/list.gleam", 2216). -?DOC( - " Make a list alternating the elements from the given lists\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " interleave([[1, 2], [101, 102], [201, 202]])\n" - " // -> [1, 101, 201, 2, 102, 202]\n" - " ```\n" -). --spec interleave(list(list(AQG))) -> list(AQG). -interleave(List) -> - _pipe = List, - _pipe@1 = transpose(_pipe), - lists:append(_pipe@1). - --file("src/gleam/list.gleam", 2285). --spec shuffle_pair_unwrap_loop(list({float(), ARI}), list(ARI)) -> list(ARI). -shuffle_pair_unwrap_loop(List, Acc) -> - case List of - [] -> - Acc; - - [Elem_pair | Enumerable] -> - shuffle_pair_unwrap_loop( - Enumerable, - [erlang:element(2, Elem_pair) | Acc] - ) - end. - --file("src/gleam/list.gleam", 2293). --spec do_shuffle_by_pair_indexes(list({float(), ARM})) -> list({float(), ARM}). -do_shuffle_by_pair_indexes(List_of_pairs) -> - sort( - List_of_pairs, - fun(A_pair, B_pair) -> - gleam@float:compare( - erlang:element(1, A_pair), - erlang:element(1, B_pair) - ) - end - ). - --file("src/gleam/list.gleam", 2278). -?DOC( - " Takes a list, randomly sorts all items and returns the shuffled list.\n" - "\n" - " This function uses `float.random` to decide the order of the elements.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " range(1, 10) |> shuffle()\n" - " // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5]\n" - " ```\n" -). --spec shuffle(list(ARF)) -> list(ARF). -shuffle(List) -> - _pipe = List, - _pipe@1 = fold(_pipe, [], fun(Acc, A) -> [{rand:uniform(), A} | Acc] end), - _pipe@2 = do_shuffle_by_pair_indexes(_pipe@1), - shuffle_pair_unwrap_loop(_pipe@2, []). - --file("src/gleam/list.gleam", 2325). --spec max_loop(list(ARW), fun((ARW, ARW) -> gleam@order:order()), ARW) -> ARW. -max_loop(List, Compare, Max) -> - case List of - [] -> - Max; - - [First | Rest] -> - case Compare(First, Max) of - gt -> - max_loop(Rest, Compare, First); - - lt -> - max_loop(Rest, Compare, Max); - - eq -> - max_loop(Rest, Compare, Max) - end - end. - --file("src/gleam/list.gleam", 2315). -?DOC( - " Takes a list and a comparator, and returns the maximum element in the list\n" - "\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " range(1, 10) |> list.max(int.compare)\n" - " // -> Ok(10)\n" - " ```\n" - "\n" - " ```gleam\n" - " [\"a\", \"c\", \"b\"] |> list.max(string.compare)\n" - " // -> Ok(\"c\")\n" - " ```\n" -). --spec max(list(ARP), fun((ARP, ARP) -> gleam@order:order())) -> {ok, ARP} | - {error, nil}. -max(List, Compare) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, max_loop(Rest, Compare, First)} - end. - --file("src/gleam/list.gleam", 2406). --spec build_reservoir_loop( - list(ASL), - integer(), - gleam@dict:dict(integer(), ASL) -) -> {gleam@dict:dict(integer(), ASL), list(ASL)}. -build_reservoir_loop(List, Size, Reservoir) -> - Reservoir_size = maps:size(Reservoir), - case Reservoir_size >= Size of - true -> - {Reservoir, List}; - - false -> - case List of - [] -> - {Reservoir, []}; - - [First | Rest] -> - Reservoir@1 = gleam@dict:insert( - Reservoir, - Reservoir_size, - First - ), - build_reservoir_loop(Rest, Size, Reservoir@1) - end - end. - --file("src/gleam/list.gleam", 2402). -?DOC( - " Builds the initial reservoir used by Algorithm L.\n" - " This is a dictionary with keys ranging from `0` up to `n - 1` where each\n" - " value is the corresponding element at that position in `list`.\n" - "\n" - " This also returns the remaining elements of `list` that didn't end up in\n" - " the reservoir.\n" -). --spec build_reservoir(list(ASG), integer()) -> {gleam@dict:dict(integer(), ASG), - list(ASG)}. -build_reservoir(List, N) -> - build_reservoir_loop(List, N, maps:new()). - --file("src/gleam/list.gleam", 2390). --spec log_random() -> float(). -log_random() -> - Random@1 = case gleam@float:logarithm( - rand:uniform() + 2.2250738585072014e-308 - ) of - {ok, Random} -> Random; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam/list"/utf8>>, - function => <<"log_random"/utf8>>, - line => 2391, - value => _assert_fail, - start => 56078, - 'end' => 56149, - pattern_start => 56089, - pattern_end => 56099}) - end, - Random@1. - --file("src/gleam/list.gleam", 2367). --spec sample_loop( - list(ASA), - gleam@dict:dict(integer(), ASA), - integer(), - float() -) -> gleam@dict:dict(integer(), ASA). -sample_loop(List, Reservoir, N, W) -> - Skip = begin - Log@1 = case gleam@float:logarithm(1.0 - W) of - {ok, Log} -> Log; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam/list"/utf8>>, - function => <<"sample_loop"/utf8>>, - line => 2374, - value => _assert_fail, - start => 55639, - 'end' => 55685, - pattern_start => 55650, - pattern_end => 55657}) - end, - erlang:round(math:floor(case Log@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> log_random() / Gleam@denominator - end)) - end, - case drop(List, Skip) of - [] -> - Reservoir; - - [First | Rest] -> - Reservoir@1 = gleam@dict:insert( - Reservoir, - gleam@int:random(N), - First - ), - W@1 = W * math:exp(case erlang:float(N) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> log_random() / Gleam@denominator@1 - end), - sample_loop(Rest, Reservoir@1, N, W@1) - end. - --file("src/gleam/list.gleam", 2349). -?DOC( - " Returns a random sample of up to n elements from a list using reservoir\n" - " sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L).\n" - " Returns an empty list if the sample size is less than or equal to 0.\n" - "\n" - " Order is not random, only selection is.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " reservoir_sample([1, 2, 3, 4, 5], 3)\n" - " // -> [2, 4, 5] // A random sample of 3 items\n" - " ```\n" -). --spec sample(list(ARX), integer()) -> list(ARX). -sample(List, N) -> - {Reservoir, Rest} = build_reservoir(List, N), - case gleam@dict:is_empty(Reservoir) of - true -> - []; - - false -> - W = math:exp(case erlang:float(N) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> log_random() / Gleam@denominator - end), - maps:values(sample_loop(Rest, Reservoir, N, W)) - end. - --file("src/gleam/list.gleam", 1851). --spec permutation_zip(list(AMT), list(AMT), list(list(AMT))) -> list(list(AMT)). -permutation_zip(List, Rest, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [Head | Tail] -> - permutation_prepend( - Head, - permutations(lists:reverse(Rest, Tail)), - Tail, - [Head | Rest], - Acc - ) - end. - --file("src/gleam/list.gleam", 1869). --spec permutation_prepend( - ANA, - list(list(ANA)), - list(ANA), - list(ANA), - list(list(ANA)) -) -> list(list(ANA)). -permutation_prepend(El, Permutations, List_1, List_2, Acc) -> - case Permutations of - [] -> - permutation_zip(List_1, List_2, Acc); - - [Head | Tail] -> - permutation_prepend(El, Tail, List_1, List_2, [[El | Head] | Acc]) - end. - --file("src/gleam/list.gleam", 1844). -?DOC( - " Returns all the permutations of a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " permutations([1, 2])\n" - " // -> [[1, 2], [2, 1]]\n" - " ```\n" -). --spec permutations(list(AMP)) -> list(list(AMP)). -permutations(List) -> - case List of - [] -> - [[]]; - - L -> - permutation_zip(L, [], []) - end. diff --git a/build/dev/javascript/gleam_stdlib/gleam@option.erl b/build/dev/javascript/gleam_stdlib/gleam@option.erl deleted file mode 100644 index 8e86a8e..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@option.erl +++ /dev/null @@ -1,413 +0,0 @@ --module(gleam@option). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/option.gleam"). --export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]). --export_type([option/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type option(FG) :: {some, FG} | none. - --file("src/gleam/option.gleam", 59). --spec reverse_and_prepend(list(FV), list(FV)) -> list(FV). -reverse_and_prepend(Prefix, Suffix) -> - case Prefix of - [] -> - Suffix; - - [First | Rest] -> - reverse_and_prepend(Rest, [First | Suffix]) - end. - --file("src/gleam/option.gleam", 44). --spec all_loop(list(option(FM)), list(FM)) -> option(list(FM)). -all_loop(List, Acc) -> - case List of - [] -> - {some, lists:reverse(Acc)}; - - [none | _] -> - none; - - [{some, First} | Rest] -> - all_loop(Rest, [First | Acc]) - end. - --file("src/gleam/option.gleam", 40). -?DOC( - " Combines a list of `Option`s into a single `Option`.\n" - " If all elements in the list are `Some` then returns a `Some` holding the list of values.\n" - " If any element is `None` then returns`None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " all([Some(1), Some(2)])\n" - " // -> Some([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " all([Some(1), None])\n" - " // -> None\n" - " ```\n" -). --spec all(list(option(FH))) -> option(list(FH)). -all(List) -> - all_loop(List, []). - --file("src/gleam/option.gleam", 80). -?DOC( - " Checks whether the `Option` is a `Some` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_some(Some(1))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_some(None)\n" - " // -> False\n" - " ```\n" -). --spec is_some(option(any())) -> boolean(). -is_some(Option) -> - Option /= none. - --file("src/gleam/option.gleam", 98). -?DOC( - " Checks whether the `Option` is a `None` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_none(Some(1))\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_none(None)\n" - " // -> True\n" - " ```\n" -). --spec is_none(option(any())) -> boolean(). -is_none(Option) -> - Option =:= none. - --file("src/gleam/option.gleam", 116). -?DOC( - " Converts an `Option` type to a `Result` type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_result(Some(1), \"some_error\")\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " to_result(None, \"some_error\")\n" - " // -> Error(\"some_error\")\n" - " ```\n" -). --spec to_result(option(GD), GG) -> {ok, GD} | {error, GG}. -to_result(Option, E) -> - case Option of - {some, A} -> - {ok, A}; - - none -> - {error, E} - end. - --file("src/gleam/option.gleam", 137). -?DOC( - " Converts a `Result` type to an `Option` type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_result(Ok(1))\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " from_result(Error(\"some_error\"))\n" - " // -> None\n" - " ```\n" -). --spec from_result({ok, GJ} | {error, any()}) -> option(GJ). -from_result(Result) -> - case Result of - {ok, A} -> - {some, A}; - - {error, _} -> - none - end. - --file("src/gleam/option.gleam", 158). -?DOC( - " Extracts the value from an `Option`, returning a default value if there is none.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap(Some(1), 0)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap(None, 0)\n" - " // -> 0\n" - " ```\n" -). --spec unwrap(option(GO), GO) -> GO. -unwrap(Option, Default) -> - case Option of - {some, X} -> - X; - - none -> - Default - end. - --file("src/gleam/option.gleam", 179). -?DOC( - " Extracts the value from an `Option`, evaluating the default function if the option is `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_unwrap(Some(1), fn() { 0 })\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_unwrap(None, fn() { 0 })\n" - " // -> 0\n" - " ```\n" -). --spec lazy_unwrap(option(GQ), fun(() -> GQ)) -> GQ. -lazy_unwrap(Option, Default) -> - case Option of - {some, X} -> - X; - - none -> - Default() - end. - --file("src/gleam/option.gleam", 204). -?DOC( - " Updates a value held within the `Some` of an `Option` by calling a given function\n" - " on it.\n" - "\n" - " If the `Option` is a `None` rather than `Some`, the function is not called and the\n" - " `Option` stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map(over: Some(1), with: fn(x) { x + 1 })\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " map(over: None, with: fn(x) { x + 1 })\n" - " // -> None\n" - " ```\n" -). --spec map(option(GS), fun((GS) -> GU)) -> option(GU). -map(Option, Fun) -> - case Option of - {some, X} -> - {some, Fun(X)}; - - none -> - none - end. - --file("src/gleam/option.gleam", 230). -?DOC( - " Merges a nested `Option` into a single layer.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flatten(Some(Some(1)))\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(Some(None))\n" - " // -> None\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(None)\n" - " // -> None\n" - " ```\n" -). --spec flatten(option(option(GW))) -> option(GW). -flatten(Option) -> - case Option of - {some, X} -> - X; - - none -> - none - end. - --file("src/gleam/option.gleam", 269). -?DOC( - " Updates a value held within the `Some` of an `Option` by calling a given function\n" - " on it, where the given function also returns an `Option`. The two options are\n" - " then merged together into one `Option`.\n" - "\n" - " If the `Option` is a `None` rather than `Some` the function is not called and the\n" - " option stays the same.\n" - "\n" - " This function is the equivalent of calling `map` followed by `flatten`, and\n" - " it is useful for chaining together multiple functions that return `Option`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " then(Some(1), fn(x) { Some(x + 1) })\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " then(Some(1), fn(x) { Some(#(\"a\", x)) })\n" - " // -> Some(#(\"a\", 1))\n" - " ```\n" - "\n" - " ```gleam\n" - " then(Some(1), fn(_) { None })\n" - " // -> None\n" - " ```\n" - "\n" - " ```gleam\n" - " then(None, fn(x) { Some(x + 1) })\n" - " // -> None\n" - " ```\n" -). --spec then(option(HA), fun((HA) -> option(HC))) -> option(HC). -then(Option, Fun) -> - case Option of - {some, X} -> - Fun(X); - - none -> - none - end. - --file("src/gleam/option.gleam", 300). -?DOC( - " Returns the first value if it is `Some`, otherwise returns the second value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " or(Some(1), Some(2))\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Some(1), None)\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(None, Some(2))\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(None, None)\n" - " // -> None\n" - " ```\n" -). --spec 'or'(option(HF), option(HF)) -> option(HF). -'or'(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second - end. - --file("src/gleam/option.gleam", 331). -?DOC( - " Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_or(Some(1), fn() { Some(2) })\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Some(1), fn() { None })\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(None, fn() { Some(2) })\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(None, fn() { None })\n" - " // -> None\n" - " ```\n" -). --spec lazy_or(option(HJ), fun(() -> option(HJ))) -> option(HJ). -lazy_or(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second() - end. - --file("src/gleam/option.gleam", 352). --spec values_loop(list(option(HR)), list(HR)) -> list(HR). -values_loop(List, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [none | Rest] -> - values_loop(Rest, Acc); - - [{some, First} | Rest@1] -> - values_loop(Rest@1, [First | Acc]) - end. - --file("src/gleam/option.gleam", 348). -?DOC( - " Given a list of `Option`s,\n" - " returns only the values inside `Some`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " values([Some(1), None, Some(3)])\n" - " // -> [1, 3]\n" - " ```\n" -). --spec values(list(option(HN))) -> list(HN). -values(Options) -> - values_loop(Options, []). diff --git a/build/dev/javascript/gleam_stdlib/gleam@order.erl b/build/dev/javascript/gleam_stdlib/gleam@order.erl deleted file mode 100644 index ec2bb84..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@order.erl +++ /dev/null @@ -1,200 +0,0 @@ --module(gleam@order). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/order.gleam"). --export([negate/1, to_int/1, compare/2, reverse/1, break_tie/2, lazy_break_tie/2]). --export_type([order/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type order() :: lt | eq | gt. - --file("src/gleam/order.gleam", 35). -?DOC( - " Inverts an order, so less-than becomes greater-than and greater-than\n" - " becomes less-than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(Lt)\n" - " // -> Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " negate(Eq)\n" - " // -> Eq\n" - " ```\n" - "\n" - " ```gleam\n" - " negate(Gt)\n" - " // -> Lt\n" - " ```\n" -). --spec negate(order()) -> order(). -negate(Order) -> - case Order of - lt -> - gt; - - eq -> - eq; - - gt -> - lt - end. - --file("src/gleam/order.gleam", 62). -?DOC( - " Produces a numeric representation of the order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_int(Lt)\n" - " // -> -1\n" - " ```\n" - "\n" - " ```gleam\n" - " to_int(Eq)\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " to_int(Gt)\n" - " // -> 1\n" - " ```\n" -). --spec to_int(order()) -> integer(). -to_int(Order) -> - case Order of - lt -> - -1; - - eq -> - 0; - - gt -> - 1 - end. - --file("src/gleam/order.gleam", 79). -?DOC( - " Compares two `Order` values to one another, producing a new `Order`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(Eq, with: Lt)\n" - " // -> Gt\n" - " ```\n" -). --spec compare(order(), order()) -> order(). -compare(A, B) -> - case {A, B} of - {X, Y} when X =:= Y -> - eq; - - {lt, _} -> - lt; - - {eq, gt} -> - lt; - - {_, _} -> - gt - end. - --file("src/gleam/order.gleam", 100). -?DOC( - " Inverts an ordering function, so less-than becomes greater-than and greater-than\n" - " becomes less-than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - " import gleam/list\n" - "\n" - " list.sort([1, 5, 4], by: reverse(int.compare))\n" - " // -> [5, 4, 1]\n" - " ```\n" -). --spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()). -reverse(Orderer) -> - fun(A, B) -> Orderer(B, A) end. - --file("src/gleam/order.gleam", 122). -?DOC( - " Return a fallback `Order` in case the first argument is `Eq`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " break_tie(in: int.compare(1, 1), with: Lt)\n" - " // -> Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " break_tie(in: int.compare(1, 0), with: Eq)\n" - " // -> Gt\n" - " ```\n" -). --spec break_tie(order(), order()) -> order(). -break_tie(Order, Other) -> - case Order of - lt -> - Order; - - gt -> - Order; - - eq -> - Other - end. - --file("src/gleam/order.gleam", 151). -?DOC( - " Invokes a fallback function returning an `Order` in case the first argument\n" - " is `Eq`.\n" - "\n" - " This can be useful when the fallback comparison might be expensive and it\n" - " needs to be delayed until strictly necessary.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt })\n" - " // -> Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq })\n" - " // -> Gt\n" - " ```\n" -). --spec lazy_break_tie(order(), fun(() -> order())) -> order(). -lazy_break_tie(Order, Comparison) -> - case Order of - lt -> - Order; - - gt -> - Order; - - eq -> - Comparison() - end. diff --git a/build/dev/javascript/gleam_stdlib/gleam@pair.erl b/build/dev/javascript/gleam_stdlib/gleam@pair.erl deleted file mode 100644 index cb18264..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@pair.erl +++ /dev/null @@ -1,110 +0,0 @@ --module(gleam@pair). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/pair.gleam"). --export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/pair.gleam", 10). -?DOC( - " Returns the first element in a pair.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " first(#(1, 2))\n" - " // -> 1\n" - " ```\n" -). --spec first({CLF, any()}) -> CLF. -first(Pair) -> - {A, _} = Pair, - A. - --file("src/gleam/pair.gleam", 24). -?DOC( - " Returns the second element in a pair.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " second(#(1, 2))\n" - " // -> 2\n" - " ```\n" -). --spec second({any(), CLI}) -> CLI. -second(Pair) -> - {_, A} = Pair, - A. - --file("src/gleam/pair.gleam", 38). -?DOC( - " Returns a new pair with the elements swapped.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " swap(#(1, 2))\n" - " // -> #(2, 1)\n" - " ```\n" -). --spec swap({CLJ, CLK}) -> {CLK, CLJ}. -swap(Pair) -> - {A, B} = Pair, - {B, A}. - --file("src/gleam/pair.gleam", 53). -?DOC( - " Returns a new pair with the first element having had `with` applied to\n" - " it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " #(1, 2) |> map_first(fn(n) { n * 2 })\n" - " // -> #(2, 2)\n" - " ```\n" -). --spec map_first({CLL, CLM}, fun((CLL) -> CLN)) -> {CLN, CLM}. -map_first(Pair, Fun) -> - {A, B} = Pair, - {Fun(A), B}. - --file("src/gleam/pair.gleam", 68). -?DOC( - " Returns a new pair with the second element having had `with` applied to\n" - " it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " #(1, 2) |> map_second(fn(n) { n * 2 })\n" - " // -> #(1, 4)\n" - " ```\n" -). --spec map_second({CLO, CLP}, fun((CLP) -> CLQ)) -> {CLO, CLQ}. -map_second(Pair, Fun) -> - {A, B} = Pair, - {A, Fun(B)}. - --file("src/gleam/pair.gleam", 83). -?DOC( - " Returns a new pair with the given elements. This can also be done using the dedicated\n" - " syntax instead: `new(1, 2) == #(1, 2)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new(1, 2)\n" - " // -> #(1, 2)\n" - " ```\n" -). --spec new(CLR, CLS) -> {CLR, CLS}. -new(First, Second) -> - {First, Second}. diff --git a/build/dev/javascript/gleam_stdlib/gleam@result.erl b/build/dev/javascript/gleam_stdlib/gleam@result.erl deleted file mode 100644 index 9d89ff7..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@result.erl +++ /dev/null @@ -1,550 +0,0 @@ --module(gleam@result). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/result.gleam"). --export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, then/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, unwrap_both/1, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Result represents the result of something that may succeed or not.\n" - " `Ok` means it was successful, `Error` means it was not successful.\n" -). - --file("src/gleam/result.gleam", 20). -?DOC( - " Checks whether the result is an `Ok` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_ok(Ok(1))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_ok(Error(Nil))\n" - " // -> False\n" - " ```\n" -). --spec is_ok({ok, any()} | {error, any()}) -> boolean(). -is_ok(Result) -> - case Result of - {error, _} -> - false; - - {ok, _} -> - true - end. - --file("src/gleam/result.gleam", 41). -?DOC( - " Checks whether the result is an `Error` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_error(Ok(1))\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_error(Error(Nil))\n" - " // -> True\n" - " ```\n" -). --spec is_error({ok, any()} | {error, any()}) -> boolean(). -is_error(Result) -> - case Result of - {ok, _} -> - false; - - {error, _} -> - true - end. - --file("src/gleam/result.gleam", 66). -?DOC( - " Updates a value held within the `Ok` of a result by calling a given function\n" - " on it.\n" - "\n" - " If the result is an `Error` rather than `Ok` the function is not called and the\n" - " result stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map(over: Ok(1), with: fn(x) { x + 1 })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " map(over: Error(1), with: fn(x) { x + 1 })\n" - " // -> Error(1)\n" - " ```\n" -). --spec map({ok, CMC} | {error, CMD}, fun((CMC) -> CMG)) -> {ok, CMG} | - {error, CMD}. -map(Result, Fun) -> - case Result of - {ok, X} -> - {ok, Fun(X)}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 91). -?DOC( - " Updates a value held within the `Error` of a result by calling a given function\n" - " on it.\n" - "\n" - " If the result is `Ok` rather than `Error` the function is not called and the\n" - " result stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map_error(over: Error(1), with: fn(x) { x + 1 })\n" - " // -> Error(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " map_error(over: Ok(1), with: fn(x) { x + 1 })\n" - " // -> Ok(1)\n" - " ```\n" -). --spec map_error({ok, CMJ} | {error, CMK}, fun((CMK) -> CMN)) -> {ok, CMJ} | - {error, CMN}. -map_error(Result, Fun) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, Error} -> - {error, Fun(Error)} - end. - --file("src/gleam/result.gleam", 120). -?DOC( - " Merges a nested `Result` into a single layer.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flatten(Ok(Ok(1)))\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(Ok(Error(\"\")))\n" - " // -> Error(\"\")\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(Error(Nil))\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec flatten({ok, {ok, CMQ} | {error, CMR}} | {error, CMR}) -> {ok, CMQ} | - {error, CMR}. -flatten(Result) -> - case Result of - {ok, X} -> - X; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 158). -?DOC( - " \"Updates\" an `Ok` result by passing its value to a function that yields a result,\n" - " and returning the yielded result. (This may \"replace\" the `Ok` with an `Error`.)\n" - "\n" - " If the input is an `Error` rather than an `Ok`, the function is not called and\n" - " the original `Error` is returned.\n" - "\n" - " This function is the equivalent of calling `map` followed by `flatten`, and\n" - " it is useful for chaining together multiple functions that may fail.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " try(Ok(1), fn(x) { Ok(x + 1) })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " try(Ok(1), fn(x) { Ok(#(\"a\", x)) })\n" - " // -> Ok(#(\"a\", 1))\n" - " ```\n" - "\n" - " ```gleam\n" - " try(Ok(1), fn(_) { Error(\"Oh no\") })\n" - " // -> Error(\"Oh no\")\n" - " ```\n" - "\n" - " ```gleam\n" - " try(Error(Nil), fn(x) { Ok(x + 1) })\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec 'try'({ok, CMY} | {error, CMZ}, fun((CMY) -> {ok, CNC} | {error, CMZ})) -> {ok, - CNC} | - {error, CMZ}. -'try'(Result, Fun) -> - case Result of - {ok, X} -> - Fun(X); - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 169). --spec then({ok, CNH} | {error, CNI}, fun((CNH) -> {ok, CNL} | {error, CNI})) -> {ok, - CNL} | - {error, CNI}. -then(Result, Fun) -> - 'try'(Result, Fun). - --file("src/gleam/result.gleam", 191). -?DOC( - " Extracts the `Ok` value from a result, returning a default value if the result\n" - " is an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap(Ok(1), 0)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap(Error(\"\"), 0)\n" - " // -> 0\n" - " ```\n" -). --spec unwrap({ok, CNQ} | {error, any()}, CNQ) -> CNQ. -unwrap(Result, Default) -> - case Result of - {ok, V} -> - V; - - {error, _} -> - Default - end. - --file("src/gleam/result.gleam", 213). -?DOC( - " Extracts the `Ok` value from a result, evaluating the default function if the result\n" - " is an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_unwrap(Ok(1), fn() { 0 })\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_unwrap(Error(\"\"), fn() { 0 })\n" - " // -> 0\n" - " ```\n" -). --spec lazy_unwrap({ok, CNU} | {error, any()}, fun(() -> CNU)) -> CNU. -lazy_unwrap(Result, Default) -> - case Result of - {ok, V} -> - V; - - {error, _} -> - Default() - end. - --file("src/gleam/result.gleam", 235). -?DOC( - " Extracts the `Error` value from a result, returning a default value if the result\n" - " is an `Ok`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap_error(Error(1), 0)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap_error(Ok(\"\"), 0)\n" - " // -> 0\n" - " ```\n" -). --spec unwrap_error({ok, any()} | {error, CNZ}, CNZ) -> CNZ. -unwrap_error(Result, Default) -> - case Result of - {ok, _} -> - Default; - - {error, E} -> - E - end. - --file("src/gleam/result.gleam", 243). --spec unwrap_both({ok, COC} | {error, COC}) -> COC. -unwrap_both(Result) -> - case Result of - {ok, A} -> - A; - - {error, A@1} -> - A@1 - end. - --file("src/gleam/result.gleam", 274). -?DOC( - " Returns the first value if it is `Ok`, otherwise returns the second value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " or(Ok(1), Ok(2))\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Ok(1), Error(\"Error 2\"))\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Error(\"Error 1\"), Ok(2))\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Error(\"Error 1\"), Error(\"Error 2\"))\n" - " // -> Error(\"Error 2\")\n" - " ```\n" -). --spec 'or'({ok, COF} | {error, COG}, {ok, COF} | {error, COG}) -> {ok, COF} | - {error, COG}. -'or'(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second - end. - --file("src/gleam/result.gleam", 307). -?DOC( - " Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value.\n" - "\n" - " If you need access to the initial error value, use `result.try_recover`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_or(Ok(1), fn() { Ok(2) })\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Ok(1), fn() { Error(\"Error 2\") })\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Error(\"Error 1\"), fn() { Ok(2) })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Error(\"Error 1\"), fn() { Error(\"Error 2\") })\n" - " // -> Error(\"Error 2\")\n" - " ```\n" -). --spec lazy_or({ok, CON} | {error, COO}, fun(() -> {ok, CON} | {error, COO})) -> {ok, - CON} | - {error, COO}. -lazy_or(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second() - end. - --file("src/gleam/result.gleam", 333). -?DOC( - " Combines a list of results into a single result.\n" - " If all elements in the list are `Ok` then returns an `Ok` holding the list of values.\n" - " If any element is `Error` then returns the first error.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " all([Ok(1), Ok(2)])\n" - " // -> Ok([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " all([Ok(1), Error(\"e\")])\n" - " // -> Error(\"e\")\n" - " ```\n" -). --spec all(list({ok, COV} | {error, COW})) -> {ok, list(COV)} | {error, COW}. -all(Results) -> - gleam@list:try_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 353). --spec partition_loop(list({ok, CPK} | {error, CPL}), list(CPK), list(CPL)) -> {list(CPK), - list(CPL)}. -partition_loop(Results, Oks, Errors) -> - case Results of - [] -> - {Oks, Errors}; - - [{ok, A} | Rest] -> - partition_loop(Rest, [A | Oks], Errors); - - [{error, E} | Rest@1] -> - partition_loop(Rest@1, Oks, [E | Errors]) - end. - --file("src/gleam/result.gleam", 349). -?DOC( - " Given a list of results, returns a pair where the first element is a list\n" - " of all the values inside `Ok` and the second element is a list with all the\n" - " values inside `Error`. The values in both lists appear in reverse order with\n" - " respect to their position in the original list of results.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " partition([Ok(1), Error(\"a\"), Error(\"b\"), Ok(2)])\n" - " // -> #([2, 1], [\"b\", \"a\"])\n" - " ```\n" -). --spec partition(list({ok, CPD} | {error, CPE})) -> {list(CPD), list(CPE)}. -partition(Results) -> - partition_loop(Results, [], []). - --file("src/gleam/result.gleam", 375). -?DOC( - " Replace the value within a result\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " replace(Ok(1), Nil)\n" - " // -> Ok(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " replace(Error(1), Nil)\n" - " // -> Error(1)\n" - " ```\n" -). --spec replace({ok, any()} | {error, CPT}, CPW) -> {ok, CPW} | {error, CPT}. -replace(Result, Value) -> - case Result of - {ok, _} -> - {ok, Value}; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 396). -?DOC( - " Replace the error within a result\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " replace_error(Error(1), Nil)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " replace_error(Ok(1), Nil)\n" - " // -> Ok(1)\n" - " ```\n" -). --spec replace_error({ok, CPZ} | {error, any()}, CQD) -> {ok, CPZ} | {error, CQD}. -replace_error(Result, Error) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, _} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 412). -?DOC( - " Given a list of results, returns only the values inside `Ok`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " values([Ok(1), Error(\"a\"), Ok(3)])\n" - " // -> [1, 3]\n" - " ```\n" -). --spec values(list({ok, CQG} | {error, any()})) -> list(CQG). -values(Results) -> - gleam@list:filter_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 445). -?DOC( - " Updates a value held within the `Error` of a result by calling a given function\n" - " on it, where the given function also returns a result. The two results are\n" - " then merged together into one result.\n" - "\n" - " If the result is an `Ok` rather than `Error` the function is not called and the\n" - " result stays the same.\n" - "\n" - " This function is useful for chaining together computations that may fail\n" - " and trying to recover from possible errors.\n" - "\n" - " If you do not need access to the initial error value, use `result.lazy_or`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " Ok(1) |> try_recover(with: fn(_) { Error(\"failed to recover\") })\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " Error(1) |> try_recover(with: fn(error) { Ok(error + 1) })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " Error(1) |> try_recover(with: fn(error) { Error(\"failed to recover\") })\n" - " // -> Error(\"failed to recover\")\n" - " ```\n" -). --spec try_recover( - {ok, CQM} | {error, CQN}, - fun((CQN) -> {ok, CQM} | {error, CQQ}) -) -> {ok, CQM} | {error, CQQ}. -try_recover(Result, Fun) -> - case Result of - {ok, Value} -> - {ok, Value}; - - {error, Error} -> - Fun(Error) - end. diff --git a/build/dev/javascript/gleam_stdlib/gleam@set.erl b/build/dev/javascript/gleam_stdlib/gleam@set.erl deleted file mode 100644 index bb3c417..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@set.erl +++ /dev/null @@ -1,429 +0,0 @@ --module(gleam@set). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/set.gleam"). --export([new/0, size/1, is_empty/1, contains/2, delete/2, to_list/1, fold/3, filter/2, drop/2, take/2, intersection/2, difference/2, is_subset/2, is_disjoint/2, each/2, insert/2, from_list/1, map/2, union/2, symmetric_difference/2]). --export_type([set/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --opaque set(CVL) :: {set, gleam@dict:dict(CVL, list(nil))}. - --file("src/gleam/set.gleam", 32). -?DOC(" Creates a new empty set.\n"). --spec new() -> set(any()). -new() -> - {set, maps:new()}. - --file("src/gleam/set.gleam", 50). -?DOC( - " Gets the number of members in a set.\n" - "\n" - " This function runs in constant time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(1)\n" - " |> insert(2)\n" - " |> size\n" - " // -> 2\n" - " ```\n" -). --spec size(set(any())) -> integer(). -size(Set) -> - maps:size(erlang:element(2, Set)). - --file("src/gleam/set.gleam", 68). -?DOC( - " Determines whether or not the set is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> is_empty\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(1) |> is_empty\n" - " // -> False\n" - " ```\n" -). --spec is_empty(set(any())) -> boolean(). -is_empty(Set) -> - Set =:= new(). - --file("src/gleam/set.gleam", 110). -?DOC( - " Checks whether a set contains a given member.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(2)\n" - " |> contains(2)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(2)\n" - " |> contains(1)\n" - " // -> False\n" - " ```\n" -). --spec contains(set(CVW), CVW) -> boolean(). -contains(Set, Member) -> - _pipe = erlang:element(2, Set), - _pipe@1 = gleam_stdlib:map_get(_pipe, Member), - gleam@result:is_ok(_pipe@1). - --file("src/gleam/set.gleam", 131). -?DOC( - " Removes a member from a set. If the set does not contain the member then\n" - " the set is returned unchanged.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(2)\n" - " |> delete(2)\n" - " |> contains(1)\n" - " // -> False\n" - " ```\n" -). --spec delete(set(CVY), CVY) -> set(CVY). -delete(Set, Member) -> - {set, gleam@dict:delete(erlang:element(2, Set), Member)}. - --file("src/gleam/set.gleam", 149). -?DOC( - " Converts the set into a list of the contained members.\n" - "\n" - " The list has no specific ordering, any unintentional ordering may change in\n" - " future versions of Gleam or Erlang.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(2) |> to_list\n" - " // -> [2]\n" - " ```\n" -). --spec to_list(set(CWB)) -> list(CWB). -to_list(Set) -> - maps:keys(erlang:element(2, Set)). - --file("src/gleam/set.gleam", 190). -?DOC( - " Combines all entries into a single value by calling a given function on each\n" - " one.\n" - "\n" - " Sets are not ordered so the values are not returned in any specific order.\n" - " Do not write code that relies on the order entries are used by this\n" - " function as it may change in later versions of Gleam or Erlang.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 3, 9])\n" - " |> fold(0, fn(accumulator, member) { accumulator + member })\n" - " // -> 13\n" - " ```\n" -). --spec fold(set(CWH), CWJ, fun((CWJ, CWH) -> CWJ)) -> CWJ. -fold(Set, Initial, Reducer) -> - gleam@dict:fold( - erlang:element(2, Set), - Initial, - fun(A, K, _) -> Reducer(A, K) end - ). - --file("src/gleam/set.gleam", 214). -?DOC( - " Creates a new set from an existing set, minus any members that a given\n" - " function returns `False` for.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " from_list([1, 4, 6, 3, 675, 44, 67])\n" - " |> filter(keeping: int.is_even)\n" - " |> to_list\n" - " // -> [4, 6, 44]\n" - " ```\n" -). --spec filter(set(CWK), fun((CWK) -> boolean())) -> set(CWK). -filter(Set, Predicate) -> - {set, - gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}. - --file("src/gleam/set.gleam", 249). -?DOC( - " Creates a new set from a given set with all the same entries except any\n" - " entry found on the given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 2, 3, 4])\n" - " |> drop([1, 3])\n" - " |> to_list\n" - " // -> [2, 4]\n" - " ```\n" -). --spec drop(set(CWR), list(CWR)) -> set(CWR). -drop(Set, Disallowed) -> - gleam@list:fold(Disallowed, Set, fun delete/2). - --file("src/gleam/set.gleam", 267). -?DOC( - " Creates a new set from a given set, only including any members which are in\n" - " a given list.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 2, 3])\n" - " |> take([1, 3, 5])\n" - " |> to_list\n" - " // -> [1, 3]\n" - " ```\n" -). --spec take(set(CWV), list(CWV)) -> set(CWV). -take(Set, Desired) -> - {set, gleam@dict:take(erlang:element(2, Set), Desired)}. - --file("src/gleam/set.gleam", 287). --spec order(set(CXD), set(CXD)) -> {set(CXD), set(CXD)}. -order(First, Second) -> - case maps:size(erlang:element(2, First)) > maps:size( - erlang:element(2, Second) - ) of - true -> - {First, Second}; - - false -> - {Second, First} - end. - --file("src/gleam/set.gleam", 305). -?DOC( - " Creates a new set that contains members that are present in both given sets.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " intersection(from_list([1, 2]), from_list([2, 3])) |> to_list\n" - " // -> [2]\n" - " ```\n" -). --spec intersection(set(CXI), set(CXI)) -> set(CXI). -intersection(First, Second) -> - {Larger, Smaller} = order(First, Second), - take(Larger, to_list(Smaller)). - --file("src/gleam/set.gleam", 323). -?DOC( - " Creates a new set that contains members that are present in the first set\n" - " but not the second.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list\n" - " // -> [1]\n" - " ```\n" -). --spec difference(set(CXM), set(CXM)) -> set(CXM). -difference(First, Second) -> - drop(First, to_list(Second)). - --file("src/gleam/set.gleam", 344). -?DOC( - " Determines if a set is fully contained by another.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_subset(from_list([1]), from_list([1, 2]))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_subset(from_list([1, 2, 3]), from_list([3, 4, 5]))\n" - " // -> False\n" - " ```\n" -). --spec is_subset(set(CXQ), set(CXQ)) -> boolean(). -is_subset(First, Second) -> - intersection(First, Second) =:= First. - --file("src/gleam/set.gleam", 362). -?DOC( - " Determines if two sets contain no common members\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6]))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5]))\n" - " // -> False\n" - " ```\n" -). --spec is_disjoint(set(CXT), set(CXT)) -> boolean(). -is_disjoint(First, Second) -> - intersection(First, Second) =:= new(). - --file("src/gleam/set.gleam", 402). -?DOC( - " Calls a function for each member in a set, discarding the return\n" - " value.\n" - "\n" - " Useful for producing a side effect for every item of a set.\n" - "\n" - " ```gleam\n" - " let set = from_list([\"apple\", \"banana\", \"cherry\"])\n" - "\n" - " each(set, io.println)\n" - " // -> Nil\n" - " // apple\n" - " // banana\n" - " // cherry\n" - " ```\n" - "\n" - " The order of elements in the iteration is an implementation detail that\n" - " should not be relied upon.\n" -). --spec each(set(CYA), fun((CYA) -> any())) -> nil. -each(Set, Fun) -> - fold( - Set, - nil, - fun(Nil, Member) -> - Fun(Member), - Nil - end - ). - --file("src/gleam/set.gleam", 86). -?DOC( - " Inserts an member into the set.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(1)\n" - " |> insert(2)\n" - " |> size\n" - " // -> 2\n" - " ```\n" -). --spec insert(set(CVT), CVT) -> set(CVT). -insert(Set, Member) -> - {set, gleam@dict:insert(erlang:element(2, Set), Member, [])}. - --file("src/gleam/set.gleam", 167). -?DOC( - " Creates a new set of the members in a given list.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - " import gleam/list\n" - "\n" - " [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort(by: int.compare)\n" - " // -> [1, 2, 3, 4]\n" - " ```\n" -). --spec from_list(list(CWE)) -> set(CWE). -from_list(Members) -> - Dict = gleam@list:fold( - Members, - maps:new(), - fun(M, K) -> gleam@dict:insert(M, K, []) end - ), - {set, Dict}. - --file("src/gleam/set.gleam", 232). -?DOC( - " Creates a new set from a given set with the result of applying the given\n" - " function to each member.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 2, 3, 4])\n" - " |> map(with: fn(x) { x * 2 })\n" - " |> to_list\n" - " // -> [2, 4, 6, 8]\n" - " ```\n" -). --spec map(set(CWN), fun((CWN) -> CWP)) -> set(CWP). -map(Set, Fun) -> - fold(Set, new(), fun(Acc, Member) -> insert(Acc, Fun(Member)) end). - --file("src/gleam/set.gleam", 282). -?DOC( - " Creates a new set that contains all members of both given sets.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " union(from_list([1, 2]), from_list([2, 3])) |> to_list\n" - " // -> [1, 2, 3]\n" - " ```\n" -). --spec union(set(CWZ), set(CWZ)) -> set(CWZ). -union(First, Second) -> - {Larger, Smaller} = order(First, Second), - fold(Smaller, Larger, fun insert/2). - --file("src/gleam/set.gleam", 374). -?DOC( - " Creates a new set that contains members that are present in either set, but\n" - " not both.\n" - "\n" - " ```gleam\n" - " symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) |> to_list\n" - " // -> [1, 2, 4]\n" - " ```\n" -). --spec symmetric_difference(set(CXW), set(CXW)) -> set(CXW). -symmetric_difference(First, Second) -> - difference(union(First, Second), intersection(First, Second)). diff --git a/build/dev/javascript/gleam_stdlib/gleam@string.erl b/build/dev/javascript/gleam_stdlib/gleam@string.erl deleted file mode 100644 index 63006b8..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@string.erl +++ /dev/null @@ -1,1012 +0,0 @@ --module(gleam@string). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/string.gleam"). --export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, slice/3, crop/2, drop_end/2, contains/2, starts_with/2, ends_with/2, split_once/2, append/2, concat/1, repeat/2, join/2, pad_start/3, pad_end/3, trim_start/1, trim_end/1, trim/1, pop_grapheme/1, to_graphemes/1, split/2, to_utf_codepoints/1, from_utf_codepoints/1, utf_codepoint/1, utf_codepoint_to_int/1, to_option/1, first/1, last/1, capitalise/1, inspect/1, byte_size/1, drop_start/2]). --export_type([direction/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Strings in Gleam are UTF-8 binaries. They can be written in your code as\n" - " text surrounded by `\"double quotes\"`.\n" -). - --type direction() :: leading | trailing. - --file("src/gleam/string.gleam", 23). -?DOC( - " Determines if a `String` is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_empty(\"\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_empty(\"the world\")\n" - " // -> False\n" - " ```\n" -). --spec is_empty(binary()) -> boolean(). -is_empty(Str) -> - Str =:= <<""/utf8>>. - --file("src/gleam/string.gleam", 51). -?DOC( - " Gets the number of grapheme clusters in a given `String`.\n" - "\n" - " This function has to iterate across the whole string to count the number of\n" - " graphemes, so it runs in linear time. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " length(\"Gleam\")\n" - " // -> 5\n" - " ```\n" - "\n" - " ```gleam\n" - " length(\"ß↑e̊\")\n" - " // -> 3\n" - " ```\n" - "\n" - " ```gleam\n" - " length(\"\")\n" - " // -> 0\n" - " ```\n" -). --spec length(binary()) -> integer(). -length(String) -> - string:length(String). - --file("src/gleam/string.gleam", 65). -?DOC( - " Reverses a `String`.\n" - "\n" - " This function has to iterate across the whole `String` so it runs in linear\n" - " time. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " reverse(\"stressed\")\n" - " // -> \"desserts\"\n" - " ```\n" -). --spec reverse(binary()) -> binary(). -reverse(String) -> - _pipe = String, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = string:reverse(_pipe@1), - unicode:characters_to_binary(_pipe@2). - --file("src/gleam/string.gleam", 86). -?DOC( - " Creates a new `String` by replacing all occurrences of a given substring.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " replace(\"www.example.com\", each: \".\", with: \"-\")\n" - " // -> \"www-example-com\"\n" - " ```\n" - "\n" - " ```gleam\n" - " replace(\"a,b,c,d,e\", each: \",\", with: \"/\")\n" - " // -> \"a/b/c/d/e\"\n" - " ```\n" -). --spec replace(binary(), binary(), binary()) -> binary(). -replace(String, Pattern, Substitute) -> - _pipe = String, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = gleam_stdlib:string_replace(_pipe@1, Pattern, Substitute), - unicode:characters_to_binary(_pipe@2). - --file("src/gleam/string.gleam", 111). -?DOC( - " Creates a new `String` with all the graphemes in the input `String` converted to\n" - " lowercase.\n" - "\n" - " Useful for case-insensitive comparisons.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lowercase(\"X-FILES\")\n" - " // -> \"x-files\"\n" - " ```\n" -). --spec lowercase(binary()) -> binary(). -lowercase(String) -> - string:lowercase(String). - --file("src/gleam/string.gleam", 127). -?DOC( - " Creates a new `String` with all the graphemes in the input `String` converted to\n" - " uppercase.\n" - "\n" - " Useful for case-insensitive comparisons and VIRTUAL YELLING.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " uppercase(\"skinner\")\n" - " // -> \"SKINNER\"\n" - " ```\n" -). --spec uppercase(binary()) -> binary(). -uppercase(String) -> - string:uppercase(String). - --file("src/gleam/string.gleam", 145). -?DOC( - " Compares two `String`s to see which is \"larger\" by comparing their graphemes.\n" - "\n" - " This does not compare the size or length of the given `String`s.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(\"Anthony\", \"Anthony\")\n" - " // -> order.Eq\n" - " ```\n" - "\n" - " ```gleam\n" - " compare(\"A\", \"B\")\n" - " // -> order.Lt\n" - " ```\n" -). --spec compare(binary(), binary()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - _ -> - case gleam_stdlib:less_than(A, B) of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/string.gleam", 194). -?DOC( - " Takes a substring given a start grapheme index and a length. Negative indexes\n" - " are taken starting from the *end* of the list.\n" - "\n" - " This function runs in linear time with the size of the index and the\n" - " length. Negative indexes are linear with the size of the input string in\n" - " addition to the other costs.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: 1, length: 2)\n" - " // -> \"le\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: 1, length: 10)\n" - " // -> \"leam\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: 10, length: 3)\n" - " // -> \"\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: -2, length: 2)\n" - " // -> \"am\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: -12, length: 2)\n" - " // -> \"\"\n" - " ```\n" -). --spec slice(binary(), integer(), integer()) -> binary(). -slice(String, Idx, Len) -> - case Len =< 0 of - true -> - <<""/utf8>>; - - false -> - case Idx < 0 of - true -> - Translated_idx = string:length(String) + Idx, - case Translated_idx < 0 of - true -> - <<""/utf8>>; - - false -> - gleam_stdlib:slice(String, Translated_idx, Len) - end; - - false -> - gleam_stdlib:slice(String, Idx, Len) - end - end. - --file("src/gleam/string.gleam", 232). -?DOC( - " Drops contents of the first `String` that occur before the second `String`.\n" - " If the `from` string does not contain the `before` string, `from` is\n" - " returned unchanged.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " crop(from: \"The Lone Gunmen\", before: \"Lone\")\n" - " // -> \"Lone Gunmen\"\n" - " ```\n" -). --spec crop(binary(), binary()) -> binary(). -crop(String, Substring) -> - gleam_stdlib:crop_string(String, Substring). - --file("src/gleam/string.gleam", 268). -?DOC( - " Drops *n* graphemes from the end of a `String`.\n" - "\n" - " This function traverses the full string, so it runs in linear time with the\n" - " size of the string. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop_end(from: \"Cigarette Smoking Man\", up_to: 2)\n" - " // -> \"Cigarette Smoking M\"\n" - " ```\n" -). --spec drop_end(binary(), integer()) -> binary(). -drop_end(String, Num_graphemes) -> - case Num_graphemes =< 0 of - true -> - String; - - false -> - slice(String, 0, string:length(String) - Num_graphemes) - end. - --file("src/gleam/string.gleam", 296). -?DOC( - " Checks if the first `String` contains the second.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " contains(does: \"theory\", contain: \"ory\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " contains(does: \"theory\", contain: \"the\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " contains(does: \"theory\", contain: \"THE\")\n" - " // -> False\n" - " ```\n" -). --spec contains(binary(), binary()) -> boolean(). -contains(Haystack, Needle) -> - gleam_stdlib:contains_string(Haystack, Needle). - --file("src/gleam/string.gleam", 309). -?DOC( - " Checks whether the first `String` starts with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " starts_with(\"theory\", \"ory\")\n" - " // -> False\n" - " ```\n" -). --spec starts_with(binary(), binary()) -> boolean(). -starts_with(String, Prefix) -> - gleam_stdlib:string_starts_with(String, Prefix). - --file("src/gleam/string.gleam", 322). -?DOC( - " Checks whether the first `String` ends with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " ends_with(\"theory\", \"ory\")\n" - " // -> True\n" - " ```\n" -). --spec ends_with(binary(), binary()) -> boolean(). -ends_with(String, Suffix) -> - gleam_stdlib:string_ends_with(String, Suffix). - --file("src/gleam/string.gleam", 361). -?DOC( - " Splits a `String` a single time on the given substring.\n" - "\n" - " Returns an `Error` if substring not present.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split_once(\"home/gleam/desktop/\", on: \"/\")\n" - " // -> Ok(#(\"home\", \"gleam/desktop/\"))\n" - " ```\n" - "\n" - " ```gleam\n" - " split_once(\"home/gleam/desktop/\", on: \"?\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec split_once(binary(), binary()) -> {ok, {binary(), binary()}} | - {error, nil}. -split_once(String, Substring) -> - case string:split(String, Substring) of - [First, Rest] -> - {ok, {First, Rest}}; - - _ -> - {error, nil} - end. - --file("src/gleam/string.gleam", 392). -?DOC( - " Creates a new `String` by joining two `String`s together.\n" - "\n" - " This function typically copies both `String`s and runs in linear time, but\n" - " the exact behaviour will depend on how the runtime you are using optimises\n" - " your code. Benchmark and profile your code if you need to understand its\n" - " performance better.\n" - "\n" - " If you are joining together large string and want to avoid copying any data\n" - " you may want to investigate using the [`string_tree`](../gleam/string_tree.html)\n" - " module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " append(to: \"butter\", suffix: \"fly\")\n" - " // -> \"butterfly\"\n" - " ```\n" -). --spec append(binary(), binary()) -> binary(). -append(First, Second) -> - <>. - --file("src/gleam/string.gleam", 412). --spec concat_loop(list(binary()), binary()) -> binary(). -concat_loop(Strings, Accumulator) -> - case Strings of - [String | Strings@1] -> - concat_loop(Strings@1, <>); - - [] -> - Accumulator - end. - --file("src/gleam/string.gleam", 408). -?DOC( - " Creates a new `String` by joining many `String`s together.\n" - "\n" - " This function copies all the `String`s and runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " concat([\"never\", \"the\", \"less\"])\n" - " // -> \"nevertheless\"\n" - " ```\n" -). --spec concat(list(binary())) -> binary(). -concat(Strings) -> - erlang:list_to_binary(Strings). - --file("src/gleam/string.gleam", 437). --spec repeat_loop(integer(), binary(), binary()) -> binary(). -repeat_loop(Times, Doubling_acc, Acc) -> - Acc@1 = case Times rem 2 of - 0 -> - Acc; - - _ -> - <> - end, - Times@1 = Times div 2, - case Times@1 =< 0 of - true -> - Acc@1; - - false -> - repeat_loop( - Times@1, - <>, - Acc@1 - ) - end. - --file("src/gleam/string.gleam", 430). -?DOC( - " Creates a new `String` by repeating a `String` a given number of times.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " repeat(\"ha\", times: 3)\n" - " // -> \"hahaha\"\n" - " ```\n" -). --spec repeat(binary(), integer()) -> binary(). -repeat(String, Times) -> - case Times =< 0 of - true -> - <<""/utf8>>; - - false -> - repeat_loop(Times, String, <<""/utf8>>) - end. - --file("src/gleam/string.gleam", 467). --spec join_loop(list(binary()), binary(), binary()) -> binary(). -join_loop(Strings, Separator, Accumulator) -> - case Strings of - [] -> - Accumulator; - - [String | Strings@1] -> - join_loop( - Strings@1, - Separator, - <<<>/binary, - String/binary>> - ) - end. - --file("src/gleam/string.gleam", 460). -?DOC( - " Joins many `String`s together with a given separator.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " join([\"home\",\"evan\",\"Desktop\"], with: \"/\")\n" - " // -> \"home/evan/Desktop\"\n" - " ```\n" -). --spec join(list(binary()), binary()) -> binary(). -join(Strings, Separator) -> - case Strings of - [] -> - <<""/utf8>>; - - [First | Rest] -> - join_loop(Rest, Separator, First) - end. - --file("src/gleam/string.gleam", 545). --spec padding(integer(), binary()) -> binary(). -padding(Size, Pad_string) -> - Pad_string_length = string:length(Pad_string), - Num_pads = case Pad_string_length of - 0 -> 0; - Gleam@denominator -> Size div Gleam@denominator - end, - Extra = case Pad_string_length of - 0 -> 0; - Gleam@denominator@1 -> Size rem Gleam@denominator@1 - end, - <<(repeat(Pad_string, Num_pads))/binary, - (slice(Pad_string, 0, Extra))/binary>>. - --file("src/gleam/string.gleam", 498). -?DOC( - " Pads the start of a `String` until it has a given length.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " pad_start(\"121\", to: 5, with: \".\")\n" - " // -> \"..121\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_start(\"121\", to: 3, with: \".\")\n" - " // -> \"121\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_start(\"121\", to: 2, with: \".\")\n" - " // -> \"121\"\n" - " ```\n" -). --spec pad_start(binary(), integer(), binary()) -> binary(). -pad_start(String, Desired_length, Pad_string) -> - Current_length = string:length(String), - To_pad_length = Desired_length - Current_length, - case To_pad_length =< 0 of - true -> - String; - - false -> - <<(padding(To_pad_length, Pad_string))/binary, String/binary>> - end. - --file("src/gleam/string.gleam", 531). -?DOC( - " Pads the end of a `String` until it has a given length.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " pad_end(\"123\", to: 5, with: \".\")\n" - " // -> \"123..\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_end(\"123\", to: 3, with: \".\")\n" - " // -> \"123\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_end(\"123\", to: 2, with: \".\")\n" - " // -> \"123\"\n" - " ```\n" -). --spec pad_end(binary(), integer(), binary()) -> binary(). -pad_end(String, Desired_length, Pad_string) -> - Current_length = string:length(String), - To_pad_length = Desired_length - Current_length, - case To_pad_length =< 0 of - true -> - String; - - false -> - <> - end. - --file("src/gleam/string.gleam", 589). -?DOC( - " Removes whitespace at the start of a `String`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " trim_start(\" hats \\n\")\n" - " // -> \"hats \\n\"\n" - " ```\n" -). --spec trim_start(binary()) -> binary(). -trim_start(String) -> - string:trim(String, leading). - --file("src/gleam/string.gleam", 603). -?DOC( - " Removes whitespace at the end of a `String`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " trim_end(\" hats \\n\")\n" - " // -> \" hats\"\n" - " ```\n" -). --spec trim_end(binary()) -> binary(). -trim_end(String) -> - string:trim(String, trailing). - --file("src/gleam/string.gleam", 567). -?DOC( - " Removes whitespace on both sides of a `String`.\n" - "\n" - " Whitespace in this function is the set of nonbreakable whitespace\n" - " codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1].\n" - "\n" - " [1]: https://unicode.org/reports/tr31/\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " trim(\" hats \\n\")\n" - " // -> \"hats\"\n" - " ```\n" -). --spec trim(binary()) -> binary(). -trim(String) -> - _pipe = String, - _pipe@1 = trim_start(_pipe), - trim_end(_pipe@1). - --file("src/gleam/string.gleam", 630). -?DOC( - " Splits a non-empty `String` into its first element (head) and rest (tail).\n" - " This lets you pattern match on `String`s exactly as you would with lists.\n" - "\n" - " ## Performance\n" - "\n" - " There is a notable overhead to using this function, so you may not want to\n" - " use it in a tight loop. If you wish to efficiently parse a string you may\n" - " want to use alternatives such as the [splitter package](https://hex.pm/packages/splitter).\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " pop_grapheme(\"gleam\")\n" - " // -> Ok(#(\"g\", \"leam\"))\n" - " ```\n" - "\n" - " ```gleam\n" - " pop_grapheme(\"\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec pop_grapheme(binary()) -> {ok, {binary(), binary()}} | {error, nil}. -pop_grapheme(String) -> - gleam_stdlib:string_pop_grapheme(String). - --file("src/gleam/string.gleam", 647). --spec to_graphemes_loop(binary(), list(binary())) -> list(binary()). -to_graphemes_loop(String, Acc) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {Grapheme, Rest}} -> - to_graphemes_loop(Rest, [Grapheme | Acc]); - - {error, _} -> - Acc - end. - --file("src/gleam/string.gleam", 641). -?DOC( - " Converts a `String` to a list of\n" - " [graphemes](https://en.wikipedia.org/wiki/Grapheme).\n" - "\n" - " ```gleam\n" - " to_graphemes(\"abc\")\n" - " // -> [\"a\", \"b\", \"c\"]\n" - " ```\n" -). --spec to_graphemes(binary()) -> list(binary()). -to_graphemes(String) -> - _pipe = String, - _pipe@1 = to_graphemes_loop(_pipe, []), - lists:reverse(_pipe@1). - --file("src/gleam/string.gleam", 333). -?DOC( - " Creates a list of `String`s by splitting a given string on a given substring.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split(\"home/gleam/desktop/\", on: \"/\")\n" - " // -> [\"home\", \"gleam\", \"desktop\", \"\"]\n" - " ```\n" -). --spec split(binary(), binary()) -> list(binary()). -split(X, Substring) -> - case Substring of - <<""/utf8>> -> - to_graphemes(X); - - _ -> - _pipe = X, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = gleam@string_tree:split(_pipe@1, Substring), - gleam@list:map(_pipe@2, fun unicode:characters_to_binary/1) - end. - --file("src/gleam/string.gleam", 694). --spec to_utf_codepoints_loop(bitstring(), list(integer())) -> list(integer()). -to_utf_codepoints_loop(Bit_array, Acc) -> - case Bit_array of - <> -> - to_utf_codepoints_loop(Rest, [First | Acc]); - - _ -> - lists:reverse(Acc) - end. - --file("src/gleam/string.gleam", 689). --spec do_to_utf_codepoints(binary()) -> list(integer()). -do_to_utf_codepoints(String) -> - to_utf_codepoints_loop(<>, []). - --file("src/gleam/string.gleam", 684). -?DOC( - " Converts a `String` to a `List` of `UtfCodepoint`.\n" - "\n" - " See and\n" - " for an\n" - " explanation on code points.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " \"a\" |> to_utf_codepoints\n" - " // -> [UtfCodepoint(97)]\n" - " ```\n" - "\n" - " ```gleam\n" - " // Semantically the same as:\n" - " // [\"🏳\", \"️\", \"‍\", \"🌈\"] or:\n" - " // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow]\n" - " \"🏳️‍🌈\" |> to_utf_codepoints\n" - " // -> [\n" - " // UtfCodepoint(127987),\n" - " // UtfCodepoint(65039),\n" - " // UtfCodepoint(8205),\n" - " // UtfCodepoint(127752),\n" - " // ]\n" - " ```\n" -). --spec to_utf_codepoints(binary()) -> list(integer()). -to_utf_codepoints(String) -> - do_to_utf_codepoints(String). - --file("src/gleam/string.gleam", 734). -?DOC( - " Converts a `List` of `UtfCodepoint`s to a `String`.\n" - "\n" - " See and\n" - " for an\n" - " explanation on code points.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(a) = utf_codepoint(97)\n" - " let assert Ok(b) = utf_codepoint(98)\n" - " let assert Ok(c) = utf_codepoint(99)\n" - " from_utf_codepoints([a, b, c])\n" - " // -> \"abc\"\n" - " ```\n" -). --spec from_utf_codepoints(list(integer())) -> binary(). -from_utf_codepoints(Utf_codepoints) -> - gleam_stdlib:utf_codepoint_list_to_string(Utf_codepoints). - --file("src/gleam/string.gleam", 740). -?DOC( - " Converts an integer to a `UtfCodepoint`.\n" - "\n" - " Returns an `Error` if the integer does not represent a valid UTF codepoint.\n" -). --spec utf_codepoint(integer()) -> {ok, integer()} | {error, nil}. -utf_codepoint(Value) -> - case Value of - I when I > 1114111 -> - {error, nil}; - - I@1 when (I@1 >= 55296) andalso (I@1 =< 57343) -> - {error, nil}; - - I@2 when I@2 < 0 -> - {error, nil}; - - I@3 -> - {ok, gleam_stdlib:identity(I@3)} - end. - --file("src/gleam/string.gleam", 761). -?DOC( - " Converts an UtfCodepoint to its ordinal code point value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert [utf_codepoint, ..] = to_utf_codepoints(\"💜\")\n" - " utf_codepoint_to_int(utf_codepoint)\n" - " // -> 128156\n" - " ```\n" -). --spec utf_codepoint_to_int(integer()) -> integer(). -utf_codepoint_to_int(Cp) -> - gleam_stdlib:identity(Cp). - --file("src/gleam/string.gleam", 778). -?DOC( - " Converts a `String` into `Option(String)` where an empty `String` becomes\n" - " `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_option(\"\")\n" - " // -> None\n" - " ```\n" - "\n" - " ```gleam\n" - " to_option(\"hats\")\n" - " // -> Some(\"hats\")\n" - " ```\n" -). --spec to_option(binary()) -> gleam@option:option(binary()). -to_option(String) -> - case String of - <<""/utf8>> -> - none; - - _ -> - {some, String} - end. - --file("src/gleam/string.gleam", 801). -?DOC( - " Returns the first grapheme cluster in a given `String` and wraps it in a\n" - " `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.\n" - " Otherwise, it returns `Ok(String)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " first(\"\")\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " first(\"icecream\")\n" - " // -> Ok(\"i\")\n" - " ```\n" -). --spec first(binary()) -> {ok, binary()} | {error, nil}. -first(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, _}} -> - {ok, First}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/string.gleam", 827). -?DOC( - " Returns the last grapheme cluster in a given `String` and wraps it in a\n" - " `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.\n" - " Otherwise, it returns `Ok(String)`.\n" - "\n" - " This function traverses the full string, so it runs in linear time with the\n" - " length of the string. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " last(\"\")\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " last(\"icecream\")\n" - " // -> Ok(\"m\")\n" - " ```\n" -). --spec last(binary()) -> {ok, binary()} | {error, nil}. -last(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, <<""/utf8>>}} -> - {ok, First}; - - {ok, {_, Rest}} -> - {ok, slice(Rest, -1, 1)}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/string.gleam", 845). -?DOC( - " Creates a new `String` with the first grapheme in the input `String`\n" - " converted to uppercase and the remaining graphemes to lowercase.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " capitalise(\"mamouna\")\n" - " // -> \"Mamouna\"\n" - " ```\n" -). --spec capitalise(binary()) -> binary(). -capitalise(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, Rest}} -> - append(string:uppercase(First), string:lowercase(Rest)); - - {error, _} -> - <<""/utf8>> - end. - --file("src/gleam/string.gleam", 876). -?DOC( - " Returns a `String` representation of a term in Gleam syntax.\n" - "\n" - " This may be occasionally useful for quick-and-dirty printing of values in\n" - " scripts. For error reporting and other uses prefer constructing strings by\n" - " pattern matching on the values.\n" - "\n" - " ## Limitations\n" - "\n" - " The output format of this function is not stable and could change at any\n" - " time. The output is not suitable for parsing.\n" - "\n" - " This function works using runtime reflection, so the output may not be\n" - " perfectly accurate for data structures where the runtime structure doesn't\n" - " hold enough information to determine the original syntax. For example,\n" - " tuples with an Erlang atom in the first position will be mistaken for Gleam\n" - " records.\n" - "\n" - " ## Security and safety\n" - "\n" - " There is no limit to how large the strings that this function can produce.\n" - " Be careful not to call this function with large data structures or you\n" - " could use very large amounts of memory, potentially causing runtime\n" - " problems.\n" -). --spec inspect(any()) -> binary(). -inspect(Term) -> - _pipe = Term, - _pipe@1 = gleam_stdlib:inspect(_pipe), - unicode:characters_to_binary(_pipe@1). - --file("src/gleam/string.gleam", 900). -?DOC( - " Returns the number of bytes in a `String`.\n" - "\n" - " This function runs in constant time on Erlang and in linear time on\n" - " JavaScript.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " byte_size(\"🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻\")\n" - " // -> 58\n" - " ```\n" -). --spec byte_size(binary()) -> integer(). -byte_size(String) -> - erlang:byte_size(String). - --file("src/gleam/string.gleam", 245). -?DOC( - " Drops *n* graphemes from the start of a `String`.\n" - "\n" - " This function runs in linear time with the number of graphemes to drop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop_start(from: \"The Lone Gunmen\", up_to: 2)\n" - " // -> \"e Lone Gunmen\"\n" - " ```\n" -). --spec drop_start(binary(), integer()) -> binary(). -drop_start(String, Num_graphemes) -> - case Num_graphemes =< 0 of - true -> - String; - - false -> - Prefix = gleam_stdlib:slice(String, 0, Num_graphemes), - Prefix_size = erlang:byte_size(Prefix), - binary:part( - String, - Prefix_size, - erlang:byte_size(String) - Prefix_size - ) - end. diff --git a/build/dev/javascript/gleam_stdlib/gleam@string_tree.erl b/build/dev/javascript/gleam_stdlib/gleam@string_tree.erl deleted file mode 100644 index 0d72b4d..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@string_tree.erl +++ /dev/null @@ -1,207 +0,0 @@ --module(gleam@string_tree). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/string_tree.gleam"). --export([append_tree/2, prepend_tree/2, from_strings/1, new/0, concat/1, from_string/1, prepend/2, append/2, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]). --export_type([string_tree/0, direction/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type string_tree() :: any(). - --type direction() :: all. - --file("src/gleam/string_tree.gleam", 61). -?DOC( - " Appends some `StringTree` onto the end of another.\n" - "\n" - " Runs in constant time.\n" -). --spec append_tree(string_tree(), string_tree()) -> string_tree(). -append_tree(Tree, Suffix) -> - gleam_stdlib:iodata_append(Tree, Suffix). - --file("src/gleam/string_tree.gleam", 48). -?DOC( - " Prepends some `StringTree` onto the start of another.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend_tree(string_tree(), string_tree()) -> string_tree(). -prepend_tree(Tree, Prefix) -> - gleam_stdlib:iodata_append(Prefix, Tree). - --file("src/gleam/string_tree.gleam", 69). -?DOC( - " Converts a list of strings into a `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec from_strings(list(binary())) -> string_tree(). -from_strings(Strings) -> - gleam_stdlib:identity(Strings). - --file("src/gleam/string_tree.gleam", 24). -?DOC( - " Create an empty `StringTree`. Useful as the start of a pipe chaining many\n" - " trees together.\n" -). --spec new() -> string_tree(). -new() -> - gleam_stdlib:identity([]). - --file("src/gleam/string_tree.gleam", 77). -?DOC( - " Joins a list of trees into a single tree.\n" - "\n" - " Runs in constant time.\n" -). --spec concat(list(string_tree())) -> string_tree(). -concat(Trees) -> - gleam_stdlib:identity(Trees). - --file("src/gleam/string_tree.gleam", 85). -?DOC( - " Converts a string into a `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec from_string(binary()) -> string_tree(). -from_string(String) -> - gleam_stdlib:identity(String). - --file("src/gleam/string_tree.gleam", 32). -?DOC( - " Prepends a `String` onto the start of some `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend(string_tree(), binary()) -> string_tree(). -prepend(Tree, Prefix) -> - gleam_stdlib:iodata_append(gleam_stdlib:identity(Prefix), Tree). - --file("src/gleam/string_tree.gleam", 40). -?DOC( - " Appends a `String` onto the end of some `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec append(string_tree(), binary()) -> string_tree(). -append(Tree, Second) -> - gleam_stdlib:iodata_append(Tree, gleam_stdlib:identity(Second)). - --file("src/gleam/string_tree.gleam", 94). -?DOC( - " Turns a `StringTree` into a `String`\n" - "\n" - " This function is implemented natively by the virtual machine and is highly\n" - " optimised.\n" -). --spec to_string(string_tree()) -> binary(). -to_string(Tree) -> - unicode:characters_to_binary(Tree). - --file("src/gleam/string_tree.gleam", 100). -?DOC(" Returns the size of the `StringTree` in bytes.\n"). --spec byte_size(string_tree()) -> integer(). -byte_size(Tree) -> - erlang:iolist_size(Tree). - --file("src/gleam/string_tree.gleam", 104). -?DOC(" Joins the given trees into a new tree separated with the given string.\n"). --spec join(list(string_tree()), binary()) -> string_tree(). -join(Trees, Sep) -> - _pipe = Trees, - _pipe@1 = gleam@list:intersperse(_pipe, gleam_stdlib:identity(Sep)), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/string_tree.gleam", 115). -?DOC( - " Converts a `StringTree` to a new one where the contents have been\n" - " lowercased.\n" -). --spec lowercase(string_tree()) -> string_tree(). -lowercase(Tree) -> - string:lowercase(Tree). - --file("src/gleam/string_tree.gleam", 122). -?DOC( - " Converts a `StringTree` to a new one where the contents have been\n" - " uppercased.\n" -). --spec uppercase(string_tree()) -> string_tree(). -uppercase(Tree) -> - string:uppercase(Tree). - --file("src/gleam/string_tree.gleam", 127). -?DOC(" Converts a `StringTree` to a new one with the contents reversed.\n"). --spec reverse(string_tree()) -> string_tree(). -reverse(Tree) -> - string:reverse(Tree). - --file("src/gleam/string_tree.gleam", 145). -?DOC(" Splits a `StringTree` on a given pattern into a list of trees.\n"). --spec split(string_tree(), binary()) -> list(string_tree()). -split(Tree, Pattern) -> - string:split(Tree, Pattern, all). - --file("src/gleam/string_tree.gleam", 156). -?DOC(" Replaces all instances of a pattern with a given string substitute.\n"). --spec replace(string_tree(), binary(), binary()) -> string_tree(). -replace(Tree, Pattern, Substitute) -> - gleam_stdlib:string_replace(Tree, Pattern, Substitute). - --file("src/gleam/string_tree.gleam", 182). -?DOC( - " Compares two string trees to determine if they have the same textual\n" - " content.\n" - "\n" - " Comparing two string trees using the `==` operator may return `False` even\n" - " if they have the same content as they may have been build in different ways,\n" - " so using this function is often preferred.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_strings([\"a\", \"b\"]) == from_string(\"ab\")\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_equal(from_strings([\"a\", \"b\"]), from_string(\"ab\"))\n" - " // -> True\n" - " ```\n" -). --spec is_equal(string_tree(), string_tree()) -> boolean(). -is_equal(A, B) -> - string:equal(A, B). - --file("src/gleam/string_tree.gleam", 206). -?DOC( - " Inspects a `StringTree` to determine if it is equivalent to an empty string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_string(\"ok\") |> is_empty\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " from_string(\"\") |> is_empty\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " from_strings([]) |> is_empty\n" - " // -> True\n" - " ```\n" -). --spec is_empty(string_tree()) -> boolean(). -is_empty(Tree) -> - string:is_empty(Tree). diff --git a/build/dev/javascript/gleam_stdlib/gleam@uri.erl b/build/dev/javascript/gleam_stdlib/gleam@uri.erl deleted file mode 100644 index 0819463..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam@uri.erl +++ /dev/null @@ -1,1044 +0,0 @@ --module(gleam@uri). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/uri.gleam"). --export([parse_query/1, percent_encode/1, query_to_string/1, percent_decode/1, path_segments/1, to_string/1, origin/1, merge/2, parse/1]). --export_type([uri/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Utilities for working with URIs\n" - "\n" - " This module provides functions for working with URIs (for example, parsing\n" - " URIs or encoding query strings). The functions in this module are implemented\n" - " according to [RFC 3986](https://tools.ietf.org/html/rfc3986).\n" - "\n" - " Query encoding (Form encoding) is defined in the\n" - " [W3C specification](https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data).\n" -). - --type uri() :: {uri, - gleam@option:option(binary()), - gleam@option:option(binary()), - gleam@option:option(binary()), - gleam@option:option(integer()), - binary(), - gleam@option:option(binary()), - gleam@option:option(binary())}. - --file("src/gleam/uri.gleam", 289). --spec is_valid_host_within_brackets_char(integer()) -> boolean(). -is_valid_host_within_brackets_char(Char) -> - (((((48 >= Char) andalso (Char =< 57)) orelse ((65 >= Char) andalso (Char =< 90))) - orelse ((97 >= Char) andalso (Char =< 122))) - orelse (Char =:= 58)) - orelse (Char =:= 46). - --file("src/gleam/uri.gleam", 506). --spec parse_fragment(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_fragment(Rest, Pieces) -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - {some, Rest}}}. - --file("src/gleam/uri.gleam", 478). --spec parse_query_with_question_mark_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_query_with_question_mark_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"#"/utf8, Rest/binary>> when Size =:= 0 -> - parse_fragment(Rest, Pieces); - - <<"#"/utf8, Rest@1/binary>> -> - Query = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - {some, Query}, - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@1); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - {some, Original}, - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_query_with_question_mark_loop( - Original, - Rest@2, - Pieces, - Size + 1 - ) - end. - --file("src/gleam/uri.gleam", 471). --spec parse_query_with_question_mark(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_query_with_question_mark(Uri_string, Pieces) -> - parse_query_with_question_mark_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 437). --spec parse_path_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_path_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"?"/utf8, Rest/binary>> -> - Path = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Path, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest, Pieces@1); - - <<"#"/utf8, Rest@1/binary>> -> - Path@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Path@1, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@2); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Original, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_path_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 433). --spec parse_path(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_path(Uri_string, Pieces) -> - parse_path_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 388). --spec parse_port_loop(binary(), uri(), integer()) -> {ok, uri()} | {error, nil}. -parse_port_loop(Uri_string, Pieces, Port) -> - case Uri_string of - <<"0"/utf8, Rest/binary>> -> - parse_port_loop(Rest, Pieces, Port * 10); - - <<"1"/utf8, Rest@1/binary>> -> - parse_port_loop(Rest@1, Pieces, (Port * 10) + 1); - - <<"2"/utf8, Rest@2/binary>> -> - parse_port_loop(Rest@2, Pieces, (Port * 10) + 2); - - <<"3"/utf8, Rest@3/binary>> -> - parse_port_loop(Rest@3, Pieces, (Port * 10) + 3); - - <<"4"/utf8, Rest@4/binary>> -> - parse_port_loop(Rest@4, Pieces, (Port * 10) + 4); - - <<"5"/utf8, Rest@5/binary>> -> - parse_port_loop(Rest@5, Pieces, (Port * 10) + 5); - - <<"6"/utf8, Rest@6/binary>> -> - parse_port_loop(Rest@6, Pieces, (Port * 10) + 6); - - <<"7"/utf8, Rest@7/binary>> -> - parse_port_loop(Rest@7, Pieces, (Port * 10) + 7); - - <<"8"/utf8, Rest@8/binary>> -> - parse_port_loop(Rest@8, Pieces, (Port * 10) + 8); - - <<"9"/utf8, Rest@9/binary>> -> - parse_port_loop(Rest@9, Pieces, (Port * 10) + 9); - - <<"?"/utf8, Rest@10/binary>> -> - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@10, Pieces@1); - - <<"#"/utf8, Rest@11/binary>> -> - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@11, Pieces@2); - - <<"/"/utf8, _/binary>> -> - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@3); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 353). --spec parse_port(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_port(Uri_string, Pieces) -> - case Uri_string of - <<":0"/utf8, Rest/binary>> -> - parse_port_loop(Rest, Pieces, 0); - - <<":1"/utf8, Rest@1/binary>> -> - parse_port_loop(Rest@1, Pieces, 1); - - <<":2"/utf8, Rest@2/binary>> -> - parse_port_loop(Rest@2, Pieces, 2); - - <<":3"/utf8, Rest@3/binary>> -> - parse_port_loop(Rest@3, Pieces, 3); - - <<":4"/utf8, Rest@4/binary>> -> - parse_port_loop(Rest@4, Pieces, 4); - - <<":5"/utf8, Rest@5/binary>> -> - parse_port_loop(Rest@5, Pieces, 5); - - <<":6"/utf8, Rest@6/binary>> -> - parse_port_loop(Rest@6, Pieces, 6); - - <<":7"/utf8, Rest@7/binary>> -> - parse_port_loop(Rest@7, Pieces, 7); - - <<":8"/utf8, Rest@8/binary>> -> - parse_port_loop(Rest@8, Pieces, 8); - - <<":9"/utf8, Rest@9/binary>> -> - parse_port_loop(Rest@9, Pieces, 9); - - <<":"/utf8>> -> - {ok, Pieces}; - - <<""/utf8>> -> - {ok, Pieces}; - - <<"?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<":?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<"#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<":#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_path(Uri_string, Pieces); - - <<":"/utf8, Rest@12/binary>> -> - case Rest@12 of - <<"/"/utf8, _/binary>> -> - parse_path(Rest@12, Pieces); - - _ -> - {error, nil} - end; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 309). --spec parse_host_outside_of_brackets_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_host_outside_of_brackets_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Original}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<":"/utf8, _/binary>> -> - Host = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Uri_string, Pieces@1); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@1}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@2}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest, Pieces@3); - - <<"#"/utf8, Rest@1/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@3}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@4); - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_host_outside_of_brackets_loop( - Original, - Rest@2, - Pieces, - Size + 1 - ) - end. - --file("src/gleam/uri.gleam", 229). --spec parse_host_within_brackets_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_host_within_brackets_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Uri_string}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<"]"/utf8, Rest/binary>> when Size =:= 0 -> - parse_port(Rest, Pieces); - - <<"]"/utf8, Rest@1/binary>> -> - Host = binary:part(Original, 0, Size + 1), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Rest@1, Pieces@1); - - <<"/"/utf8, _/binary>> when Size =:= 0 -> - parse_path(Uri_string, Pieces); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@1}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest@2/binary>> when Size =:= 0 -> - parse_query_with_question_mark(Rest@2, Pieces); - - <<"?"/utf8, Rest@3/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@2}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@3, Pieces@3); - - <<"#"/utf8, Rest@4/binary>> when Size =:= 0 -> - parse_fragment(Rest@4, Pieces); - - <<"#"/utf8, Rest@5/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@3}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@5, Pieces@4); - - _ -> - {Char, Rest@6} = gleam_stdlib:string_pop_codeunit(Uri_string), - case is_valid_host_within_brackets_char(Char) of - true -> - parse_host_within_brackets_loop( - Original, - Rest@6, - Pieces, - Size + 1 - ); - - false -> - parse_host_outside_of_brackets_loop( - Original, - Original, - Pieces, - 0 - ) - end - end. - --file("src/gleam/uri.gleam", 222). --spec parse_host_within_brackets(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_host_within_brackets(Uri_string, Pieces) -> - parse_host_within_brackets_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 302). --spec parse_host_outside_of_brackets(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_host_outside_of_brackets(Uri_string, Pieces) -> - parse_host_outside_of_brackets_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 199). --spec parse_host(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_host(Uri_string, Pieces) -> - case Uri_string of - <<"["/utf8, _/binary>> -> - parse_host_within_brackets(Uri_string, Pieces); - - <<":"/utf8, _/binary>> -> - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Uri_string, Pieces@1); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - parse_host_outside_of_brackets(Uri_string, Pieces) - end. - --file("src/gleam/uri.gleam", 167). --spec parse_userinfo_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_userinfo_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"@"/utf8, Rest/binary>> when Size =:= 0 -> - parse_host(Rest, Pieces); - - <<"@"/utf8, Rest@1/binary>> -> - Userinfo = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - {some, Userinfo}, - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_host(Rest@1, Pieces@1); - - <<""/utf8>> -> - parse_host(Original, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - <<"?"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - <<"#"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_userinfo_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 163). --spec parse_authority_pieces(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_authority_pieces(String, Pieces) -> - parse_userinfo_loop(String, String, Pieces, 0). - --file("src/gleam/uri.gleam", 150). --spec parse_authority_with_slashes(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_authority_with_slashes(Uri_string, Pieces) -> - case Uri_string of - <<"//"/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<"//"/utf8, Rest/binary>> -> - parse_authority_pieces(Rest, Pieces); - - _ -> - parse_path(Uri_string, Pieces) - end. - --file("src/gleam/uri.gleam", 91). --spec parse_scheme_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_scheme_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"/"/utf8, _/binary>> when Size =:= 0 -> - parse_authority_with_slashes(Uri_string, Pieces); - - <<"/"/utf8, _/binary>> -> - Scheme = binary:part(Original, 0, Size), - Pieces@1 = {uri, - {some, string:lowercase(Scheme)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_authority_with_slashes(Uri_string, Pieces@1); - - <<"?"/utf8, Rest/binary>> when Size =:= 0 -> - parse_query_with_question_mark(Rest, Pieces); - - <<"?"/utf8, Rest@1/binary>> -> - Scheme@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - {some, string:lowercase(Scheme@1)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@1, Pieces@2); - - <<"#"/utf8, Rest@2/binary>> when Size =:= 0 -> - parse_fragment(Rest@2, Pieces); - - <<"#"/utf8, Rest@3/binary>> -> - Scheme@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - {some, string:lowercase(Scheme@2)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@3, Pieces@3); - - <<":"/utf8, _/binary>> when Size =:= 0 -> - {error, nil}; - - <<":"/utf8, Rest@4/binary>> -> - Scheme@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - {some, string:lowercase(Scheme@3)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_authority_with_slashes(Rest@4, Pieces@4); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Original, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@5} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_scheme_loop(Original, Rest@5, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 537). -?DOC( - " Parses an urlencoded query string into a list of key value pairs.\n" - " Returns an error for invalid encoding.\n" - "\n" - " The opposite operation is `uri.query_to_string`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse_query(\"a=1&b=2\")\n" - " // -> Ok([#(\"a\", \"1\"), #(\"b\", \"2\")])\n" - " ```\n" -). --spec parse_query(binary()) -> {ok, list({binary(), binary()})} | {error, nil}. -parse_query(Query) -> - gleam_stdlib:parse_query(Query). - --file("src/gleam/uri.gleam", 573). -?DOC( - " Encodes a string into a percent encoded representation.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " percent_encode(\"100% great\")\n" - " // -> \"100%25%20great\"\n" - " ```\n" -). --spec percent_encode(binary()) -> binary(). -percent_encode(Value) -> - gleam_stdlib:percent_encode(Value). - --file("src/gleam/uri.gleam", 558). --spec query_pair({binary(), binary()}) -> gleam@string_tree:string_tree(). -query_pair(Pair) -> - gleam_stdlib:identity( - [gleam_stdlib:percent_encode(erlang:element(1, Pair)), - <<"="/utf8>>, - gleam_stdlib:percent_encode(erlang:element(2, Pair))] - ). - --file("src/gleam/uri.gleam", 550). -?DOC( - " Encodes a list of key value pairs as a URI query string.\n" - "\n" - " The opposite operation is `uri.parse_query`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " query_to_string([#(\"a\", \"1\"), #(\"b\", \"2\")])\n" - " // -> \"a=1&b=2\"\n" - " ```\n" -). --spec query_to_string(list({binary(), binary()})) -> binary(). -query_to_string(Query) -> - _pipe = Query, - _pipe@1 = gleam@list:map(_pipe, fun query_pair/1), - _pipe@2 = gleam@list:intersperse( - _pipe@1, - gleam_stdlib:identity(<<"&"/utf8>>) - ), - _pipe@3 = gleam_stdlib:identity(_pipe@2), - unicode:characters_to_binary(_pipe@3). - --file("src/gleam/uri.gleam", 586). -?DOC( - " Decodes a percent encoded string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " percent_decode(\"100%25%20great+fun\")\n" - " // -> Ok(\"100% great+fun\")\n" - " ```\n" -). --spec percent_decode(binary()) -> {ok, binary()} | {error, nil}. -percent_decode(Value) -> - gleam_stdlib:percent_decode(Value). - --file("src/gleam/uri.gleam", 608). --spec remove_dot_segments_loop(list(binary()), list(binary())) -> list(binary()). -remove_dot_segments_loop(Input, Accumulator) -> - case Input of - [] -> - lists:reverse(Accumulator); - - [Segment | Rest] -> - Accumulator@5 = case {Segment, Accumulator} of - {<<""/utf8>>, Accumulator@1} -> - Accumulator@1; - - {<<"."/utf8>>, Accumulator@2} -> - Accumulator@2; - - {<<".."/utf8>>, []} -> - []; - - {<<".."/utf8>>, [_ | Accumulator@3]} -> - Accumulator@3; - - {Segment@1, Accumulator@4} -> - [Segment@1 | Accumulator@4] - end, - remove_dot_segments_loop(Rest, Accumulator@5) - end. - --file("src/gleam/uri.gleam", 604). --spec remove_dot_segments(list(binary())) -> list(binary()). -remove_dot_segments(Input) -> - remove_dot_segments_loop(Input, []). - --file("src/gleam/uri.gleam", 600). -?DOC( - " Splits the path section of a URI into it's constituent segments.\n" - "\n" - " Removes empty segments and resolves dot-segments as specified in\n" - " [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " path_segments(\"/users/1\")\n" - " // -> [\"users\" ,\"1\"]\n" - " ```\n" -). --spec path_segments(binary()) -> list(binary()). -path_segments(Path) -> - remove_dot_segments(gleam@string:split(Path, <<"/"/utf8>>)). - --file("src/gleam/uri.gleam", 639). -?DOC( - " Encodes a `Uri` value as a URI string.\n" - "\n" - " The opposite operation is `uri.parse`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let uri = Uri(..empty, scheme: Some(\"https\"), host: Some(\"example.com\"))\n" - " to_string(uri)\n" - " // -> \"https://example.com\"\n" - " ```\n" -). --spec to_string(uri()) -> binary(). -to_string(Uri) -> - Parts = case erlang:element(8, Uri) of - {some, Fragment} -> - [<<"#"/utf8>>, Fragment]; - - none -> - [] - end, - Parts@1 = case erlang:element(7, Uri) of - {some, Query} -> - [<<"?"/utf8>>, Query | Parts]; - - none -> - Parts - end, - Parts@2 = [erlang:element(6, Uri) | Parts@1], - Parts@3 = case {erlang:element(4, Uri), - gleam_stdlib:string_starts_with(erlang:element(6, Uri), <<"/"/utf8>>)} of - {{some, Host}, false} when Host =/= <<""/utf8>> -> - [<<"/"/utf8>> | Parts@2]; - - {_, _} -> - Parts@2 - end, - Parts@4 = case {erlang:element(4, Uri), erlang:element(5, Uri)} of - {{some, _}, {some, Port}} -> - [<<":"/utf8>>, erlang:integer_to_binary(Port) | Parts@3]; - - {_, _} -> - Parts@3 - end, - Parts@5 = case {erlang:element(2, Uri), - erlang:element(3, Uri), - erlang:element(4, Uri)} of - {{some, S}, {some, U}, {some, H}} -> - [S, <<"://"/utf8>>, U, <<"@"/utf8>>, H | Parts@4]; - - {{some, S@1}, none, {some, H@1}} -> - [S@1, <<"://"/utf8>>, H@1 | Parts@4]; - - {{some, S@2}, {some, _}, none} -> - [S@2, <<":"/utf8>> | Parts@4]; - - {{some, S@2}, none, none} -> - [S@2, <<":"/utf8>> | Parts@4]; - - {none, none, {some, H@2}} -> - [<<"//"/utf8>>, H@2 | Parts@4]; - - {_, _, _} -> - Parts@4 - end, - erlang:list_to_binary(Parts@5). - --file("src/gleam/uri.gleam", 683). -?DOC( - " Fetches the origin of a URI.\n" - "\n" - " Returns the origin of a uri as defined in\n" - " [RFC 6454](https://tools.ietf.org/html/rfc6454)\n" - "\n" - " The supported URI schemes are `http` and `https`.\n" - " URLs without a scheme will return `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(uri) = parse(\"https://example.com/path?foo#bar\")\n" - " origin(uri)\n" - " // -> Ok(\"https://example.com\")\n" - " ```\n" -). --spec origin(uri()) -> {ok, binary()} | {error, nil}. -origin(Uri) -> - {uri, Scheme, _, Host, Port, _, _, _} = Uri, - case {Host, Scheme} of - {{some, H}, {some, <<"https"/utf8>>}} when Port =:= {some, 443} -> - {ok, erlang:list_to_binary([<<"https://"/utf8>>, H])}; - - {{some, H@1}, {some, <<"http"/utf8>>}} when Port =:= {some, 80} -> - {ok, erlang:list_to_binary([<<"http://"/utf8>>, H@1])}; - - {{some, H@2}, {some, S}} when (S =:= <<"http"/utf8>>) orelse (S =:= <<"https"/utf8>>) -> - case Port of - {some, P} -> - {ok, - erlang:list_to_binary( - [S, - <<"://"/utf8>>, - H@2, - <<":"/utf8>>, - erlang:integer_to_binary(P)] - )}; - - none -> - {ok, erlang:list_to_binary([S, <<"://"/utf8>>, H@2])} - end; - - {_, _} -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 764). --spec drop_last(list(DDO)) -> list(DDO). -drop_last(Elements) -> - gleam@list:take(Elements, erlang:length(Elements) - 1). - --file("src/gleam/uri.gleam", 768). --spec join_segments(list(binary())) -> binary(). -join_segments(Segments) -> - gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). - --file("src/gleam/uri.gleam", 706). -?DOC( - " Resolves a URI with respect to the given base URI.\n" - "\n" - " The base URI must be an absolute URI or this function will return an error.\n" - " The algorithm for merging uris is described in\n" - " [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2).\n" -). --spec merge(uri(), uri()) -> {ok, uri()} | {error, nil}. -merge(Base, Relative) -> - case Base of - {uri, {some, _}, _, {some, _}, _, _, _, _} -> - case Relative of - {uri, _, _, {some, _}, _, _, _, _} -> - Path = begin - _pipe = erlang:element(6, Relative), - _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), - _pipe@2 = remove_dot_segments(_pipe@1), - join_segments(_pipe@2) - end, - Resolved = {uri, - gleam@option:'or'( - erlang:element(2, Relative), - erlang:element(2, Base) - ), - none, - erlang:element(4, Relative), - gleam@option:'or'( - erlang:element(5, Relative), - erlang:element(5, Base) - ), - Path, - erlang:element(7, Relative), - erlang:element(8, Relative)}, - {ok, Resolved}; - - _ -> - {New_path, New_query} = case erlang:element(6, Relative) of - <<""/utf8>> -> - {erlang:element(6, Base), - gleam@option:'or'( - erlang:element(7, Relative), - erlang:element(7, Base) - )}; - - _ -> - Path_segments = case gleam_stdlib:string_starts_with( - erlang:element(6, Relative), - <<"/"/utf8>> - ) of - true -> - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ); - - false -> - _pipe@3 = erlang:element(6, Base), - _pipe@4 = gleam@string:split( - _pipe@3, - <<"/"/utf8>> - ), - _pipe@5 = drop_last(_pipe@4), - lists:append( - _pipe@5, - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ) - ) - end, - Path@1 = begin - _pipe@6 = Path_segments, - _pipe@7 = remove_dot_segments(_pipe@6), - join_segments(_pipe@7) - end, - {Path@1, erlang:element(7, Relative)} - end, - Resolved@1 = {uri, - erlang:element(2, Base), - none, - erlang:element(4, Base), - erlang:element(5, Base), - New_path, - New_query, - erlang:element(8, Relative)}, - {ok, Resolved@1} - end; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 81). -?DOC( - " Parses a compliant URI string into the `Uri` Type.\n" - " If the string is not a valid URI string then an error is returned.\n" - "\n" - " The opposite operation is `uri.to_string`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse(\"https://example.com:1234/a/b?query=true#fragment\")\n" - " // -> Ok(\n" - " // Uri(\n" - " // scheme: Some(\"https\"),\n" - " // userinfo: None,\n" - " // host: Some(\"example.com\"),\n" - " // port: Some(1234),\n" - " // path: \"/a/b\",\n" - " // query: Some(\"query=true\"),\n" - " // fragment: Some(\"fragment\")\n" - " // )\n" - " // )\n" - " ```\n" -). --spec parse(binary()) -> {ok, uri()} | {error, nil}. -parse(Uri_string) -> - gleam_stdlib:uri_parse(Uri_string). diff --git a/build/dev/javascript/gleam_stdlib/gleam_stdlib.erl b/build/dev/javascript/gleam_stdlib/gleam_stdlib.erl deleted file mode 100644 index 2c416f4..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam_stdlib.erl +++ /dev/null @@ -1,534 +0,0 @@ --module(gleam_stdlib). - --export([ - map_get/2, iodata_append/2, identity/1, parse_int/1, parse_float/1, - less_than/2, string_pop_grapheme/1, string_pop_codeunit/1, - string_starts_with/2, wrap_list/1, string_ends_with/2, string_pad/4, - uri_parse/1, bit_array_slice/3, percent_encode/1, percent_decode/1, - base64_decode/1, parse_query/1, bit_array_concat/1, - base64_encode/2, tuple_get/2, classify_dynamic/1, print/1, - println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, - int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, - crop_string/2, base16_encode/1, base16_decode/1, string_replace/3, slice/3, - bit_array_to_int_and_size/1, bit_array_pad_to_bytes/1, index/2, list/5, - dict/1, int/1, float/1, bit_array/1, is_null/1 -]). - -%% Taken from OTP's uri_string module --define(DEC2HEX(X), - if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; - ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 - end). - -%% Taken from OTP's uri_string module --define(HEX2DEC(X), - if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; - ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; - ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 - end). - --define(is_lowercase_char(X), - (X > 96 andalso X < 123)). --define(is_underscore_char(X), - (X == 95)). --define(is_digit_char(X), - (X > 47 andalso X < 58)). --define(is_ascii_character(X), - (erlang:is_integer(X) andalso X >= 32 andalso X =< 126)). - -uppercase(X) -> X - 32. - -map_get(Map, Key) -> - case maps:find(Key, Map) of - error -> {error, nil}; - OkFound -> OkFound - end. - -iodata_append(Iodata, String) -> [Iodata, String]. - -identity(X) -> X. - -classify_dynamic(nil) -> <<"Nil">>; -classify_dynamic(null) -> <<"Nil">>; -classify_dynamic(undefined) -> <<"Nil">>; -classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; -classify_dynamic(X) when is_atom(X) -> <<"Atom">>; -classify_dynamic(X) when is_binary(X) -> <<"String">>; -classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>; -classify_dynamic(X) when is_integer(X) -> <<"Int">>; -classify_dynamic(X) when is_float(X) -> <<"Float">>; -classify_dynamic(X) when is_list(X) -> <<"List">>; -classify_dynamic(X) when is_map(X) -> <<"Dict">>; -classify_dynamic(X) when is_tuple(X) -> <<"Array">>; -classify_dynamic(X) when is_reference(X) -> <<"Reference">>; -classify_dynamic(X) when is_pid(X) -> <<"Pid">>; -classify_dynamic(X) when is_port(X) -> <<"Port">>; -classify_dynamic(X) when - is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse - is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse - is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse - is_function(X, 9) orelse is_function(X, 10) orelse is_function(X, 11) orelse - is_function(X, 12) -> <<"Function">>; -classify_dynamic(_) -> <<"Unknown">>. - -tuple_get(_tup, Index) when Index < 0 -> {error, nil}; -tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil}; -tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}. - -int_from_base_string(String, Base) -> - case catch binary_to_integer(String, Base) of - Int when is_integer(Int) -> {ok, Int}; - _ -> {error, nil} - end. - -parse_int(String) -> - case catch binary_to_integer(String) of - Int when is_integer(Int) -> {ok, Int}; - _ -> {error, nil} - end. - -parse_float(String) -> - case catch binary_to_float(String) of - Float when is_float(Float) -> {ok, Float}; - _ -> {error, nil} - end. - -less_than(Lhs, Rhs) -> - Lhs < Rhs. - -string_starts_with(_, <<>>) -> true; -string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false; -string_starts_with(String, Prefix) -> - PrefixSize = byte_size(Prefix), - Prefix == binary_part(String, 0, PrefixSize). - -string_ends_with(_, <<>>) -> true; -string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false; -string_ends_with(String, Suffix) -> - SuffixSize = byte_size(Suffix), - Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize). - -string_pad(String, Length, Dir, PadString) -> - Chars = string:pad(String, Length, Dir, binary_to_list(PadString)), - case unicode:characters_to_binary(Chars) of - Bin when is_binary(Bin) -> Bin; - Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}}) - end. - -string_pop_grapheme(String) -> - case string:next_grapheme(String) of - [ Next | Rest ] when is_binary(Rest) -> - {ok, {unicode:characters_to_binary([Next]), Rest}}; - - [ Next | Rest ] -> - {ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}}; - - _ -> {error, nil} - end. - -string_pop_codeunit(<>) -> {Cp, Rest}; -string_pop_codeunit(Binary) -> {0, Binary}. - -bit_array_pad_to_bytes(Bin) -> - case erlang:bit_size(Bin) rem 8 of - 0 -> Bin; - TrailingBits -> - PaddingBits = 8 - TrailingBits, - <> - end. - -bit_array_concat(BitArrays) -> - list_to_bitstring(BitArrays). - --if(?OTP_RELEASE >= 26). -base64_encode(Bin, Padding) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - base64:encode(PaddedBin, #{padding => Padding}). --else. -base64_encode(_Bin, _Padding) -> - erlang:error(<<"Erlang OTP/26 or higher is required to use base64:encode">>). --endif. - -bit_array_slice(Bin, Pos, Len) -> - try {ok, binary:part(Bin, Pos, Len)} - catch error:badarg -> {error, nil} - end. - -base64_decode(S) -> - try {ok, base64:decode(S)} - catch error:_ -> {error, nil} - end. - -wrap_list(X) when is_list(X) -> X; -wrap_list(X) -> [X]. - -parse_query(Query) -> - case uri_string:dissect_query(Query) of - {error, _, _} -> {error, nil}; - Pairs -> - Pairs1 = lists:map(fun - ({K, true}) -> {K, <<"">>}; - (Pair) -> Pair - end, Pairs), - {ok, Pairs1} - end. - -percent_encode(B) -> percent_encode(B, <<>>). -percent_encode(<<>>, Acc) -> - Acc; -percent_encode(<>, Acc) -> - case percent_ok(H) of - true -> - percent_encode(T, <>); - false -> - <> = <>, - percent_encode(T, <>) - end. - -percent_decode(Cs) -> percent_decode(Cs, <<>>). -percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> - case is_hex_digit(C0) andalso is_hex_digit(C1) of - true -> - B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), - percent_decode(Cs, <>); - false -> - {error, nil} - end; -percent_decode(<>, Acc) -> - percent_decode(Cs, <>); -percent_decode(<<>>, Acc) -> - check_utf8(Acc). - -percent_ok($!) -> true; -percent_ok($$) -> true; -percent_ok($') -> true; -percent_ok($() -> true; -percent_ok($)) -> true; -percent_ok($*) -> true; -percent_ok($+) -> true; -percent_ok($-) -> true; -percent_ok($.) -> true; -percent_ok($_) -> true; -percent_ok($~) -> true; -percent_ok(C) when $0 =< C, C =< $9 -> true; -percent_ok(C) when $A =< C, C =< $Z -> true; -percent_ok(C) when $a =< C, C =< $z -> true; -percent_ok(_) -> false. - -is_hex_digit(C) -> - ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). - -check_utf8(Cs) -> - case unicode:characters_to_list(Cs) of - {incomplete, _, _} -> {error, nil}; - {error, _, _} -> {error, nil}; - _ -> {ok, Cs} - end. - -uri_parse(String) -> - case uri_string:parse(String) of - {error, _, _} -> {error, nil}; - Uri -> - Port = - try maps:get(port, Uri) of - undefined -> none; - Value -> {some, Value} - catch _:_ -> none - end, - {ok, {uri, - maps_get_optional(Uri, scheme), - maps_get_optional(Uri, userinfo), - maps_get_optional(Uri, host), - Port, - maps_get_or(Uri, path, <<>>), - maps_get_optional(Uri, query), - maps_get_optional(Uri, fragment) - }} - end. - -maps_get_optional(Map, Key) -> - try {some, maps:get(Key, Map)} - catch _:_ -> none - end. - -maps_get_or(Map, Key, Default) -> - try maps:get(Key, Map) - catch _:_ -> Default - end. - -print(String) -> - io:put_chars(String), - nil. - -println(String) -> - io:put_chars([String, $\n]), - nil. - -print_error(String) -> - io:put_chars(standard_error, String), - nil. - -println_error(String) -> - io:put_chars(standard_error, [String, $\n]), - nil. - -inspect(true) -> - "True"; -inspect(false) -> - "False"; -inspect(nil) -> - "Nil"; -inspect(Data) when is_map(Data) -> - Fields = [ - [<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>] - || {Key, Value} <- maps:to_list(Data) - ], - ["dict.from_list([", lists:join(", ", Fields), "])"]; -inspect(Atom) when is_atom(Atom) -> - erlang:element(2, inspect_atom(Atom)); -inspect(Any) when is_integer(Any) -> - erlang:integer_to_list(Any); -inspect(Any) when is_float(Any) -> - io_lib_format:fwrite_g(Any); -inspect(Binary) when is_binary(Binary) -> - case inspect_maybe_utf8_string(Binary, <<>>) of - {ok, InspectedUtf8String} -> InspectedUtf8String; - {error, not_a_utf8_string} -> - Segments = [erlang:integer_to_list(X) || <> <= Binary], - ["<<", lists:join(", ", Segments), ">>"] - end; -inspect(Bits) when is_bitstring(Bits) -> - inspect_bit_array(Bits); -inspect(List) when is_list(List) -> - case inspect_list(List, true) of - {charlist, _} -> ["charlist.from_string(\"", list_to_binary(List), "\")"]; - {proper, Elements} -> ["[", Elements, "]"]; - {improper, Elements} -> ["//erl([", Elements, "])"] - end; -inspect(Any) when is_tuple(Any) % Record constructors - andalso is_atom(element(1, Any)) - andalso element(1, Any) =/= false - andalso element(1, Any) =/= true - andalso element(1, Any) =/= nil --> - [Atom | ArgsList] = erlang:tuple_to_list(Any), - InspectedArgs = lists:map(fun inspect/1, ArgsList), - case inspect_atom(Atom) of - {gleam_atom, GleamAtom} -> - Args = lists:join(<<", ">>, InspectedArgs), - [GleamAtom, "(", Args, ")"]; - {erlang_atom, ErlangAtom} -> - Args = lists:join(<<", ">>, [ErlangAtom | InspectedArgs]), - ["#(", Args, ")"] - end; -inspect(Tuple) when is_tuple(Tuple) -> - Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)), - ["#(", lists:join(", ", Elements), ")"]; -inspect(Any) when is_function(Any) -> - {arity, Arity} = erlang:fun_info(Any, arity), - ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), - Args = lists:join(<<", ">>, - lists:map(fun(Arg) -> <> end, ArgsAsciiCodes) - ), - ["//fn(", Args, ") { ... }"]; -inspect(Any) -> - ["//erl(", io_lib:format("~p", [Any]), ")"]. - -inspect_atom(Atom) -> - Binary = erlang:atom_to_binary(Atom), - case inspect_maybe_gleam_atom(Binary, none, <<>>) of - {ok, Inspected} -> {gleam_atom, Inspected}; - {error, _} -> {erlang_atom, ["atom.create(\"", Binary, "\")"]} - end. - -inspect_maybe_gleam_atom(<<>>, none, _) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, none, _) when ?is_digit_char(First) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, _PrevChar, _Acc) - when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, none, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) -> - inspect_maybe_gleam_atom(Rest, $_, Acc); -inspect_maybe_gleam_atom(<>, $_, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<>, _PrevChar, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) -> - {ok, Acc}; -inspect_maybe_gleam_atom(A, B, C) -> - erlang:display({A, B, C}), - throw({gleam_error, A, B, C}). - -inspect_list([], _) -> - {proper, []}; -inspect_list([First], true) when ?is_ascii_character(First) -> - {charlist, nil}; -inspect_list([First], _) -> - {proper, [inspect(First)]}; -inspect_list([First | Rest], ValidCharlist) when is_list(Rest) -> - StillValidCharlist = ValidCharlist andalso ?is_ascii_character(First), - {Kind, Inspected} = inspect_list(Rest, StillValidCharlist), - {Kind, [inspect(First), <<", ">> | Inspected]}; -inspect_list([First | ImproperTail], _) -> - {improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}. - -inspect_bit_array(Bits) -> - Text = inspect_bit_array(Bits, <<"<<">>), - <>">>. - -inspect_bit_array(<<>>, Acc) -> - Acc; -inspect_bit_array(<>, Acc) -> - inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X))); -inspect_bit_array(Rest, Acc) -> - Size = bit_size(Rest), - <> = Rest, - X1 = erlang:integer_to_binary(X), - Size1 = erlang:integer_to_binary(Size), - Segment = <>, - inspect_bit_array(<<>>, append_segment(Acc, Segment)). - -bit_array_to_int_and_size(A) -> - Size = bit_size(A), - <> = A, - {A1, Size}. - -append_segment(<<"<<">>, Segment) -> - <<"<<", Segment/binary>>; -append_segment(Acc, Segment) -> - <>. - - -inspect_maybe_utf8_string(Binary, Acc) -> - case Binary of - <<>> -> {ok, <<$", Acc/binary, $">>}; - <> -> - Escaped = case First of - $" -> <<$\\, $">>; - $\\ -> <<$\\, $\\>>; - $\r -> <<$\\, $r>>; - $\n -> <<$\\, $n>>; - $\t -> <<$\\, $t>>; - $\f -> <<$\\, $f>>; - X when X > 126, X < 160 -> convert_to_u(X); - X when X < 32 -> convert_to_u(X); - Other -> <> - end, - inspect_maybe_utf8_string(Rest, <>); - _ -> {error, not_a_utf8_string} - end. - -convert_to_u(Code) -> - list_to_binary(io_lib:format("\\u{~4.16.0B}", [Code])). - -float_to_string(Float) when is_float(Float) -> - erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)). - -utf_codepoint_list_to_string(List) -> - case unicode:characters_to_binary(List) of - {error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}}); - Binary -> Binary - end. - -crop_string(String, Prefix) -> - case string:find(String, Prefix) of - nomatch -> String; - New -> New - end. - -contains_string(String, Substring) -> - is_bitstring(string:find(String, Substring)). - -base16_encode(Bin) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - binary:encode_hex(PaddedBin). - -base16_decode(String) -> - try - {ok, binary:decode_hex(String)} - catch - _:_ -> {error, nil} - end. - -string_replace(String, Pattern, Replacement) -> - string:replace(String, Pattern, Replacement, all). - -slice(String, Index, Length) -> - case string:slice(String, Index, Length) of - X when is_binary(X) -> X; - X when is_list(X) -> unicode:characters_to_binary(X) - end. - -index([X | _], 0) -> - {ok, {some, X}}; -index([_, X | _], 1) -> - {ok, {some, X}}; -index([_, _, X | _], 2) -> - {ok, {some, X}}; -index([_, _, _, X | _], 3) -> - {ok, {some, X}}; -index([_, _, _, _, X | _], 4) -> - {ok, {some, X}}; -index([_, _, _, _, _, X | _], 5) -> - {ok, {some, X}}; -index([_, _, _, _, _, _, X | _], 6) -> - {ok, {some, X}}; -index([_, _, _, _, _, _, _, X | _], 7) -> - {ok, {some, X}}; -index(Tuple, Index) when is_tuple(Tuple) andalso is_integer(Index) -> - {ok, try - {some, element(Index + 1, Tuple)} - catch _:_ -> - none - end}; -index(Map, Key) when is_map(Map) -> - {ok, try - {some, maps:get(Key, Map)} - catch _:_ -> - none - end}; -index(_, Index) when is_integer(Index) -> - {error, <<"Indexable">>}; -index(_, _) -> - {error, <<"Dict">>}. - -list(T, A, B, C, D) when is_tuple(T) -> - list(tuple_to_list(T), A, B, C, D); -list([], _, _, _, Acc) -> - {lists:reverse(Acc), []}; -list([X | Xs], Decode, PushPath, Index, Acc) -> - {Out, Errors} = Decode(X), - case Errors of - [] -> list(Xs, Decode, PushPath, Index + 1, [Out | Acc]); - _ -> PushPath({[], Errors}, integer_to_binary(Index)) - end; -list(Unexpected, _, _, _, []) -> - Found = gleam@dynamic:classify(Unexpected), - Error = {decode_error, <<"List"/utf8>>, Found, []}, - {[], [Error]}; -list(_, _, _, _, Acc) -> - {lists:reverse(Acc), []}. - -dict(#{} = Data) -> {ok, Data}; -dict(_) -> {error, nil}. - -int(I) when is_integer(I) -> {ok, I}; -int(_) -> {error, 0}. - -float(F) when is_float(F) -> {ok, F}; -float(_) -> {error, 0.0}. - -bit_array(B) when is_bitstring(B) -> {ok, B}; -bit_array(_) -> {error, <<>>}. - -is_null(X) -> - X =:= undefined orelse X =:= null orelse X =:= nil. diff --git a/build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs b/build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs deleted file mode 100644 index ebac45f..0000000 --- a/build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs +++ /dev/null @@ -1,1048 +0,0 @@ -import { - BitArray, - Error, - List, - Ok, - Result, - UtfCodepoint, - stringBits, - toBitArray, - bitArraySlice, - NonEmpty, - Empty, - CustomType, -} from "./gleam.mjs"; -import { Some, None } from "./gleam/option.mjs"; -import Dict from "./dict.mjs"; -import { classify } from "./gleam/dynamic.mjs"; -import { DecodeError } from "./gleam/dynamic/decode.mjs"; - -const Nil = undefined; -const NOT_FOUND = {}; - -export function identity(x) { - return x; -} - -export function parse_int(value) { - if (/^[-+]?(\d+)$/.test(value)) { - return new Ok(parseInt(value)); - } else { - return new Error(Nil); - } -} - -export function parse_float(value) { - if (/^[-+]?(\d+)\.(\d+)([eE][-+]?\d+)?$/.test(value)) { - return new Ok(parseFloat(value)); - } else { - return new Error(Nil); - } -} - -export function to_string(term) { - return term.toString(); -} - -export function int_to_base_string(int, base) { - return int.toString(base).toUpperCase(); -} - -const int_base_patterns = { - 2: /[^0-1]/, - 3: /[^0-2]/, - 4: /[^0-3]/, - 5: /[^0-4]/, - 6: /[^0-5]/, - 7: /[^0-6]/, - 8: /[^0-7]/, - 9: /[^0-8]/, - 10: /[^0-9]/, - 11: /[^0-9a]/, - 12: /[^0-9a-b]/, - 13: /[^0-9a-c]/, - 14: /[^0-9a-d]/, - 15: /[^0-9a-e]/, - 16: /[^0-9a-f]/, - 17: /[^0-9a-g]/, - 18: /[^0-9a-h]/, - 19: /[^0-9a-i]/, - 20: /[^0-9a-j]/, - 21: /[^0-9a-k]/, - 22: /[^0-9a-l]/, - 23: /[^0-9a-m]/, - 24: /[^0-9a-n]/, - 25: /[^0-9a-o]/, - 26: /[^0-9a-p]/, - 27: /[^0-9a-q]/, - 28: /[^0-9a-r]/, - 29: /[^0-9a-s]/, - 30: /[^0-9a-t]/, - 31: /[^0-9a-u]/, - 32: /[^0-9a-v]/, - 33: /[^0-9a-w]/, - 34: /[^0-9a-x]/, - 35: /[^0-9a-y]/, - 36: /[^0-9a-z]/, -}; - -export function int_from_base_string(string, base) { - if (int_base_patterns[base].test(string.replace(/^-/, "").toLowerCase())) { - return new Error(Nil); - } - - const result = parseInt(string, base); - - if (isNaN(result)) { - return new Error(Nil); - } - - return new Ok(result); -} - -export function string_replace(string, target, substitute) { - return string.replaceAll(target, substitute); -} - -export function string_reverse(string) { - return [...string].reverse().join(""); -} - -export function string_length(string) { - if (string === "") { - return 0; - } - const iterator = graphemes_iterator(string); - if (iterator) { - let i = 0; - for (const _ of iterator) { - i++; - } - return i; - } else { - return string.match(/./gsu).length; - } -} - -export function graphemes(string) { - const iterator = graphemes_iterator(string); - if (iterator) { - return List.fromArray(Array.from(iterator).map((item) => item.segment)); - } else { - return List.fromArray(string.match(/./gsu)); - } -} - -let segmenter = undefined; - -function graphemes_iterator(string) { - if (globalThis.Intl && Intl.Segmenter) { - segmenter ||= new Intl.Segmenter(); - return segmenter.segment(string)[Symbol.iterator](); - } -} - -export function pop_grapheme(string) { - let first; - const iterator = graphemes_iterator(string); - if (iterator) { - first = iterator.next().value?.segment; - } else { - first = string.match(/./su)?.[0]; - } - if (first) { - return new Ok([first, string.slice(first.length)]); - } else { - return new Error(Nil); - } -} - -export function pop_codeunit(str) { - return [str.charCodeAt(0) | 0, str.slice(1)]; -} - -export function lowercase(string) { - return string.toLowerCase(); -} - -export function uppercase(string) { - return string.toUpperCase(); -} - -export function less_than(a, b) { - return a < b; -} - -export function add(a, b) { - return a + b; -} - -export function split(xs, pattern) { - return List.fromArray(xs.split(pattern)); -} - -export function concat(xs) { - let result = ""; - for (const x of xs) { - result = result + x; - } - return result; -} - -export function length(data) { - return data.length; -} - -export function string_byte_slice(string, index, length) { - return string.slice(index, index + length); -} - -export function string_grapheme_slice(string, idx, len) { - if (len <= 0 || idx >= string.length) { - return ""; - } - - const iterator = graphemes_iterator(string); - if (iterator) { - while (idx-- > 0) { - iterator.next(); - } - - let result = ""; - - while (len-- > 0) { - const v = iterator.next().value; - if (v === undefined) { - break; - } - - result += v.segment; - } - - return result; - } else { - return string - .match(/./gsu) - .slice(idx, idx + len) - .join(""); - } -} - -export function string_codeunit_slice(str, from, length) { - return str.slice(from, from + length); -} -export function crop_string(string, substring) { - return string.substring(string.indexOf(substring)); -} - -export function contains_string(haystack, needle) { - return haystack.indexOf(needle) >= 0; -} - -export function starts_with(haystack, needle) { - return haystack.startsWith(needle); -} - -export function ends_with(haystack, needle) { - return haystack.endsWith(needle); -} - -export function split_once(haystack, needle) { - const index = haystack.indexOf(needle); - if (index >= 0) { - const before = haystack.slice(0, index); - const after = haystack.slice(index + needle.length); - return new Ok([before, after]); - } else { - return new Error(Nil); - } -} - -const unicode_whitespaces = [ - "\u0020", // Space - "\u0009", // Horizontal tab - "\u000A", // Line feed - "\u000B", // Vertical tab - "\u000C", // Form feed - "\u000D", // Carriage return - "\u0085", // Next line - "\u2028", // Line separator - "\u2029", // Paragraph separator -].join(""); - -const trim_start_regex = /* @__PURE__ */ new RegExp( - `^[${unicode_whitespaces}]*`, -); -const trim_end_regex = /* @__PURE__ */ new RegExp(`[${unicode_whitespaces}]*$`); - -export function trim_start(string) { - return string.replace(trim_start_regex, ""); -} - -export function trim_end(string) { - return string.replace(trim_end_regex, ""); -} - -export function bit_array_from_string(string) { - return toBitArray([stringBits(string)]); -} - -export function bit_array_bit_size(bit_array) { - return bit_array.bitSize; -} - -export function bit_array_byte_size(bit_array) { - return bit_array.byteSize; -} - -export function bit_array_pad_to_bytes(bit_array) { - const trailingBitsCount = bit_array.bitSize % 8; - - // If the bit array is a whole number of bytes it can be returned unchanged - if (trailingBitsCount === 0) { - return bit_array; - } - - const finalByte = bit_array.byteAt(bit_array.byteSize - 1); - - // The required final byte has its unused trailing bits set to zero - const unusedBitsCount = 8 - trailingBitsCount; - const correctFinalByte = (finalByte >> unusedBitsCount) << unusedBitsCount; - - // If the unused bits in the final byte are already set to zero then the - // existing buffer can be re-used, avoiding a copy - if (finalByte === correctFinalByte) { - return new BitArray( - bit_array.rawBuffer, - bit_array.byteSize * 8, - bit_array.bitOffset, - ); - } - - // Copy the bit array into a new aligned buffer and set the correct final byte - const buffer = new Uint8Array(bit_array.byteSize); - for (let i = 0; i < buffer.length - 1; i++) { - buffer[i] = bit_array.byteAt(i); - } - buffer[buffer.length - 1] = correctFinalByte; - - return new BitArray(buffer); -} - -export function bit_array_concat(bit_arrays) { - return toBitArray(bit_arrays.toArray()); -} - -export function console_log(term) { - console.log(term); -} - -export function console_error(term) { - console.error(term); -} - -export function crash(message) { - throw new globalThis.Error(message); -} - -export function bit_array_to_string(bit_array) { - // If the bit array isn't a whole number of bytes then return an error - if (bit_array.bitSize % 8 !== 0) { - return new Error(Nil); - } - - try { - const decoder = new TextDecoder("utf-8", { fatal: true }); - - if (bit_array.bitOffset === 0) { - return new Ok(decoder.decode(bit_array.rawBuffer)); - } else { - // The input data isn't aligned, so copy it into a new aligned buffer so - // that TextDecoder can be used - const buffer = new Uint8Array(bit_array.byteSize); - for (let i = 0; i < buffer.length; i++) { - buffer[i] = bit_array.byteAt(i); - } - return new Ok(decoder.decode(buffer)); - } - } catch { - return new Error(Nil); - } -} - -export function print(string) { - if (typeof process === "object" && process.stdout?.write) { - process.stdout.write(string); // We can write without a trailing newline - } else if (typeof Deno === "object") { - Deno.stdout.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline - } else { - console.log(string); // We're in a browser. Newlines are mandated - } -} - -export function print_error(string) { - if (typeof process === "object" && process.stderr?.write) { - process.stderr.write(string); // We can write without a trailing newline - } else if (typeof Deno === "object") { - Deno.stderr.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline - } else { - console.error(string); // We're in a browser. Newlines are mandated - } -} - -export function print_debug(string) { - if (typeof process === "object" && process.stderr?.write) { - process.stderr.write(string + "\n"); // If we're in Node.js, use `stderr` - } else if (typeof Deno === "object") { - Deno.stderr.writeSync(new TextEncoder().encode(string + "\n")); // If we're in Deno, use `stderr` - } else { - console.log(string); // Otherwise, use `console.log` (so that it doesn't look like an error) - } -} - -export function ceiling(float) { - return Math.ceil(float); -} - -export function floor(float) { - return Math.floor(float); -} - -export function round(float) { - return Math.round(float); -} - -export function truncate(float) { - return Math.trunc(float); -} - -export function power(base, exponent) { - // It is checked in Gleam that: - // - The base is non-negative and that the exponent is not fractional. - // - The base is non-zero and the exponent is non-negative (otherwise - // the result will essentially be division by zero). - // It can thus be assumed that valid input is passed to the Math.pow - // function and a NaN or Infinity value will not be produced. - return Math.pow(base, exponent); -} - -export function random_uniform() { - const random_uniform_result = Math.random(); - // With round-to-nearest-even behavior, the ranges claimed for the functions below - // (excluding the one for Math.random() itself) aren't exact. - // If extremely large bounds are chosen (2^53 or higher), - // it's possible in extremely rare cases to calculate the usually-excluded upper bound. - // Note that as numbers in JavaScript are IEEE 754 floating point numbers - // See: - // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: - if (random_uniform_result === 1.0) { - return random_uniform(); - } - return random_uniform_result; -} - -export function bit_array_slice(bits, position, length) { - const start = Math.min(position, position + length); - const end = Math.max(position, position + length); - - if (start < 0 || end * 8 > bits.bitSize) { - return new Error(Nil); - } - - return new Ok(bitArraySlice(bits, start * 8, end * 8)); -} - -export function codepoint(int) { - return new UtfCodepoint(int); -} - -export function string_to_codepoint_integer_list(string) { - return List.fromArray(Array.from(string).map((item) => item.codePointAt(0))); -} - -export function utf_codepoint_list_to_string(utf_codepoint_integer_list) { - return utf_codepoint_integer_list - .toArray() - .map((x) => String.fromCodePoint(x.value)) - .join(""); -} - -export function utf_codepoint_to_int(utf_codepoint) { - return utf_codepoint.value; -} - -export function new_map() { - return Dict.new(); -} - -export function map_size(map) { - return map.size; -} - -export function map_to_list(map) { - return List.fromArray(map.entries()); -} - -export function map_remove(key, map) { - return map.delete(key); -} - -export function map_get(map, key) { - const value = map.get(key, NOT_FOUND); - if (value === NOT_FOUND) { - return new Error(Nil); - } - return new Ok(value); -} - -export function map_insert(key, value, map) { - return map.set(key, value); -} - -function unsafe_percent_decode(string) { - return decodeURIComponent(string || ""); -} - -function unsafe_percent_decode_query(string) { - return decodeURIComponent((string || "").replace("+", " ")); -} - -export function percent_decode(string) { - try { - return new Ok(unsafe_percent_decode(string)); - } catch { - return new Error(Nil); - } -} - -export function percent_encode(string) { - return encodeURIComponent(string).replace("%2B", "+"); -} - -export function parse_query(query) { - try { - const pairs = []; - for (const section of query.split("&")) { - const [key, value] = section.split("="); - if (!key) continue; - - const decodedKey = unsafe_percent_decode_query(key); - const decodedValue = unsafe_percent_decode_query(value); - pairs.push([decodedKey, decodedValue]); - } - return new Ok(List.fromArray(pairs)); - } catch { - return new Error(Nil); - } -} - -const b64EncodeLookup = [ - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, -]; - -let b64TextDecoder; - -// Implementation based on https://github.com/mitschabaude/fast-base64/blob/main/js.js -export function base64_encode(bit_array, padding) { - b64TextDecoder ??= new TextDecoder(); - - bit_array = bit_array_pad_to_bytes(bit_array); - - const m = bit_array.byteSize; - const k = m % 3; - const n = Math.floor(m / 3) * 4 + (k && k + 1); - const N = Math.ceil(m / 3) * 4; - const encoded = new Uint8Array(N); - - for (let i = 0, j = 0; j < m; i += 4, j += 3) { - const y = - (bit_array.byteAt(j) << 16) + - (bit_array.byteAt(j + 1) << 8) + - (bit_array.byteAt(j + 2) | 0); - - encoded[i] = b64EncodeLookup[y >> 18]; - encoded[i + 1] = b64EncodeLookup[(y >> 12) & 0x3f]; - encoded[i + 2] = b64EncodeLookup[(y >> 6) & 0x3f]; - encoded[i + 3] = b64EncodeLookup[y & 0x3f]; - } - - let base64 = b64TextDecoder.decode(new Uint8Array(encoded.buffer, 0, n)); - - if (padding) { - if (k === 1) { - base64 += "=="; - } else if (k === 2) { - base64 += "="; - } - } - - return base64; -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64 -export function base64_decode(sBase64) { - try { - const binString = atob(sBase64); - const length = binString.length; - const array = new Uint8Array(length); - for (let i = 0; i < length; i++) { - array[i] = binString.charCodeAt(i); - } - return new Ok(new BitArray(array)); - } catch { - return new Error(Nil); - } -} - -export function classify_dynamic(data) { - if (typeof data === "string") { - return "String"; - } else if (typeof data === "boolean") { - return "Bool"; - } else if (data instanceof Result) { - return "Result"; - } else if (data instanceof List) { - return "List"; - } else if (data instanceof BitArray) { - return "BitArray"; - } else if (data instanceof Dict) { - return "Dict"; - } else if (Number.isInteger(data)) { - return "Int"; - } else if (Array.isArray(data)) { - return `Array`; - } else if (typeof data === "number") { - return "Float"; - } else if (data === null) { - return "Nil"; - } else if (data === undefined) { - return "Nil"; - } else { - const type = typeof data; - return type.charAt(0).toUpperCase() + type.slice(1); - } -} - -export function byte_size(string) { - return new TextEncoder().encode(string).length; -} - -// In JavaScript bitwise operations convert numbers to a sequence of 32 bits -// while Erlang uses arbitrary precision. -// To get around this problem and get consistent results use BigInt and then -// downcast the value back to a Number value. - -export function bitwise_and(x, y) { - return Number(BigInt(x) & BigInt(y)); -} - -export function bitwise_not(x) { - return Number(~BigInt(x)); -} - -export function bitwise_or(x, y) { - return Number(BigInt(x) | BigInt(y)); -} - -export function bitwise_exclusive_or(x, y) { - return Number(BigInt(x) ^ BigInt(y)); -} - -export function bitwise_shift_left(x, y) { - return Number(BigInt(x) << BigInt(y)); -} - -export function bitwise_shift_right(x, y) { - return Number(BigInt(x) >> BigInt(y)); -} - -export function inspect(v) { - return new Inspector().inspect(v); -} - -export function float_to_string(float) { - const string = float.toString().replace("+", ""); - if (string.indexOf(".") >= 0) { - return string; - } else { - const index = string.indexOf("e"); - if (index >= 0) { - return string.slice(0, index) + ".0" + string.slice(index); - } else { - return string + ".0"; - } - } -} - -class Inspector { - #references = new Set(); - - inspect(v) { - const t = typeof v; - if (v === true) return "True"; - if (v === false) return "False"; - if (v === null) return "//js(null)"; - if (v === undefined) return "Nil"; - if (t === "string") return this.#string(v); - if (t === "bigint" || Number.isInteger(v)) return v.toString(); - if (t === "number") return float_to_string(v); - if (v instanceof UtfCodepoint) return this.#utfCodepoint(v); - if (v instanceof BitArray) return this.#bit_array(v); - if (v instanceof RegExp) return `//js(${v})`; - if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; - if (v instanceof globalThis.Error) return `//js(${v.toString()})`; - if (v instanceof Function) { - const args = []; - for (const i of Array(v.length).keys()) - args.push(String.fromCharCode(i + 97)); - return `//fn(${args.join(", ")}) { ... }`; - } - - if (this.#references.size === this.#references.add(v).size) { - return "//js(circular reference)"; - } - - let printed; - if (Array.isArray(v)) { - printed = `#(${v.map((v) => this.inspect(v)).join(", ")})`; - } else if (v instanceof List) { - printed = this.#list(v); - } else if (v instanceof CustomType) { - printed = this.#customType(v); - } else if (v instanceof Dict) { - printed = this.#dict(v); - } else if (v instanceof Set) { - return `//js(Set(${[...v].map((v) => this.inspect(v)).join(", ")}))`; - } else { - printed = this.#object(v); - } - this.#references.delete(v); - return printed; - } - - #object(v) { - const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; - const props = []; - for (const k of Object.keys(v)) { - props.push(`${this.inspect(k)}: ${this.inspect(v[k])}`); - } - const body = props.length ? " " + props.join(", ") + " " : ""; - const head = name === "Object" ? "" : name + " "; - return `//js(${head}{${body}})`; - } - - #dict(map) { - let body = "dict.from_list(["; - let first = true; - map.forEach((value, key) => { - if (!first) body = body + ", "; - body = body + "#(" + this.inspect(key) + ", " + this.inspect(value) + ")"; - first = false; - }); - return body + "])"; - } - - #customType(record) { - const props = Object.keys(record) - .map((label) => { - const value = this.inspect(record[label]); - return isNaN(parseInt(label)) ? `${label}: ${value}` : value; - }) - .join(", "); - return props - ? `${record.constructor.name}(${props})` - : record.constructor.name; - } - - #list(list) { - if (list instanceof Empty) { - return "[]"; - } - - let char_out = 'charlist.from_string("'; - let list_out = "["; - - let current = list; - while (current instanceof NonEmpty) { - let element = current.head; - current = current.tail; - - if (list_out !== "[") { - list_out += ", "; - } - list_out += this.inspect(element); - - if (char_out) { - if (Number.isInteger(element) && element >= 32 && element <= 126) { - char_out += String.fromCharCode(element); - } else { - char_out = null; - } - } - } - - if (char_out) { - return char_out + '")'; - } else { - return list_out + "]"; - } - } - - #string(str) { - let new_str = '"'; - for (let i = 0; i < str.length; i++) { - const char = str[i]; - switch (char) { - case "\n": - new_str += "\\n"; - break; - case "\r": - new_str += "\\r"; - break; - case "\t": - new_str += "\\t"; - break; - case "\f": - new_str += "\\f"; - break; - case "\\": - new_str += "\\\\"; - break; - case '"': - new_str += '\\"'; - break; - default: - if (char < " " || (char > "~" && char < "\u{00A0}")) { - new_str += - "\\u{" + - char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + - "}"; - } else { - new_str += char; - } - } - } - new_str += '"'; - return new_str; - } - - #utfCodepoint(codepoint) { - return `//utfcodepoint(${String.fromCodePoint(codepoint.value)})`; - } - - #bit_array(bits) { - if (bits.bitSize === 0) { - return "<<>>"; - } - - let acc = "<<"; - - for (let i = 0; i < bits.byteSize - 1; i++) { - acc += bits.byteAt(i).toString(); - acc += ", "; - } - - if (bits.byteSize * 8 === bits.bitSize) { - acc += bits.byteAt(bits.byteSize - 1).toString(); - } else { - const trailingBitsCount = bits.bitSize % 8; - acc += bits.byteAt(bits.byteSize - 1) >> (8 - trailingBitsCount); - acc += `:size(${trailingBitsCount})`; - } - - acc += ">>"; - return acc; - } -} - -export function base16_encode(bit_array) { - const trailingBitsCount = bit_array.bitSize % 8; - - let result = ""; - - for (let i = 0; i < bit_array.byteSize; i++) { - let byte = bit_array.byteAt(i); - - if (i === bit_array.byteSize - 1 && trailingBitsCount !== 0) { - const unusedBitsCount = 8 - trailingBitsCount; - byte = (byte >> unusedBitsCount) << unusedBitsCount; - } - - result += byte.toString(16).padStart(2, "0").toUpperCase(); - } - - return result; -} - -export function base16_decode(string) { - const bytes = new Uint8Array(string.length / 2); - for (let i = 0; i < string.length; i += 2) { - const a = parseInt(string[i], 16); - const b = parseInt(string[i + 1], 16); - if (isNaN(a) || isNaN(b)) return new Error(Nil); - bytes[i / 2] = a * 16 + b; - } - return new Ok(new BitArray(bytes)); -} - -export function bit_array_to_int_and_size(bits) { - const trailingBitsCount = bits.bitSize % 8; - const unusedBitsCount = trailingBitsCount === 0 ? 0 : 8 - trailingBitsCount; - - return [bits.byteAt(0) >> unusedBitsCount, bits.bitSize]; -} - -export function bit_array_starts_with(bits, prefix) { - if (prefix.bitSize > bits.bitSize) { - return false; - } - - // Check any whole bytes - const byteCount = Math.trunc(prefix.bitSize / 8); - for (let i = 0; i < byteCount; i++) { - if (bits.byteAt(i) !== prefix.byteAt(i)) { - return false; - } - } - - // Check any trailing bits at the end of the prefix - if (prefix.bitSize % 8 !== 0) { - const unusedBitsCount = 8 - (prefix.bitSize % 8); - if ( - bits.byteAt(byteCount) >> unusedBitsCount !== - prefix.byteAt(byteCount) >> unusedBitsCount - ) { - return false; - } - } - - return true; -} - -export function log(x) { - // It is checked in Gleam that: - // - The input is strictly positive (x > 0) - // - This ensures that Math.log will never return NaN or -Infinity - // The function can thus safely pass the input to Math.log - // and a valid finite float will always be produced. - return Math.log(x); -} - -export function exp(x) { - return Math.exp(x); -} - -export function list_to_array(list) { - let current = list; - let array = []; - while (current instanceof NonEmpty) { - array.push(current.head); - current = current.tail; - } - return array; -} - -export function index(data, key) { - // Dictionaries and dictionary-like objects can be indexed - if (data instanceof Dict || data instanceof WeakMap || data instanceof Map) { - const token = {}; - const entry = data.get(key, token); - if (entry === token) return new Ok(new None()); - return new Ok(new Some(entry)); - } - - const key_is_int = Number.isInteger(key); - - // Only elements 0-7 of lists can be indexed, negative indices are not allowed - if (key_is_int && key >= 0 && key < 8 && data instanceof List) { - let i = 0; - for (const value of data) { - if (i === key) return new Ok(new Some(value)); - i++; - } - return new Error("Indexable"); - } - - // Arrays and objects can be indexed - if ( - (key_is_int && Array.isArray(data)) || - (data && typeof data === "object") || - (data && Object.getPrototypeOf(data) === Object.prototype) - ) { - if (key in data) return new Ok(new Some(data[key])); - return new Ok(new None()); - } - - return new Error(key_is_int ? "Indexable" : "Dict"); -} - -export function list(data, decode, pushPath, index, emptyList) { - if (!(data instanceof List || Array.isArray(data))) { - const error = new DecodeError("List", classify(data), emptyList); - return [emptyList, List.fromArray([error])]; - } - - const decoded = []; - - for (const element of data) { - const layer = decode(element); - const [out, errors] = layer; - - if (errors instanceof NonEmpty) { - const [_, errors] = pushPath(layer, index.toString()); - return [emptyList, errors]; - } - decoded.push(out); - index++; - } - - return [List.fromArray(decoded), emptyList]; -} - -export function dict(data) { - if (data instanceof Dict) { - return new Ok(data); - } - if (data instanceof Map || data instanceof WeakMap) { - return new Ok(Dict.fromMap(data)); - } - if (data == null) { - return new Error("Dict"); - } - if (typeof data !== "object") { - return new Error("Dict"); - } - const proto = Object.getPrototypeOf(data); - if (proto === Object.prototype || proto === null) { - return new Ok(Dict.fromObject(data)); - } - return new Error("Dict"); -} - -export function bit_array(data) { - if (data instanceof BitArray) return new Ok(data); - if (data instanceof Uint8Array) return new Ok(new BitArray(data)); - return new Error(new BitArray(new Uint8Array())); -} - -export function float(data) { - if (typeof data === "number") return new Ok(data); - return new Error(0.0); -} - -export function int(data) { - if (Number.isInteger(data)) return new Ok(data); - return new Error(0); -} - -export function string(data) { - if (typeof data === "string") return new Ok(data); - return new Error(""); -} - -export function is_null(data) { - return data === null || data === undefined; -} diff --git a/build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache b/build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache deleted file mode 100644 index b3da925345c563e0958a2d10015535fb17ae5816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21304 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 YqI87yK>=zdYzv}1guOvjlyIyt06O%*tN;K2 diff --git a/build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache_inline b/build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache_meta b/build/dev/javascript/gleam_time/_gleam_artefacts/gleam@time@calendar.cache_meta deleted file mode 100644 index e65ddb65f29754b87dd5eaa78b87eeded909f888..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1524 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
-//// The license of that package is produced below: -//// -//// -//// > MIT License -//// -//// > Copyright 2018 Aaron VonderHaar -//// -//// > Redistribution and use in source and binary forms, with or without modification, -//// are permitted provided that the following conditions are met: -//// -//// 1. Redistributions of source code must retain the above copyright notice, -//// this list of conditions and the following disclaimer. -//// -//// 2. Redistributions in binary form must reproduce the above copyright notice, -//// this list of conditions and the following disclaimer in the documentation -//// and/or other materials provided with the distribution. -//// -//// 3. Neither the name of the copyright holder nor the names of its contributors -//// may be used to endorse or promote products derived from this software without -//// specific prior written permission. -//// -//// > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -//// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -//// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -//// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -//// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -//// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -//// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -//// -//// > The above copyright notice and this permission notice shall be included in all -//// copies or substantial portions of the Software. -////
-//// - -// Just in case we decide in the future to no longer include the above reference -// and license, this package was initially a port of the `elm-color` module: -// -// https://github.com/avh4/elm-color/ -// - -// IMPORTS -------------------------------------------------------------------- - -import gleam/dynamic/decode -import gleam/float -import gleam/int -import gleam/json.{type Json} -import gleam/list -import gleam/result -import gleam/string - -// TYPES ---------------------------------------------------------------------- - -/// A representation of a colour that can be converted to RGBA or HSLA format. -/// -/// -///
-/// -pub opaque type Colour { - Rgba(r: Float, g: Float, b: Float, a: Float) - Hsla(h: Float, s: Float, l: Float, a: Float) -} - -/// Type alias for `Colour` -/// -/// -///
-/// -pub type Color = - Colour - -// UTILITY -------------------------------------------------------------------- - -fn valid_colour_value(c: Float) -> Result(Float, Nil) { - case c >. 1.0 || c <. 0.0 { - True -> Error(Nil) - False -> Ok(c) - } -} - -fn hue_to_rgb(hue: Float, m1: Float, m2: Float) -> Float { - let h = case hue { - _ if hue <. 0.0 -> hue +. 1.0 - _ if hue >. 1.0 -> hue -. 1.0 - _ -> hue - } - - let h_t_6 = h *. 6.0 - let h_t_2 = h *. 2.0 - let h_t_3 = h *. 3.0 - - case h { - _ if h_t_6 <. 1.0 -> m1 +. { m2 -. m1 } *. h *. 6.0 - _ if h_t_2 <. 1.0 -> m2 - _ if h_t_3 <. 2.0 -> m1 +. { m2 -. m1 } *. { 2.0 /. 3.0 -. h } *. 6.0 - _ -> m1 - } -} - -fn hex_string_to_int(hex_string: String) -> Result(Int, Nil) { - let hex = case hex_string { - "#" <> hex_number -> hex_number - "0x" <> hex_number -> hex_number - _ -> hex_string - } - - hex - |> string.lowercase() - |> string.to_graphemes() - |> list.reverse() - |> list.index_fold(Ok(0), fn(total, char, index) { - case total { - Error(Nil) -> Error(Nil) - Ok(v) -> { - use num <- result.try(case char { - "a" -> Ok(10) - "b" -> Ok(11) - "c" -> Ok(12) - "d" -> Ok(13) - "e" -> Ok(14) - "f" -> Ok(15) - _ -> int.parse(char) - }) - use base <- result.try(int.power(16, int.to_float(index))) - Ok(v + float.round(int.to_float(num) *. base)) - } - } - }) -} - -fn hsla_to_rgba( - h: Float, - s: Float, - l: Float, - a: Float, -) -> #(Float, Float, Float, Float) { - let m2 = case l <=. 0.5 { - True -> l *. { s +. 1.0 } - False -> l +. s -. l *. s - } - - let m1 = l *. 2.0 -. m2 - - let r = hue_to_rgb(h +. 1.0 /. 3.0, m1, m2) - let g = hue_to_rgb(h, m1, m2) - let b = hue_to_rgb(h -. 1.0 /. 3.0, m1, m2) - - #(r, g, b, a) -} - -fn rgba_to_hsla( - r: Float, - g: Float, - b: Float, - a: Float, -) -> #(Float, Float, Float, Float) { - let min_colour = float.min(r, float.min(g, b)) - - let max_colour = float.max(r, float.max(g, b)) - - let h1 = case True { - _ if max_colour == r -> float.divide(g -. b, max_colour -. min_colour) - _ if max_colour == g -> - float.divide(b -. r, max_colour -. min_colour) - |> result.try(fn(d) { Ok(2.0 +. d) }) - _ -> - float.divide(r -. g, max_colour -. min_colour) - |> result.try(fn(d) { Ok(4.0 +. d) }) - } - - let h2 = case h1 { - Ok(v) -> Ok(v *. { 1.0 /. 6.0 }) - _ -> h1 - } - - let h3 = case h2 { - Ok(v) if v <. 0.0 -> v +. 1.0 - Ok(v) -> v - _ -> 0.0 - } - - let l = { min_colour +. max_colour } /. 2.0 - - let s = case True { - _ if min_colour == max_colour -> 0.0 - _ if l <. 0.5 -> - { max_colour -. min_colour } /. { max_colour +. min_colour } - _ -> { max_colour -. min_colour } /. { 2.0 -. max_colour -. min_colour } - } - - #(h3, s, l, a) -} - -// CONSTRUCTORS --------------------------------------------------------------- - -/// Returns a `Result(Colour)` created from the given 8 bit RGB values. -/// -/// Returns `Error(Nil)` if the supplied RGB values are greater than 255 or less than 0. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb255(255, 0, 0) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgb255(r red: Int, g green: Int, b blue: Int) -> Result(Colour, Nil) { - use r <- result.try( - red - |> int.to_float() - |> float.divide(255.0) - |> result.try(valid_colour_value), - ) - - use g <- result.try( - green - |> int.to_float() - |> float.divide(255.0) - |> result.try(valid_colour_value), - ) - - use b <- result.try( - blue - |> int.to_float() - |> float.divide(255.0) - |> result.try(valid_colour_value), - ) - - Ok(Rgba(r: r, g: g, b: b, a: 1.0)) -} - -/// Returns `Result(Colour)` created from the given RGB values. -/// -/// If the supplied RGB values are greater than 1.0 or less than 0.0 returns `Error(Nil)` -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb(1.0, 0.0, 0.0) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgb( - r red: Float, - g green: Float, - b blue: Float, -) -> Result(Colour, Nil) { - use r <- result.try(valid_colour_value(red)) - use g <- result.try(valid_colour_value(green)) - use b <- result.try(valid_colour_value(blue)) - - Ok(Rgba(r: r, g: g, b: b, a: 1.0)) -} - -/// Returns `Result(Colour)` created from the given RGBA values. -/// -/// Returns `Error(Nil)` if the supplied RGBA values are greater than 1.0 or less than 0.0. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red_half_opacity) = from_rbga(1.0, 0.0, 0.0, 0.5) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgba( - r red: Float, - g green: Float, - b blue: Float, - a alpha: Float, -) -> Result(Colour, Nil) { - use r <- result.try(valid_colour_value(red)) - use g <- result.try(valid_colour_value(green)) - use b <- result.try(valid_colour_value(blue)) - use a <- result.try(valid_colour_value(alpha)) - - Ok(Rgba(r: r, g: g, b: b, a: a)) -} - -/// Returns `Result(Colour)` created from the given HSLA values. -/// -/// Returns `Error(Nil)`f the supplied HSLA values are greater than 1.0 or less than 0.0. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red_half_opacity) = from_hsla(0.0, 1.0, 0.5, 0.5) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_hsla( - h hue: Float, - s saturation: Float, - l lightness: Float, - a alpha: Float, -) -> Result(Colour, Nil) { - use h <- result.try(valid_colour_value(hue)) - use s <- result.try(valid_colour_value(saturation)) - use l <- result.try(valid_colour_value(lightness)) - use a <- result.try(valid_colour_value(alpha)) - - Ok(Hsla(h: h, s: s, l: l, a: a)) -} - -/// Returns `Result(Colour)` created from the given HSL values. -/// -/// Returns `Error(Nil)` if the supplied HSL values are greater than 1.0 or less than 0.0. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_hsla(0.0, 1.0, 0.5) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_hsl( - h hue: Float, - s saturation: Float, - l lightness: Float, -) -> Result(Colour, Nil) { - from_hsla(hue, saturation, lightness, 1.0) -} - -/// Returns a `Result(Colour)` created from the given hex `Int`. -/// -/// Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffff or less than 0x0. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb_hex(0xff0000) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgb_hex(hex: Int) -> Result(Colour, Nil) { - case hex > 0xffffff || hex < 0 { - True -> Error(Nil) - False -> { - let r = - int.bitwise_shift_right(hex, 16) - |> int.bitwise_and(0xff) - let g = - int.bitwise_shift_right(hex, 8) - |> int.bitwise_and(0xff) - let b = int.bitwise_and(hex, 0xff) - from_rgb255(r, g, b) - } - } -} - -/// Returns a `Result(Colour)` created from the given RGB hex `String`. -/// -/// Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `"#ffffff" or less than `"#0"` -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb_hex_string("#ff0000") -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgb_hex_string(hex_string: String) -> Result(Colour, Nil) { - use hex_int <- result.try(hex_string_to_int(hex_string)) - - from_rgb_hex(hex_int) -} - -/// Returns a `Result(Colour)` created from the given RGBA hex `String`. -/// -/// Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `"#ffffffff" or less than `"#0"` -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red_half_opacity) = from_rgba_hex_string("#ff00007f") -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgba_hex_string(hex_string: String) -> Result(Colour, Nil) { - use hex_int <- result.try(hex_string_to_int(hex_string)) - - from_rgba_hex(hex_int) -} - -/// Returns a `Result(Colour)` created from the given hex `Int`. -/// -/// Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffffff or less than 0x0. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red_half_opacity) = from_rgba_hex(0xff00007f) -/// } -/// ``` -///
-/// -/// -/// -pub fn from_rgba_hex(hex: Int) -> Result(Colour, Nil) { - case hex > 0xffffffff || hex < 0 { - True -> Error(Nil) - False -> { - // This won't fail because we are always dividing by 255.0 - let assert Ok(r) = - int.bitwise_shift_right(hex, 24) - |> int.bitwise_and(0xff) - |> int.to_float() - |> float.divide(255.0) - // This won't fail because we are always dividing by 255.0 - let assert Ok(g) = - int.bitwise_shift_right(hex, 16) - |> int.bitwise_and(0xff) - |> int.to_float() - |> float.divide(255.0) - // This won't fail because we are always dividing by 255.0 - let assert Ok(b) = - int.bitwise_shift_right(hex, 8) - |> int.bitwise_and(0xff) - |> int.to_float() - |> float.divide(255.0) - // This won't fail because we are always dividing by 255.0 - let assert Ok(a) = - int.bitwise_and(hex, 0xff) - |> int.to_float() - |> float.divide(255.0) - from_rgba(r, g, b, a) - } - } -} - -// CONVERSIONS ---------------------------------------------------------------- - -/// Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s -/// R, G, B, and A values respectively. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb255(255, 0, 0) -/// let #(r, g, b, a) = to_rgba(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_rgba(colour: Colour) -> #(Float, Float, Float, Float) { - case colour { - Rgba(r, g, b, a) -> #(r, g, b, a) - Hsla(h, s, l, a) -> hsla_to_rgba(h, s, l, a) - } -} - -/// Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s -/// H, S, L, and A values respectively. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb255(255, 0, 0) -/// let #(h, s, l, a) = to_hsla(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_hsla(colour: Colour) -> #(Float, Float, Float, Float) { - case colour { - Hsla(h, s, l, a) -> #(h, s, l, a) - Rgba(r, g, b, a) -> rgba_to_hsla(r, g, b, a) - } -} - -/// Returns an rgba formatted CSS `String` created from the given `Colour`. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgb255(255, 0, 0) -/// let css_red = to_css_rgba_string(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_css_rgba_string(colour: Colour) -> String { - let #(r, g, b, a) = to_rgba(colour) - - let percent = fn(x: Float) -> Float { - // This won't fail because we are always dividing by 100.0 - let assert Ok(p) = - x - |> float.multiply(10_000.0) - |> float.round() - |> int.to_float() - |> float.divide(100.0) - - p - } - - let round_to = fn(x: Float) -> Float { - // This won't fail because we are always dividing by 1000.0 - let assert Ok(r) = - x - |> float.multiply(1000.0) - |> float.round() - |> int.to_float() - |> float.divide(1000.0) - - r - } - - string.join( - [ - "rgba(", - float.to_string(percent(r)) <> "%,", - float.to_string(percent(g)) <> "%,", - float.to_string(percent(b)) <> "%,", - float.to_string(round_to(a)), - ")", - ], - "", - ) -} - -/// Returns an rgba hex formatted `String` created from the given `Colour`. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0) -/// let red_hex = to_rgba_hex_string(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_rgba_hex_string(colour: Colour) -> String { - let hex_string = - to_rgba_hex(colour) - |> int.to_base16() - - case string.length(hex_string) { - 8 -> hex_string - l -> string.repeat("0", 8 - l) <> hex_string - } -} - -/// Returns an rgb hex formatted `String` created from the given `Colour`. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgba(255, 0, 0) -/// let red_hex = to_rgb_hex_string(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_rgb_hex_string(colour: Colour) -> String { - let hex_string = - to_rgb_hex(colour) - |> int.to_base16() - - case string.length(hex_string) { - 6 -> hex_string - l -> string.repeat("0", 6 - l) <> hex_string - } -} - -/// Returns an hex `Int` created from the given `Colour`. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0) -/// let red_hex_int = to_rgba_hex(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_rgba_hex(colour: Colour) -> Int { - let #(r, g, b, a) = to_rgba(colour) - - let red = - r *. 255.0 - |> float.round() - |> int.bitwise_shift_left(24) - - let green = - g *. 255.0 - |> float.round() - |> int.bitwise_shift_left(16) - - let blue = - b *. 255.0 - |> float.round() - |> int.bitwise_shift_left(8) - - let alpha = - a *. 255.0 - |> float.round() - - red + green + blue + alpha -} - -/// Returns a rgb hex `Int` created from the given `Colour`. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// assert Ok(red) = from_rgba(255, 0, 0) -/// let red_hex_int = to_rgb_hex(red) -/// } -/// ``` -///
-/// -/// -/// -pub fn to_rgb_hex(colour: Colour) -> Int { - let #(r, g, b, _) = to_rgba(colour) - - let red = - r *. 255.0 - |> float.round() - |> int.bitwise_shift_left(16) - - let green = - g *. 255.0 - |> float.round() - |> int.bitwise_shift_left(8) - - let blue = - b *. 255.0 - |> float.round() - - red + green + blue -} - -// JSON ------------------------------------------------------------------------ - -/// Encodes a `Colour` value as a Gleam [`Json`](https://hexdocs.pm/gleam_json/gleam/json.html#Json) -/// value. You'll need this if you want to send a `Colour` value over the network -/// in a HTTP request or response, for example. -/// -/// -/// -pub fn encode(colour: Colour) -> Json { - case colour { - Rgba(r, g, b, a) -> encode_rgba(r, g, b, a) - Hsla(h, s, l, a) -> encode_hsla(h, s, l, a) - } -} - -fn encode_rgba(r: Float, g: Float, b: Float, a: Float) -> Json { - json.object([ - #("r", json.float(r)), - #("g", json.float(g)), - #("b", json.float(b)), - #("a", json.float(a)), - ]) -} - -fn encode_hsla(h: Float, s: Float, l: Float, a: Float) -> Json { - json.object([ - #("h", json.float(h)), - #("s", json.float(s)), - #("l", json.float(l)), - #("a", json.float(a)), - ]) -} - -/// Attempt to decode some [`Dynamic`](https://hexdocs.pm/gleam_stdlib/gleam/dynamic.html#Dynamic) -/// value into a `Colour`. Most often you'll use this to decode some JSON. -/// -/// -/// -pub fn decoder() -> decode.Decoder(Colour) { - decode.one_of(rgba_decoder(), or: [hsla_decoder()]) -} - -fn rgba_decoder() -> decode.Decoder(Colour) { - use r <- decode.field("r", decode.float) - use g <- decode.field("g", decode.float) - use b <- decode.field("b", decode.float) - use a <- decode.field("a", decode.float) - - decode.success(Rgba(r, g, b, a)) -} - -fn hsla_decoder() -> decode.Decoder(Colour) { - use h <- decode.field("h", decode.float) - use s <- decode.field("s", decode.float) - use l <- decode.field("l", decode.float) - use a <- decode.field("a", decode.float) - - decode.success(Hsla(h, s, l, a)) -} - -// COLOURS --------------------------------------------------------------------- - -/// A `Colour` reprsenting the colour RGBA(239, 41, 41, 1.0) -pub const light_red = Rgba( - r: 0.9372549019607843, - g: 0.1607843137254902, - b: 0.1607843137254902, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(204, 0, 0, 1.0) -pub const red = Rgba(r: 0.8, g: 0.0, b: 0.0, a: 1.0) - -/// A `Colour` reprsenting the colour RGBA(164, 0, 0, 1.0) -pub const dark_red = Rgba(r: 0.6431372549019608, g: 0.0, b: 0.0, a: 1.0) - -/// A `Colour` reprsenting the colour RGBA(252, 175, 62, 1.0) -pub const light_orange = Rgba( - r: 0.9882352941176471, - g: 0.6862745098039216, - b: 0.24313725490196078, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(245, 121, 0, 1.0) -pub const orange = Rgba( - r: 0.9607843137254902, - g: 0.4745098039215686, - b: 0.0, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(206, 92, 0, 1.0) -pub const dark_orange = Rgba( - r: 0.807843137254902, - g: 0.3607843137254902, - b: 0.0, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(255, 233, 79, 1.0) -pub const light_yellow = Rgba( - r: 1.0, - g: 0.9137254901960784, - b: 0.30980392156862746, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(237, 212, 0, 1.0) -pub const yellow = Rgba( - r: 0.9294117647058824, - g: 0.8313725490196079, - b: 0.0, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(196, 160, 0, 1.0) -pub const dark_yellow = Rgba( - r: 0.7686274509803922, - g: 0.6274509803921569, - b: 0.0, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(138, 226, 52, 1.0) -pub const light_green = Rgba( - r: 0.5411764705882353, - g: 0.8862745098039215, - b: 0.20392156862745098, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(115, 210, 22, 1.0) -pub const green = Rgba( - r: 0.45098039215686275, - g: 0.8235294117647058, - b: 0.08627450980392157, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(78, 154, 6, 1.0) -pub const dark_green = Rgba( - r: 0.3058823529411765, - g: 0.6039215686274509, - b: 0.023529411764705882, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(114, 159, 207, 1.0) -pub const light_blue = Rgba( - r: 0.4470588235294118, - g: 0.6235294117647059, - b: 0.8117647058823529, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(52, 101, 164, 1.0) -pub const blue = Rgba( - r: 0.20392156862745098, - g: 0.396078431372549, - b: 0.6431372549019608, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(32, 74, 135, 1.0) -pub const dark_blue = Rgba( - r: 0.12549019607843137, - g: 0.2901960784313726, - b: 0.5294117647058824, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(173, 127, 168, 1.0) -pub const light_purple = Rgba( - r: 0.6784313725490196, - g: 0.4980392156862745, - b: 0.6588235294117647, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(117, 80, 123, 1.0) -pub const purple = Rgba( - r: 0.4588235294117647, - g: 0.3137254901960784, - b: 0.4823529411764706, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(92, 53, 102, 1.0) -pub const dark_purple = Rgba( - r: 0.3607843137254902, - g: 0.20784313725490197, - b: 0.4, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(233, 185, 110, 1.0) -pub const light_brown = Rgba( - r: 0.9137254901960784, - g: 0.7254901960784313, - b: 0.43137254901960786, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(193, 125, 17, 1.0) -pub const brown = Rgba( - r: 0.7568627450980392, - g: 0.49019607843137253, - b: 0.06666666666666667, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(143, 89, 2, 1.0) -pub const dark_brown = Rgba( - r: 0.5607843137254902, - g: 0.34901960784313724, - b: 0.00784313725490196, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(0, 0, 0, 1.0) -pub const black = Rgba(r: 0.0, g: 0.0, b: 0.0, a: 1.0) - -/// A `Colour` reprsenting the colour RGBA(255, 255, 255, 1.0) -pub const white = Rgba(r: 1.0, g: 1.0, b: 1.0, a: 1.0) - -/// A `Colour` reprsenting the colour RGBA(238, 238, 236, 1.0) -pub const light_grey = Rgba( - r: 0.9333333333333333, - g: 0.9333333333333333, - b: 0.9254901960784314, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(211, 215, 207, 1.0) -pub const grey = Rgba( - r: 0.8274509803921568, - g: 0.8431372549019608, - b: 0.8117647058823529, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(186, 189, 182, 1.0) -pub const dark_grey = Rgba( - r: 0.7294117647058823, - g: 0.7411764705882353, - b: 0.7137254901960784, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(238, 238, 236, 1.0) -pub const light_gray = Rgba( - r: 0.9333333333333333, - g: 0.9333333333333333, - b: 0.9254901960784314, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(211, 215, 207, 1.0) -pub const gray = Rgba( - r: 0.8274509803921568, - g: 0.8431372549019608, - b: 0.8117647058823529, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(186, 189, 182, 1.0) -pub const dark_gray = Rgba( - r: 0.7294117647058823, - g: 0.7411764705882353, - b: 0.7137254901960784, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(136, 138, 133, 1.0) -pub const light_charcoal = Rgba( - r: 0.5333333333333333, - g: 0.5411764705882353, - b: 0.5215686274509804, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(85, 87, 83, 1.0) -pub const charcoal = Rgba( - r: 0.3333333333333333, - g: 0.3411764705882353, - b: 0.3254901960784314, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(46, 52, 54, 1.0) -pub const dark_charcoal = Rgba( - r: 0.1803921568627451, - g: 0.20392156862745098, - b: 0.21176470588235294, - a: 1.0, -) - -/// A `Colour` reprsenting the colour RGBA(255, 175, 243, 1.0) -pub const pink = Rgba( - r: 1.0, - g: 0.6862745098039216, - b: 0.9529411764705882, - a: 1.0, -) diff --git a/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam b/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam deleted file mode 100644 index 54f75e4..0000000 --- a/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam +++ /dev/null @@ -1,173 +0,0 @@ -//// -//// - **Accessibility** -//// - [`luminance`](#luminance) -//// - [`contrast_ratio`](#contrast_ratio) -//// - [`maximum_contrast`](#maximum_contrast) -//// -//// --- -//// -//// This package was heavily inspired by the `elm-color-extra` module. -//// The original source code can be found -//// here. -//// -////
-//// The license of that package is produced below: -//// -//// -//// > MIT License -//// -//// > Copyright (c) 2016 Andreas Köberle -//// -//// > Permission is hereby granted, free of charge, to any person obtaining a copy -//// of this software and associated documentation files (the "Software"), to deal -//// in the Software without restriction, including without limitation the rights -//// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//// copies of the Software, and to permit persons to whom the Software is -//// furnished to do so, subject to the following conditions: -//// -//// > The above copyright notice and this permission notice shall be included in all -//// copies or substantial portions of the Software. -//// -//// > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//// SOFTWARE. -//// -////
-//// - -// Just in case we decide in the future to no longer include the above reference -// and license, this package was initially a port of the `elm-color-extra` module: -// -// https://github.com/noahzgordon/elm-color-extra -// - -// IMPORTS -------------------------------------------------------------------- - -import gleam/float -import gleam/list -import gleam_community/colour.{type Colour} - -// UTILITIES ------------------------------------------------------------------ - -fn intensity(colour_value: Float) -> Float { - // Calculation taken from https://www.w3.org/TR/WCAG20/#relativeluminancedef - case True { - _ if colour_value <=. 0.03928 -> colour_value /. 12.92 - _ -> { - // Is this guaranteed to be `OK`? - let assert Ok(i) = float.power({ colour_value +. 0.055 } /. 1.055, 2.4) - i - } - } -} - -// ACCESSIBILITY -------------------------------------------------------------- - -/// Returns the relative brightness of the given `Colour` as a `Float` between -/// 0.0, and 1.0 with 0.0 being the darkest possible colour and 1.0 being the lightest. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// luminance(colour.white) // 1.0 -/// } -/// ``` -///
-/// -/// -/// -pub fn luminance(colour: Colour) -> Float { - // Calculation taken from https://www.w3.org/TR/WCAG20/#relativeluminancedef - let #(r, g, b, _) = colour.to_rgba(colour) - - let r_intensity = intensity(r) - let g_intensity = intensity(g) - let b_intensity = intensity(b) - - 0.2126 *. r_intensity +. 0.7152 *. g_intensity +. 0.0722 *. b_intensity -} - -/// Returns the contrast between two `Colour` values as a `Float` between 1.0, -/// and 21.0 with 1.0 being no contrast and, 21.0 being the highest possible contrast. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// contrast_ratio(between: colour.white, and: colour.black) // 21.0 -/// } -/// ``` -///
-/// -/// -/// -pub fn contrast_ratio(between colour_a: Colour, and colour_b: Colour) -> Float { - // Calculation taken from https://www.w3.org/TR/WCAG20/#contrast-ratiodef - let luminance_a = luminance(colour_a) +. 0.05 - let luminance_b = luminance(colour_b) +. 0.05 - - case luminance_a >. luminance_b { - True -> luminance_a /. luminance_b - False -> luminance_b /. luminance_a - } -} - -/// Returns the `Colour` with the highest contrast between the base `Colour`, -/// and and the other provided `Colour` values. -/// -///
-/// Example: -/// -/// ```gleam -/// fn example() { -/// maximum_contrast( -/// colour.yellow, -/// [colour.white, colour.dark_blue, colour.green], -/// ) -/// } -/// ``` -///
-/// -/// -/// -pub fn maximum_contrast( - base: Colour, - colours: List(Colour), -) -> Result(Colour, Nil) { - colours - |> list.sort(fn(colour_a, colour_b) { - let contrast_a = contrast_ratio(base, colour_a) - let contrast_b = contrast_ratio(base, colour_b) - - float.compare(contrast_b, contrast_a) - }) - |> list.first() -} diff --git a/build/packages/gleam_community_colour/src/gleam_community@colour.erl b/build/packages/gleam_community_colour/src/gleam_community@colour.erl deleted file mode 100644 index faee070..0000000 --- a/build/packages/gleam_community_colour/src/gleam_community@colour.erl +++ /dev/null @@ -1,1199 +0,0 @@ --module(gleam_community@colour). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/gleam_community/colour.gleam"). --export([from_rgb255/3, from_rgb/3, from_rgba/4, from_hsla/4, from_hsl/3, from_rgb_hex/1, from_rgb_hex_string/1, from_rgba_hex/1, from_rgba_hex_string/1, to_rgba/1, to_hsla/1, to_css_rgba_string/1, to_rgba_hex/1, to_rgba_hex_string/1, to_rgb_hex/1, to_rgb_hex_string/1, encode/1, decoder/0]). --export_type([colour/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - "\n" - " - **Types**\n" - " - [`Colour`](#Colour)\n" - " - [`Color`](#Color)\n" - " - **Constructors**\n" - " - [`from_rgb255`](#from_rgb255)\n" - " - [`from_rgb`](#from_rgb)\n" - " - [`from_rgba`](#from_rgba)\n" - " - [`from_hsl`](#from_hsl)\n" - " - [`from_hsla`](#from_hsla)\n" - " - [`from_rgb_hex`](#from_rgb_hex)\n" - " - [`from_rgba_hex`](#from_rgba_hex)\n" - " - [`from_rgb_hex_string`](#from_rgb_hex_string)\n" - " - [`from_rgba_hex_string`](#from_rgba_hex_string)\n" - " - **Conversions**\n" - " - [`to_rgba`](#to_rgba)\n" - " - [`to_hsla`](#hsla)\n" - " - [`to_css_rgba_string`](#to_css_rgba_string)\n" - " - [`to_rgba_hex_string`](#to_rgba_hex_string)\n" - " - [`to_rgb_hex_string`](#to_rgb_hex_string)\n" - " - [`to_rgba_hex`](#to_rgba_hex)\n" - " - [`to_rgb_hex`](#to_rgb_hex)\n" - " - **JSON**\n" - " - [`encode`](#encode)\n" - " - [`decoder`](#decoder)\n" - " - **Colours**\n" - " - [`light_red`](#light_red)\n" - " - [`red`](#red)\n" - " - [`dark_red`](#dark_red)\n" - " - [`light_orange`](#light_orange)\n" - " - [`orange`](#orange)\n" - " - [`dark_orange`](#dark_orange)\n" - " - [`light_yellow`](#light_yellow)\n" - " - [`yellow`](#yellow)\n" - " - [`dark_yellow`](#dark_yellow)\n" - " - [`light_green`](#light_green)\n" - " - [`green`](#green)\n" - " - [`dark_green`](#dark_green)\n" - " - [`light_blue`](#light_blue)\n" - " - [`blue`](#blue)\n" - " - [`dark_blue`](#dark_blue)\n" - " - [`light_purple`](#light_purple)\n" - " - [`purple`](#purple)\n" - " - [`dark_purple`](#dark_purple)\n" - " - [`light_brown`](#light_brown)\n" - " - [`brown`](#brown)\n" - " - [`dark_brown`](#dark_brown)\n" - " - [`black`](#black)\n" - " - [`white`](#white)\n" - " - [`light_grey`](#light_grey)\n" - " - [`grey`](#grey)\n" - " - [`dark_grey`](#dark_grey)\n" - " - [`light_gray`](#light_gray)\n" - " - [`gray`](#gray)\n" - " - [`dark_gray`](#dark_gray)\n" - " - [`light_charcoal`](#light_charcoal)\n" - " - [`charcoal`](#charcoal)\n" - " - [`dark_charcoal`](#dark_charcoal)\n" - " - [`pink`](#pink)\n" - "\n" - " ---\n" - "\n" - " This package was heavily inspired by the `elm-color` module.\n" - " The original source code can be found\n" - " here.\n" - "\n" - "
\n" - " The license of that package is produced below:\n" - "\n" - "\n" - " > MIT License\n" - "\n" - " > Copyright 2018 Aaron VonderHaar\n" - "\n" - " > Redistribution and use in source and binary forms, with or without modification,\n" - " are permitted provided that the following conditions are met:\n" - "\n" - " 1. Redistributions of source code must retain the above copyright notice,\n" - " this list of conditions and the following disclaimer.\n" - "\n" - " 2. Redistributions in binary form must reproduce the above copyright notice,\n" - " this list of conditions and the following disclaimer in the documentation\n" - " and/or other materials provided with the distribution.\n" - "\n" - " 3. Neither the name of the copyright holder nor the names of its contributors\n" - " may be used to endorse or promote products derived from this software without\n" - " specific prior written permission.\n" - "\n" - " > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n" - " ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" - " OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\n" - " THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n" - " EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n" - " OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" - " THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" - " ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" - "\n" - " > The above copyright notice and this permission notice shall be included in all\n" - " copies or substantial portions of the Software.\n" - "
\n" - "\n" -). - --opaque colour() :: {rgba, float(), float(), float(), float()} | - {hsla, float(), float(), float(), float()}. - --file("src/gleam_community/colour.gleam", 155). --spec valid_colour_value(float()) -> {ok, float()} | {error, nil}. -valid_colour_value(C) -> - case (C > 1.0) orelse (C < +0.0) of - true -> - {error, nil}; - - false -> - {ok, C} - end. - --file("src/gleam_community/colour.gleam", 162). --spec hue_to_rgb(float(), float(), float()) -> float(). -hue_to_rgb(Hue, M1, M2) -> - H = case Hue of - _ when Hue < +0.0 -> - Hue + 1.0; - - _ when Hue > 1.0 -> - Hue - 1.0; - - _ -> - Hue - end, - H_t_6 = H * 6.0, - H_t_2 = H * 2.0, - H_t_3 = H * 3.0, - case H of - _ when H_t_6 < 1.0 -> - M1 + (((M2 - M1) * H) * 6.0); - - _ when H_t_2 < 1.0 -> - M2; - - _ when H_t_3 < 2.0 -> - M1 + (((M2 - M1) * ((2.0 / 3.0) - H)) * 6.0); - - _ -> - M1 - end. - --file("src/gleam_community/colour.gleam", 181). --spec hex_string_to_int(binary()) -> {ok, integer()} | {error, nil}. -hex_string_to_int(Hex_string) -> - Hex = case Hex_string of - <<"#"/utf8, Hex_number/binary>> -> - Hex_number; - - <<"0x"/utf8, Hex_number@1/binary>> -> - Hex_number@1; - - _ -> - Hex_string - end, - _pipe = Hex, - _pipe@1 = string:lowercase(_pipe), - _pipe@2 = gleam@string:to_graphemes(_pipe@1), - _pipe@3 = lists:reverse(_pipe@2), - gleam@list:index_fold( - _pipe@3, - {ok, 0}, - fun(Total, Char, Index) -> case Total of - {error, nil} -> - {error, nil}; - - {ok, V} -> - gleam@result:'try'(case Char of - <<"a"/utf8>> -> - {ok, 10}; - - <<"b"/utf8>> -> - {ok, 11}; - - <<"c"/utf8>> -> - {ok, 12}; - - <<"d"/utf8>> -> - {ok, 13}; - - <<"e"/utf8>> -> - {ok, 14}; - - <<"f"/utf8>> -> - {ok, 15}; - - _ -> - gleam_stdlib:parse_int(Char) - end, fun(Num) -> - gleam@result:'try'( - gleam@int:power(16, erlang:float(Index)), - fun(Base) -> - {ok, - V + erlang:round( - erlang:float(Num) * Base - )} - end - ) - end) - end end - ). - --file("src/gleam_community/colour.gleam", 212). --spec hsla_to_rgba(float(), float(), float(), float()) -> {float(), - float(), - float(), - float()}. -hsla_to_rgba(H, S, L, A) -> - M2 = case L =< 0.5 of - true -> - L * (S + 1.0); - - false -> - (L + S) - (L * S) - end, - M1 = (L * 2.0) - M2, - R = hue_to_rgb(H + (1.0 / 3.0), M1, M2), - G = hue_to_rgb(H, M1, M2), - B = hue_to_rgb(H - (1.0 / 3.0), M1, M2), - {R, G, B, A}. - --file("src/gleam_community/colour.gleam", 232). --spec rgba_to_hsla(float(), float(), float(), float()) -> {float(), - float(), - float(), - float()}. -rgba_to_hsla(R, G, B, A) -> - Min_colour = gleam@float:min(R, gleam@float:min(G, B)), - Max_colour = gleam@float:max(R, gleam@float:max(G, B)), - H1 = case true of - _ when Max_colour =:= R -> - gleam@float:divide(G - B, Max_colour - Min_colour); - - _ when Max_colour =:= G -> - _pipe = gleam@float:divide(B - R, Max_colour - Min_colour), - gleam@result:'try'(_pipe, fun(D) -> {ok, 2.0 + D} end); - - _ -> - _pipe@1 = gleam@float:divide(R - G, Max_colour - Min_colour), - gleam@result:'try'(_pipe@1, fun(D@1) -> {ok, 4.0 + D@1} end) - end, - H2 = case H1 of - {ok, V} -> - {ok, V * (1.0 / 6.0)}; - - _ -> - H1 - end, - H3 = case H2 of - {ok, V@1} when V@1 < +0.0 -> - V@1 + 1.0; - - {ok, V@2} -> - V@2; - - _ -> - +0.0 - end, - L = (Min_colour + Max_colour) / 2.0, - S = case true of - _ when Min_colour =:= Max_colour -> - +0.0; - - _ when L < 0.5 -> - case (Max_colour + Min_colour) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> (Max_colour - Min_colour) / Gleam@denominator - end; - - _ -> - case ((2.0 - Max_colour) - Min_colour) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> (Max_colour - Min_colour) / Gleam@denominator@1 - end - end, - {H3, S, L, A}. - --file("src/gleam_community/colour.gleam", 300). -?DOC( - " Returns a `Result(Colour)` created from the given 8 bit RGB values.\n" - "\n" - " Returns `Error(Nil)` if the supplied RGB values are greater than 255 or less than 0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb255(integer(), integer(), integer()) -> {ok, colour()} | - {error, nil}. -from_rgb255(Red, Green, Blue) -> - gleam@result:'try'( - begin - _pipe = Red, - _pipe@1 = erlang:float(_pipe), - _pipe@2 = gleam@float:divide(_pipe@1, 255.0), - gleam@result:'try'(_pipe@2, fun valid_colour_value/1) - end, - fun(R) -> - gleam@result:'try'( - begin - _pipe@3 = Green, - _pipe@4 = erlang:float(_pipe@3), - _pipe@5 = gleam@float:divide(_pipe@4, 255.0), - gleam@result:'try'(_pipe@5, fun valid_colour_value/1) - end, - fun(G) -> - gleam@result:'try'( - begin - _pipe@6 = Blue, - _pipe@7 = erlang:float(_pipe@6), - _pipe@8 = gleam@float:divide(_pipe@7, 255.0), - gleam@result:'try'( - _pipe@8, - fun valid_colour_value/1 - ) - end, - fun(B) -> {ok, {rgba, R, G, B, 1.0}} end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 348). -?DOC( - " Returns `Result(Colour)` created from the given RGB values.\n" - "\n" - " If the supplied RGB values are greater than 1.0 or less than 0.0 returns `Error(Nil)`\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb(1.0, 0.0, 0.0)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb(float(), float(), float()) -> {ok, colour()} | {error, nil}. -from_rgb(Red, Green, Blue) -> - gleam@result:'try'( - valid_colour_value(Red), - fun(R) -> - gleam@result:'try'( - valid_colour_value(Green), - fun(G) -> - gleam@result:'try'( - valid_colour_value(Blue), - fun(B) -> {ok, {rgba, R, G, B, 1.0}} end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 383). -?DOC( - " Returns `Result(Colour)` created from the given RGBA values.\n" - "\n" - " Returns `Error(Nil)` if the supplied RGBA values are greater than 1.0 or less than 0.0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_rbga(1.0, 0.0, 0.0, 0.5)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgba(float(), float(), float(), float()) -> {ok, colour()} | - {error, nil}. -from_rgba(Red, Green, Blue, Alpha) -> - gleam@result:'try'( - valid_colour_value(Red), - fun(R) -> - gleam@result:'try'( - valid_colour_value(Green), - fun(G) -> - gleam@result:'try'( - valid_colour_value(Blue), - fun(B) -> - gleam@result:'try'( - valid_colour_value(Alpha), - fun(A) -> {ok, {rgba, R, G, B, A}} end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 420). -?DOC( - " Returns `Result(Colour)` created from the given HSLA values.\n" - "\n" - " Returns `Error(Nil)`f the supplied HSLA values are greater than 1.0 or less than 0.0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_hsla(0.0, 1.0, 0.5, 0.5)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_hsla(float(), float(), float(), float()) -> {ok, colour()} | - {error, nil}. -from_hsla(Hue, Saturation, Lightness, Alpha) -> - gleam@result:'try'( - valid_colour_value(Hue), - fun(H) -> - gleam@result:'try'( - valid_colour_value(Saturation), - fun(S) -> - gleam@result:'try'( - valid_colour_value(Lightness), - fun(L) -> - gleam@result:'try'( - valid_colour_value(Alpha), - fun(A) -> {ok, {hsla, H, S, L, A}} end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 457). -?DOC( - " Returns `Result(Colour)` created from the given HSL values.\n" - "\n" - " Returns `Error(Nil)` if the supplied HSL values are greater than 1.0 or less than 0.0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_hsla(0.0, 1.0, 0.5)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_hsl(float(), float(), float()) -> {ok, colour()} | {error, nil}. -from_hsl(Hue, Saturation, Lightness) -> - from_hsla(Hue, Saturation, Lightness, 1.0). - --file("src/gleam_community/colour.gleam", 488). -?DOC( - " Returns a `Result(Colour)` created from the given hex `Int`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffff or less than 0x0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb_hex(0xff0000)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb_hex(integer()) -> {ok, colour()} | {error, nil}. -from_rgb_hex(Hex) -> - case (Hex > 16#ffffff) orelse (Hex < 0) of - true -> - {error, nil}; - - false -> - R = begin - _pipe = erlang:'bsr'(Hex, 16), - erlang:'band'(_pipe, 16#ff) - end, - G = begin - _pipe@1 = erlang:'bsr'(Hex, 8), - erlang:'band'(_pipe@1, 16#ff) - end, - B = erlang:'band'(Hex, 16#ff), - from_rgb255(R, G, B) - end. - --file("src/gleam_community/colour.gleam", 527). -?DOC( - " Returns a `Result(Colour)` created from the given RGB hex `String`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `\"#ffffff\" or less than `\"#0\"`\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb_hex_string(\"#ff0000\")\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgb_hex_string(binary()) -> {ok, colour()} | {error, nil}. -from_rgb_hex_string(Hex_string) -> - gleam@result:'try'( - hex_string_to_int(Hex_string), - fun(Hex_int) -> from_rgb_hex(Hex_int) end - ). - --file("src/gleam_community/colour.gleam", 585). -?DOC( - " Returns a `Result(Colour)` created from the given hex `Int`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffffff or less than 0x0.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_rgba_hex(0xff00007f)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgba_hex(integer()) -> {ok, colour()} | {error, nil}. -from_rgba_hex(Hex) -> - case (Hex > 16#ffffffff) orelse (Hex < 0) of - true -> - {error, nil}; - - false -> - R@1 = case begin - _pipe = erlang:'bsr'(Hex, 24), - _pipe@1 = erlang:'band'(_pipe, 16#ff), - _pipe@2 = erlang:float(_pipe@1), - gleam@float:divide(_pipe@2, 255.0) - end of - {ok, R} -> R; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 590, - value => _assert_fail, - start => 17111, - 'end' => 17260, - pattern_start => 17122, - pattern_end => 17127}) - end, - G@1 = case begin - _pipe@3 = erlang:'bsr'(Hex, 16), - _pipe@4 = erlang:'band'(_pipe@3, 16#ff), - _pipe@5 = erlang:float(_pipe@4), - gleam@float:divide(_pipe@5, 255.0) - end of - {ok, G} -> G; - _assert_fail@1 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 596, - value => _assert_fail@1, - start => 17332, - 'end' => 17481, - pattern_start => 17343, - pattern_end => 17348}) - end, - B@1 = case begin - _pipe@6 = erlang:'bsr'(Hex, 8), - _pipe@7 = erlang:'band'(_pipe@6, 16#ff), - _pipe@8 = erlang:float(_pipe@7), - gleam@float:divide(_pipe@8, 255.0) - end of - {ok, B} -> B; - _assert_fail@2 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 602, - value => _assert_fail@2, - start => 17553, - 'end' => 17701, - pattern_start => 17564, - pattern_end => 17569}) - end, - A@1 = case begin - _pipe@9 = erlang:'band'(Hex, 16#ff), - _pipe@10 = erlang:float(_pipe@9), - gleam@float:divide(_pipe@10, 255.0) - end of - {ok, A} -> A; - _assert_fail@3 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"from_rgba_hex"/utf8>>, - line => 608, - value => _assert_fail@3, - start => 17773, - 'end' => 17883, - pattern_start => 17784, - pattern_end => 17789}) - end, - from_rgba(R@1, G@1, B@1, A@1) - end. - --file("src/gleam_community/colour.gleam", 556). -?DOC( - " Returns a `Result(Colour)` created from the given RGBA hex `String`.\n" - "\n" - " Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `\"#ffffffff\" or less than `\"#0\"`\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red_half_opacity) = from_rgba_hex_string(\"#ff00007f\")\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec from_rgba_hex_string(binary()) -> {ok, colour()} | {error, nil}. -from_rgba_hex_string(Hex_string) -> - gleam@result:'try'( - hex_string_to_int(Hex_string), - fun(Hex_int) -> from_rgba_hex(Hex_int) end - ). - --file("src/gleam_community/colour.gleam", 642). -?DOC( - " Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s\n" - " R, G, B, and A values respectively.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " let #(r, g, b, a) = to_rgba(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgba(colour()) -> {float(), float(), float(), float()}. -to_rgba(Colour) -> - case Colour of - {rgba, R, G, B, A} -> - {R, G, B, A}; - - {hsla, H, S, L, A@1} -> - hsla_to_rgba(H, S, L, A@1) - end. - --file("src/gleam_community/colour.gleam", 672). -?DOC( - " Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s\n" - " H, S, L, and A values respectively.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " let #(h, s, l, a) = to_hsla(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_hsla(colour()) -> {float(), float(), float(), float()}. -to_hsla(Colour) -> - case Colour of - {hsla, H, S, L, A} -> - {H, S, L, A}; - - {rgba, R, G, B, A@1} -> - rgba_to_hsla(R, G, B, A@1) - end. - --file("src/gleam_community/colour.gleam", 701). -?DOC( - " Returns an rgba formatted CSS `String` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgb255(255, 0, 0)\n" - " let css_red = to_css_rgba_string(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_css_rgba_string(colour()) -> binary(). -to_css_rgba_string(Colour) -> - {R, G, B, A} = to_rgba(Colour), - Percent = fun(X) -> - P@1 = case begin - _pipe = X, - _pipe@1 = gleam@float:multiply(_pipe, 10000.0), - _pipe@2 = erlang:round(_pipe@1), - _pipe@3 = erlang:float(_pipe@2), - gleam@float:divide(_pipe@3, 100.0) - end of - {ok, P} -> P; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"to_css_rgba_string"/utf8>>, - line => 706, - value => _assert_fail, - start => 20510, - 'end' => 20646, - pattern_start => 20521, - pattern_end => 20526}) - end, - P@1 - end, - Round_to = fun(X@1) -> - R@2 = case begin - _pipe@4 = X@1, - _pipe@5 = gleam@float:multiply(_pipe@4, 1000.0), - _pipe@6 = erlang:round(_pipe@5), - _pipe@7 = erlang:float(_pipe@6), - gleam@float:divide(_pipe@7, 1000.0) - end of - {ok, R@1} -> R@1; - _assert_fail@1 -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour"/utf8>>, - function => <<"to_css_rgba_string"/utf8>>, - line => 718, - value => _assert_fail@1, - start => 20768, - 'end' => 20903, - pattern_start => 20779, - pattern_end => 20784}) - end, - R@2 - end, - gleam@string:join( - [<<"rgba("/utf8>>, - <<(gleam_stdlib:float_to_string(Percent(R)))/binary, "%,"/utf8>>, - <<(gleam_stdlib:float_to_string(Percent(G)))/binary, "%,"/utf8>>, - <<(gleam_stdlib:float_to_string(Percent(B)))/binary, "%,"/utf8>>, - gleam_stdlib:float_to_string(Round_to(A)), - <<")"/utf8>>], - <<""/utf8>> - ). - --file("src/gleam_community/colour.gleam", 829). -?DOC( - " Returns an hex `Int` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0)\n" - " let red_hex_int = to_rgba_hex(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgba_hex(colour()) -> integer(). -to_rgba_hex(Colour) -> - {R, G, B, A} = to_rgba(Colour), - Red = begin - _pipe = R * 255.0, - _pipe@1 = erlang:round(_pipe), - erlang:'bsl'(_pipe@1, 24) - end, - Green = begin - _pipe@2 = G * 255.0, - _pipe@3 = erlang:round(_pipe@2), - erlang:'bsl'(_pipe@3, 16) - end, - Blue = begin - _pipe@4 = B * 255.0, - _pipe@5 = erlang:round(_pipe@4), - erlang:'bsl'(_pipe@5, 8) - end, - Alpha = begin - _pipe@6 = A * 255.0, - erlang:round(_pipe@6) - end, - ((Red + Green) + Blue) + Alpha. - --file("src/gleam_community/colour.gleam", 763). -?DOC( - " Returns an rgba hex formatted `String` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0)\n" - " let red_hex = to_rgba_hex_string(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgba_hex_string(colour()) -> binary(). -to_rgba_hex_string(Colour) -> - Hex_string = begin - _pipe = to_rgba_hex(Colour), - gleam@int:to_base16(_pipe) - end, - case string:length(Hex_string) of - 8 -> - Hex_string; - - L -> - <<(gleam@string:repeat(<<"0"/utf8>>, 8 - L))/binary, - Hex_string/binary>> - end. - --file("src/gleam_community/colour.gleam", 876). -?DOC( - " Returns a rgb hex `Int` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(255, 0, 0)\n" - " let red_hex_int = to_rgb_hex(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgb_hex(colour()) -> integer(). -to_rgb_hex(Colour) -> - {R, G, B, _} = to_rgba(Colour), - Red = begin - _pipe = R * 255.0, - _pipe@1 = erlang:round(_pipe), - erlang:'bsl'(_pipe@1, 16) - end, - Green = begin - _pipe@2 = G * 255.0, - _pipe@3 = erlang:round(_pipe@2), - erlang:'bsl'(_pipe@3, 8) - end, - Blue = begin - _pipe@4 = B * 255.0, - erlang:round(_pipe@4) - end, - (Red + Green) + Blue. - --file("src/gleam_community/colour.gleam", 796). -?DOC( - " Returns an rgb hex formatted `String` created from the given `Colour`.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " assert Ok(red) = from_rgba(255, 0, 0)\n" - " let red_hex = to_rgb_hex_string(red)\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec to_rgb_hex_string(colour()) -> binary(). -to_rgb_hex_string(Colour) -> - Hex_string = begin - _pipe = to_rgb_hex(Colour), - gleam@int:to_base16(_pipe) - end, - case string:length(Hex_string) of - 6 -> - Hex_string; - - L -> - <<(gleam@string:repeat(<<"0"/utf8>>, 6 - L))/binary, - Hex_string/binary>> - end. - --file("src/gleam_community/colour.gleam", 918). --spec encode_rgba(float(), float(), float(), float()) -> gleam@json:json(). -encode_rgba(R, G, B, A) -> - gleam@json:object( - [{<<"r"/utf8>>, gleam@json:float(R)}, - {<<"g"/utf8>>, gleam@json:float(G)}, - {<<"b"/utf8>>, gleam@json:float(B)}, - {<<"a"/utf8>>, gleam@json:float(A)}] - ). - --file("src/gleam_community/colour.gleam", 927). --spec encode_hsla(float(), float(), float(), float()) -> gleam@json:json(). -encode_hsla(H, S, L, A) -> - gleam@json:object( - [{<<"h"/utf8>>, gleam@json:float(H)}, - {<<"s"/utf8>>, gleam@json:float(S)}, - {<<"l"/utf8>>, gleam@json:float(L)}, - {<<"a"/utf8>>, gleam@json:float(A)}] - ). - --file("src/gleam_community/colour.gleam", 911). -?DOC( - " Encodes a `Colour` value as a Gleam [`Json`](https://hexdocs.pm/gleam_json/gleam/json.html#Json)\n" - " value. You'll need this if you want to send a `Colour` value over the network\n" - " in a HTTP request or response, for example.\n" - "\n" - " \n" -). --spec encode(colour()) -> gleam@json:json(). -encode(Colour) -> - case Colour of - {rgba, R, G, B, A} -> - encode_rgba(R, G, B, A); - - {hsla, H, S, L, A@1} -> - encode_hsla(H, S, L, A@1) - end. - --file("src/gleam_community/colour.gleam", 952). --spec rgba_decoder() -> gleam@dynamic@decode:decoder(colour()). -rgba_decoder() -> - gleam@dynamic@decode:field( - <<"r"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(R) -> - gleam@dynamic@decode:field( - <<"g"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(G) -> - gleam@dynamic@decode:field( - <<"b"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(B) -> - gleam@dynamic@decode:field( - <<"a"/utf8>>, - {decoder, - fun gleam@dynamic@decode:decode_float/1}, - fun(A) -> - gleam@dynamic@decode:success( - {rgba, R, G, B, A} - ) - end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 961). --spec hsla_decoder() -> gleam@dynamic@decode:decoder(colour()). -hsla_decoder() -> - gleam@dynamic@decode:field( - <<"h"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(H) -> - gleam@dynamic@decode:field( - <<"s"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(S) -> - gleam@dynamic@decode:field( - <<"l"/utf8>>, - {decoder, fun gleam@dynamic@decode:decode_float/1}, - fun(L) -> - gleam@dynamic@decode:field( - <<"a"/utf8>>, - {decoder, - fun gleam@dynamic@decode:decode_float/1}, - fun(A) -> - gleam@dynamic@decode:success( - {hsla, H, S, L, A} - ) - end - ) - end - ) - end - ) - end - ). - --file("src/gleam_community/colour.gleam", 948). -?DOC( - " Attempt to decode some [`Dynamic`](https://hexdocs.pm/gleam_stdlib/gleam/dynamic.html#Dynamic)\n" - " value into a `Colour`. Most often you'll use this to decode some JSON.\n" - "\n" - " \n" -). --spec decoder() -> gleam@dynamic@decode:decoder(colour()). -decoder() -> - gleam@dynamic@decode:one_of(rgba_decoder(), [hsla_decoder()]). diff --git a/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl b/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl deleted file mode 100644 index 35c1d67..0000000 --- a/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl +++ /dev/null @@ -1,203 +0,0 @@ --module(gleam_community@colour@accessibility). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/gleam_community/colour/accessibility.gleam"). --export([luminance/1, contrast_ratio/2, maximum_contrast/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " \n" - " - **Accessibility**\n" - " - [`luminance`](#luminance)\n" - " - [`contrast_ratio`](#contrast_ratio)\n" - " - [`maximum_contrast`](#maximum_contrast)\n" - "\n" - " ---\n" - "\n" - " This package was heavily inspired by the `elm-color-extra` module.\n" - " The original source code can be found\n" - " here.\n" - "\n" - "
\n" - " The license of that package is produced below:\n" - " \n" - " \n" - " > MIT License\n" - "\n" - " > Copyright (c) 2016 Andreas Köberle\n" - "\n" - " > Permission is hereby granted, free of charge, to any person obtaining a copy\n" - " of this software and associated documentation files (the \"Software\"), to deal\n" - " in the Software without restriction, including without limitation the rights\n" - " to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" - " copies of the Software, and to permit persons to whom the Software is\n" - " furnished to do so, subject to the following conditions:\n" - "\n" - " > The above copyright notice and this permission notice shall be included in all\n" - " copies or substantial portions of the Software.\n" - "\n" - " > THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" - " IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" - " FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" - " AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" - " LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" - " OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" - " SOFTWARE.\n" - "\n" - "
\n" - "\n" -). - --file("src/gleam_community/colour/accessibility.gleam", 56). --spec intensity(float()) -> float(). -intensity(Colour_value) -> - case true of - _ when Colour_value =< 0.03928 -> - Colour_value / 12.92; - - _ -> - I@1 = case gleam@float:power((Colour_value + 0.055) / 1.055, 2.4) of - {ok, I} -> I; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam_community/colour/accessibility"/utf8>>, - function => <<"intensity"/utf8>>, - line => 62, - value => _assert_fail, - start => 2399, - 'end' => 2470, - pattern_start => 2410, - pattern_end => 2415}) - end, - I@1 - end. - --file("src/gleam_community/colour/accessibility.gleam", 92). -?DOC( - " Returns the relative brightness of the given `Colour` as a `Float` between\n" - " 0.0, and 1.0 with 0.0 being the darkest possible colour and 1.0 being the lightest.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " luminance(colour.white) // 1.0\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec luminance(gleam_community@colour:colour()) -> float(). -luminance(Colour) -> - {R, G, B, _} = gleam_community@colour:to_rgba(Colour), - R_intensity = intensity(R), - G_intensity = intensity(G), - B_intensity = intensity(B), - ((0.2126 * R_intensity) + (0.7152 * G_intensity)) + (0.0722 * B_intensity). - --file("src/gleam_community/colour/accessibility.gleam", 125). -?DOC( - " Returns the contrast between two `Colour` values as a `Float` between 1.0,\n" - " and 21.0 with 1.0 being no contrast and, 21.0 being the highest possible contrast.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " contrast_ratio(between: colour.white, and: colour.black) // 21.0\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec contrast_ratio( - gleam_community@colour:colour(), - gleam_community@colour:colour() -) -> float(). -contrast_ratio(Colour_a, Colour_b) -> - Luminance_a = luminance(Colour_a) + 0.05, - Luminance_b = luminance(Colour_b) + 0.05, - case Luminance_a > Luminance_b of - true -> - case Luminance_b of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> Luminance_a / Gleam@denominator - end; - - false -> - case Luminance_a of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> Luminance_b / Gleam@denominator@1 - end - end. - --file("src/gleam_community/colour/accessibility.gleam", 161). -?DOC( - " Returns the `Colour` with the highest contrast between the base `Colour`,\n" - " and and the other provided `Colour` values.\n" - "\n" - "
\n" - " Example:\n" - "\n" - " ```gleam\n" - " fn example() {\n" - " maximum_contrast(\n" - " colour.yellow,\n" - " [colour.white, colour.dark_blue, colour.green],\n" - " )\n" - " }\n" - " ```\n" - "
\n" - "\n" - " \n" -). --spec maximum_contrast( - gleam_community@colour:colour(), - list(gleam_community@colour:colour()) -) -> {ok, gleam_community@colour:colour()} | {error, nil}. -maximum_contrast(Base, Colours) -> - _pipe = Colours, - _pipe@1 = gleam@list:sort( - _pipe, - fun(Colour_a, Colour_b) -> - Contrast_a = contrast_ratio(Base, Colour_a), - Contrast_b = contrast_ratio(Base, Colour_b), - gleam@float:compare(Contrast_b, Contrast_a) - end - ), - gleam@list:first(_pipe@1). diff --git a/build/packages/gleam_community_colour/src/gleam_community_colour.app.src b/build/packages/gleam_community_colour/src/gleam_community_colour.app.src deleted file mode 100644 index 0d22534..0000000 --- a/build/packages/gleam_community_colour/src/gleam_community_colour.app.src +++ /dev/null @@ -1,10 +0,0 @@ -{application, gleam_community_colour, [ - {vsn, "2.0.2"}, - {applications, [gleam_json, - gleam_stdlib]}, - {description, "Colour types, conversions, and other utilities"}, - {modules, [gleam_community@colour, - gleam_community@colour@accessibility, - gleam_community_colour@@main]}, - {registered, []} -]}. diff --git a/build/packages/gleam_json/LICENCE b/build/packages/gleam_json/LICENCE deleted file mode 100644 index 3d89615..0000000 --- a/build/packages/gleam_json/LICENCE +++ /dev/null @@ -1,191 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2021 - present, Louis Pilfold . - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/build/packages/gleam_json/README.md b/build/packages/gleam_json/README.md deleted file mode 100644 index 1a06b52..0000000 --- a/build/packages/gleam_json/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# json 🐑 - -Work with JSON in Gleam! - -## Installation - -```shell -gleam add gleam_json@3 -``` - -## Encoding - -```gleam -import myapp.{type Cat} -import gleam/json - -pub fn cat_to_json(cat: Cat) -> String { - json.object([ - #("name", json.string(cat.name)), - #("lives", json.int(cat.lives)), - #("flaws", json.null()), - #("nicknames", json.array(cat.nicknames, of: json.string)), - ]) - |> json.to_string -} -``` - -## Parsing - -JSON is parsed into a `Dynamic` value which can be decoded using the -`gleam/dynamic/decode` module from the Gleam standard library. - -```gleam -import myapp.{Cat} -import gleam/json -import gleam/dynamic/decode - -pub fn cat_from_json(json_string: String) -> Result(Cat, json.DecodeError) { - let cat_decoder = { - use name <- decode.field("name", decode.string) - use lives <- decode.field("lives", decode.int) - use nicknames <- decode.field("nicknames", decode.list(decode.string)) - decode.success(Cat(name:, lives:, nicknames:)) - } - json.parse(from: json_string, using: cat_decoder) -} -``` diff --git a/build/packages/gleam_json/gleam.toml b/build/packages/gleam_json/gleam.toml deleted file mode 100644 index f7e7f8d..0000000 --- a/build/packages/gleam_json/gleam.toml +++ /dev/null @@ -1,18 +0,0 @@ -name = "gleam_json" -version = "3.1.0" -gleam = ">= 1.13.0" - -licences = ["Apache-2.0"] -description = "Work with JSON in Gleam" - -repository = { type = "github", user = "gleam-lang", repo = "json" } -links = [ - { title = "Website", href = "https://gleam.run" }, - { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, -] - -[dependencies] -gleam_stdlib = ">= 0.51.0 and < 2.0.0" - -[dev-dependencies] -gleeunit = ">= 1.2.0 and < 2.0.0" diff --git a/build/packages/gleam_json/src/gleam/json.gleam b/build/packages/gleam_json/src/gleam/json.gleam deleted file mode 100644 index e3a3cae..0000000 --- a/build/packages/gleam_json/src/gleam/json.gleam +++ /dev/null @@ -1,316 +0,0 @@ -import gleam/bit_array -import gleam/dict.{type Dict} -import gleam/dynamic.{type Dynamic} -import gleam/dynamic/decode -import gleam/list -import gleam/option.{type Option, None, Some} -import gleam/result -import gleam/string_tree.{type StringTree} - -pub type Json - -pub type DecodeError { - UnexpectedEndOfInput - UnexpectedByte(String) - UnexpectedSequence(String) - UnableToDecode(List(decode.DecodeError)) -} - -/// Decode a JSON string into dynamically typed data which can be decoded into -/// typed data with the `gleam/dynamic` module. -/// -/// ## Examples -/// -/// ```gleam -/// > parse("[1,2,3]", decode.list(of: decode.int)) -/// Ok([1, 2, 3]) -/// ``` -/// -/// ```gleam -/// > parse("[", decode.list(of: decode.int)) -/// Error(UnexpectedEndOfInput) -/// ``` -/// -/// ```gleam -/// > parse("1", decode.string) -/// Error(UnableToDecode([decode.DecodeError("String", "Int", [])])) -/// ``` -/// -pub fn parse( - from json: String, - using decoder: decode.Decoder(t), -) -> Result(t, DecodeError) { - do_parse(from: json, using: decoder) -} - -@target(erlang) -fn do_parse( - from json: String, - using decoder: decode.Decoder(t), -) -> Result(t, DecodeError) { - let bits = bit_array.from_string(json) - parse_bits(bits, decoder) -} - -@target(javascript) -fn do_parse( - from json: String, - using decoder: decode.Decoder(t), -) -> Result(t, DecodeError) { - use dynamic_value <- result.try(decode_string(json)) - decode.run(dynamic_value, decoder) - |> result.map_error(UnableToDecode) -} - -@external(javascript, "../gleam_json_ffi.mjs", "decode") -fn decode_string(a: String) -> Result(Dynamic, DecodeError) - -/// Decode a JSON bit string into dynamically typed data which can be decoded -/// into typed data with the `gleam/dynamic` module. -/// -/// ## Examples -/// -/// ```gleam -/// > parse_bits(<<"[1,2,3]">>, decode.list(of: decode.int)) -/// Ok([1, 2, 3]) -/// ``` -/// -/// ```gleam -/// > parse_bits(<<"[">>, decode.list(of: decode.int)) -/// Error(UnexpectedEndOfInput) -/// ``` -/// -/// ```gleam -/// > parse_bits(<<"1">>, decode.string) -/// Error(UnableToDecode([decode.DecodeError("String", "Int", [])])), -/// ``` -/// -pub fn parse_bits( - from json: BitArray, - using decoder: decode.Decoder(t), -) -> Result(t, DecodeError) { - use dynamic_value <- result.try(decode_to_dynamic(json)) - decode.run(dynamic_value, decoder) - |> result.map_error(UnableToDecode) -} - -@external(erlang, "gleam_json_ffi", "decode") -fn decode_to_dynamic(json: BitArray) -> Result(Dynamic, DecodeError) { - case bit_array.to_string(json) { - Ok(string) -> decode_string(string) - Error(Nil) -> Error(UnexpectedByte("")) - } -} - -/// Convert a JSON value into a string. -/// -/// Where possible prefer the `to_string_tree` function as it is faster than -/// this function, and BEAM VM IO is optimised for sending `StringTree` data. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(array([1, 2, 3], of: int)) -/// "[1,2,3]" -/// ``` -/// -pub fn to_string(json: Json) -> String { - do_to_string(json) -} - -@external(erlang, "gleam_json_ffi", "json_to_string") -@external(javascript, "../gleam_json_ffi.mjs", "json_to_string") -fn do_to_string(a: Json) -> String - -/// Convert a JSON value into a string tree. -/// -/// Where possible prefer this function to the `to_string` function as it is -/// slower than this function, and BEAM VM IO is optimised for sending -/// `StringTree` data. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string_tree(array([1, 2, 3], of: int)) -/// string_tree.from_string("[1,2,3]") -/// ``` -/// -@external(erlang, "gleam_json_ffi", "json_to_iodata") -@external(javascript, "../gleam_json_ffi.mjs", "json_to_string") -pub fn to_string_tree(json: Json) -> StringTree - -/// Encode a string into JSON, using normal JSON escaping. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(string("Hello!")) -/// "\"Hello!\"" -/// ``` -/// -pub fn string(input: String) -> Json { - do_string(input) -} - -@external(erlang, "gleam_json_ffi", "string") -@external(javascript, "../gleam_json_ffi.mjs", "identity") -fn do_string(a: String) -> Json - -/// Encode a bool into JSON. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(bool(False)) -/// "false" -/// ``` -/// -pub fn bool(input: Bool) -> Json { - do_bool(input) -} - -@external(erlang, "gleam_json_ffi", "bool") -@external(javascript, "../gleam_json_ffi.mjs", "identity") -fn do_bool(a: Bool) -> Json - -/// Encode an int into JSON. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(int(50)) -/// "50" -/// ``` -/// -pub fn int(input: Int) -> Json { - do_int(input) -} - -@external(erlang, "gleam_json_ffi", "int") -@external(javascript, "../gleam_json_ffi.mjs", "identity") -fn do_int(a: Int) -> Json - -/// Encode a float into JSON. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(float(4.7)) -/// "4.7" -/// ``` -/// -pub fn float(input: Float) -> Json { - do_float(input) -} - -@external(erlang, "gleam_json_ffi", "float") -@external(javascript, "../gleam_json_ffi.mjs", "identity") -fn do_float(input input: Float) -> Json - -/// The JSON value null. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(null()) -/// "null" -/// ``` -/// -pub fn null() -> Json { - do_null() -} - -@external(erlang, "gleam_json_ffi", "null") -@external(javascript, "../gleam_json_ffi.mjs", "do_null") -fn do_null() -> Json - -/// Encode an optional value into JSON, using null if it is the `None` variant. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(nullable(Some(50), of: int)) -/// "50" -/// ``` -/// -/// ```gleam -/// > to_string(nullable(None, of: int)) -/// "null" -/// ``` -/// -pub fn nullable(from input: Option(a), of inner_type: fn(a) -> Json) -> Json { - case input { - Some(value) -> inner_type(value) - None -> null() - } -} - -/// Encode a list of key-value pairs into a JSON object. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(object([ -/// #("game", string("Pac-Man")), -/// #("score", int(3333360)), -/// ])) -/// "{\"game\":\"Pac-Mac\",\"score\":3333360}" -/// ``` -/// -pub fn object(entries: List(#(String, Json))) -> Json { - do_object(entries) -} - -@external(erlang, "gleam_json_ffi", "object") -@external(javascript, "../gleam_json_ffi.mjs", "object") -fn do_object(entries entries: List(#(String, Json))) -> Json - -/// Encode a list into a JSON array. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(array([1, 2, 3], of: int)) -/// "[1, 2, 3]" -/// ``` -/// -pub fn array(from entries: List(a), of inner_type: fn(a) -> Json) -> Json { - entries - |> list.map(inner_type) - |> preprocessed_array -} - -/// Encode a list of JSON values into a JSON array. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(preprocessed_array([int(1), float(2.0), string("3")])) -/// "[1, 2.0, \"3\"]" -/// ``` -/// -pub fn preprocessed_array(from: List(Json)) -> Json { - do_preprocessed_array(from) -} - -@external(erlang, "gleam_json_ffi", "array") -@external(javascript, "../gleam_json_ffi.mjs", "array") -fn do_preprocessed_array(from from: List(Json)) -> Json - -/// Encode a Dict into a JSON object using the supplied functions to encode -/// the keys and the values respectively. -/// -/// ## Examples -/// -/// ```gleam -/// > to_string(dict(dict.from_list([ #(3, 3.0), #(4, 4.0)]), int.to_string, float) -/// "{\"3\": 3.0, \"4\": 4.0}" -/// ``` -/// -pub fn dict( - dict: Dict(k, v), - keys: fn(k) -> String, - values: fn(v) -> Json, -) -> Json { - object(dict.fold(dict, [], fn(acc, k, v) { [#(keys(k), values(v)), ..acc] })) -} diff --git a/build/packages/gleam_json/src/gleam@json.erl b/build/packages/gleam_json/src/gleam@json.erl deleted file mode 100644 index 8a33e49..0000000 --- a/build/packages/gleam_json/src/gleam@json.erl +++ /dev/null @@ -1,304 +0,0 @@ --module(gleam@json). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/json.gleam"). --export([parse_bits/2, parse/2, to_string/1, to_string_tree/1, string/1, bool/1, int/1, float/1, null/0, nullable/2, object/1, preprocessed_array/1, array/2, dict/3]). --export_type([json/0, decode_error/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type json() :: any(). - --type decode_error() :: unexpected_end_of_input | - {unexpected_byte, binary()} | - {unexpected_sequence, binary()} | - {unable_to_decode, list(gleam@dynamic@decode:decode_error())}. - --file("src/gleam/json.gleam", 88). -?DOC( - " Decode a JSON bit string into dynamically typed data which can be decoded\n" - " into typed data with the `gleam/dynamic` module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"[1,2,3]\">>, decode.list(of: decode.int))\n" - " Ok([1, 2, 3])\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"[\">>, decode.list(of: decode.int))\n" - " Error(UnexpectedEndOfInput)\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"1\">>, decode.string)\n" - " Error(UnableToDecode([decode.DecodeError(\"String\", \"Int\", [])])),\n" - " ```\n" -). --spec parse_bits(bitstring(), gleam@dynamic@decode:decoder(DNO)) -> {ok, DNO} | - {error, decode_error()}. -parse_bits(Json, Decoder) -> - gleam@result:'try'( - gleam_json_ffi:decode(Json), - fun(Dynamic_value) -> - _pipe = gleam@dynamic@decode:run(Dynamic_value, Decoder), - gleam@result:map_error( - _pipe, - fun(Field@0) -> {unable_to_decode, Field@0} end - ) - end - ). - --file("src/gleam/json.gleam", 47). --spec do_parse(binary(), gleam@dynamic@decode:decoder(DNI)) -> {ok, DNI} | - {error, decode_error()}. -do_parse(Json, Decoder) -> - Bits = gleam_stdlib:identity(Json), - parse_bits(Bits, Decoder). - --file("src/gleam/json.gleam", 39). -?DOC( - " Decode a JSON string into dynamically typed data which can be decoded into\n" - " typed data with the `gleam/dynamic` module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > parse(\"[1,2,3]\", decode.list(of: decode.int))\n" - " Ok([1, 2, 3])\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse(\"[\", decode.list(of: decode.int))\n" - " Error(UnexpectedEndOfInput)\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse(\"1\", decode.string)\n" - " Error(UnableToDecode([decode.DecodeError(\"String\", \"Int\", [])]))\n" - " ```\n" -). --spec parse(binary(), gleam@dynamic@decode:decoder(DNE)) -> {ok, DNE} | - {error, decode_error()}. -parse(Json, Decoder) -> - do_parse(Json, Decoder). - --file("src/gleam/json.gleam", 117). -?DOC( - " Convert a JSON value into a string.\n" - "\n" - " Where possible prefer the `to_string_tree` function as it is faster than\n" - " this function, and BEAM VM IO is optimised for sending `StringTree` data.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(array([1, 2, 3], of: int))\n" - " \"[1,2,3]\"\n" - " ```\n" -). --spec to_string(json()) -> binary(). -to_string(Json) -> - gleam_json_ffi:json_to_string(Json). - --file("src/gleam/json.gleam", 140). -?DOC( - " Convert a JSON value into a string tree.\n" - "\n" - " Where possible prefer this function to the `to_string` function as it is\n" - " slower than this function, and BEAM VM IO is optimised for sending\n" - " `StringTree` data.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string_tree(array([1, 2, 3], of: int))\n" - " string_tree.from_string(\"[1,2,3]\")\n" - " ```\n" -). --spec to_string_tree(json()) -> gleam@string_tree:string_tree(). -to_string_tree(Json) -> - gleam_json_ffi:json_to_iodata(Json). - --file("src/gleam/json.gleam", 151). -?DOC( - " Encode a string into JSON, using normal JSON escaping.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(string(\"Hello!\"))\n" - " \"\\\"Hello!\\\"\"\n" - " ```\n" -). --spec string(binary()) -> json(). -string(Input) -> - gleam_json_ffi:string(Input). - --file("src/gleam/json.gleam", 168). -?DOC( - " Encode a bool into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(bool(False))\n" - " \"false\"\n" - " ```\n" -). --spec bool(boolean()) -> json(). -bool(Input) -> - gleam_json_ffi:bool(Input). - --file("src/gleam/json.gleam", 185). -?DOC( - " Encode an int into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(int(50))\n" - " \"50\"\n" - " ```\n" -). --spec int(integer()) -> json(). -int(Input) -> - gleam_json_ffi:int(Input). - --file("src/gleam/json.gleam", 202). -?DOC( - " Encode a float into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(float(4.7))\n" - " \"4.7\"\n" - " ```\n" -). --spec float(float()) -> json(). -float(Input) -> - gleam_json_ffi:float(Input). - --file("src/gleam/json.gleam", 219). -?DOC( - " The JSON value null.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(null())\n" - " \"null\"\n" - " ```\n" -). --spec null() -> json(). -null() -> - gleam_json_ffi:null(). - --file("src/gleam/json.gleam", 241). -?DOC( - " Encode an optional value into JSON, using null if it is the `None` variant.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(nullable(Some(50), of: int))\n" - " \"50\"\n" - " ```\n" - "\n" - " ```gleam\n" - " > to_string(nullable(None, of: int))\n" - " \"null\"\n" - " ```\n" -). --spec nullable(gleam@option:option(DNU), fun((DNU) -> json())) -> json(). -nullable(Input, Inner_type) -> - case Input of - {some, Value} -> - Inner_type(Value); - - none -> - null() - end. - --file("src/gleam/json.gleam", 260). -?DOC( - " Encode a list of key-value pairs into a JSON object.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(object([\n" - " #(\"game\", string(\"Pac-Man\")),\n" - " #(\"score\", int(3333360)),\n" - " ]))\n" - " \"{\\\"game\\\":\\\"Pac-Mac\\\",\\\"score\\\":3333360}\"\n" - " ```\n" -). --spec object(list({binary(), json()})) -> json(). -object(Entries) -> - gleam_json_ffi:object(Entries). - --file("src/gleam/json.gleam", 292). -?DOC( - " Encode a list of JSON values into a JSON array.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(preprocessed_array([int(1), float(2.0), string(\"3\")]))\n" - " \"[1, 2.0, \\\"3\\\"]\"\n" - " ```\n" -). --spec preprocessed_array(list(json())) -> json(). -preprocessed_array(From) -> - gleam_json_ffi:array(From). - --file("src/gleam/json.gleam", 277). -?DOC( - " Encode a list into a JSON array.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(array([1, 2, 3], of: int))\n" - " \"[1, 2, 3]\"\n" - " ```\n" -). --spec array(list(DNY), fun((DNY) -> json())) -> json(). -array(Entries, Inner_type) -> - _pipe = Entries, - _pipe@1 = gleam@list:map(_pipe, Inner_type), - preprocessed_array(_pipe@1). - --file("src/gleam/json.gleam", 310). -?DOC( - " Encode a Dict into a JSON object using the supplied functions to encode\n" - " the keys and the values respectively.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(dict(dict.from_list([ #(3, 3.0), #(4, 4.0)]), int.to_string, float)\n" - " \"{\\\"3\\\": 3.0, \\\"4\\\": 4.0}\"\n" - " ```\n" -). --spec dict( - gleam@dict:dict(DOC, DOD), - fun((DOC) -> binary()), - fun((DOD) -> json()) -) -> json(). -dict(Dict, Keys, Values) -> - object( - gleam@dict:fold( - Dict, - [], - fun(Acc, K, V) -> [{Keys(K), Values(V)} | Acc] end - ) - ). diff --git a/build/packages/gleam_json/src/gleam_json.app.src b/build/packages/gleam_json/src/gleam_json.app.src deleted file mode 100644 index 3bad27e..0000000 --- a/build/packages/gleam_json/src/gleam_json.app.src +++ /dev/null @@ -1,9 +0,0 @@ -{application, gleam_json, [ - {vsn, "3.1.0"}, - {applications, [gleam_stdlib]}, - {description, "Work with JSON in Gleam"}, - {modules, [gleam@json, - gleam_json@@main, - gleam_json_ffi]}, - {registered, []} -]}. diff --git a/build/packages/gleam_json/src/gleam_json_ffi.erl b/build/packages/gleam_json/src/gleam_json_ffi.erl deleted file mode 100644 index 06a26a0..0000000 --- a/build/packages/gleam_json/src/gleam_json_ffi.erl +++ /dev/null @@ -1,66 +0,0 @@ --module(gleam_json_ffi). - --export([ - decode/1, json_to_iodata/1, json_to_string/1, int/1, float/1, string/1, - bool/1, null/0, array/1, object/1 -]). - --if(?OTP_RELEASE < 27). --define(bad_version, - error({erlang_otp_27_required, << "Insufficient Erlang/OTP version. - -`gleam_json` uses the Erlang `json` module introduced in Erlang/OTP 27. -You are using Erlang/OTP "/utf8, (integer_to_binary(?OTP_RELEASE))/binary, " -Please upgrade your Erlang install or downgrade to `gleam_json` v1.0.1. -"/utf8>>})). - -decode(_) -> ?bad_version. -json_to_iodata(_) -> ?bad_version. -json_to_string(_) -> ?bad_version. -int(_) -> ?bad_version. -float(_) -> ?bad_version. -string(_) -> ?bad_version. -bool(_) -> ?bad_version. -array(_) -> ?bad_version. -object(_) -> ?bad_version. -null() -> ?bad_version. --else. - -decode(Json) -> - try - {ok, json:decode(Json)} - catch - error:unexpected_end -> {error, unexpected_end_of_input}; - error:{invalid_byte, Byte} -> {error, {unexpected_byte, hex(Byte)}}; - error:{unexpected_sequence, Byte} -> {error, {unexpected_sequence, Byte}} - end. - -hex(I) -> - H = list_to_binary(integer_to_list(I, 16)), - <<"0x"/utf8, H/binary>>. - -json_to_iodata(Json) -> - Json. - -json_to_string(Json) when is_binary(Json) -> - Json; -json_to_string(Json) when is_list(Json) -> - list_to_binary(Json). - -null() -> <<"null">>. -bool(true) -> <<"true">>; -bool(false) -> <<"false">>. -int(X) -> json:encode_integer(X). -float(X) -> json:encode_float(X). -string(X) -> json:encode_binary(X). - -array([]) -> <<"[]">>; -array([First | Rest]) -> [$[, First | array_loop(Rest)]. -array_loop([]) -> "]"; -array_loop([Elem | Rest]) -> [$,, Elem | array_loop(Rest)]. - -object(List) -> encode_object([[$,, string(Key), $: | Value] || {Key, Value} <- List]). -encode_object([]) -> <<"{}">>; -encode_object([[_Comma | Entry] | Rest]) -> ["{", Entry, Rest, "}"]. - --endif. diff --git a/build/packages/gleam_json/src/gleam_json_ffi.mjs b/build/packages/gleam_json/src/gleam_json_ffi.mjs deleted file mode 100644 index 1d8d3ff..0000000 --- a/build/packages/gleam_json/src/gleam_json_ffi.mjs +++ /dev/null @@ -1,201 +0,0 @@ -import { - Result$Ok, - Result$Error, - List$isNonEmpty, - List$NonEmpty$first, - List$NonEmpty$rest, -} from "./gleam.mjs"; -import { - DecodeError$UnexpectedByte, - DecodeError$UnexpectedEndOfInput, -} from "./gleam/json.mjs"; - -export function json_to_string(json) { - return JSON.stringify(json); -} - -export function object(entries) { - return Object.fromEntries(entries); -} - -export function identity(x) { - return x; -} - -export function array(list) { - const array = []; - while (List$isNonEmpty(list)) { - array.push(List$NonEmpty$first(list)); - list = List$NonEmpty$rest(list); - } - return array; -} - -export function do_null() { - return null; -} - -export function decode(string) { - try { - const result = JSON.parse(string); - return Result$Ok(result); - } catch (err) { - return Result$Error(getJsonDecodeError(err, string)); - } -} - -export function getJsonDecodeError(stdErr, json) { - if (isUnexpectedEndOfInput(stdErr)) return DecodeError$UnexpectedEndOfInput(); - return toUnexpectedByteError(stdErr, json); -} - -/** - * Matches unexpected end of input messages in: - * - Chromium (edge, chrome, node) - * - Spidermonkey (firefox) - * - JavascriptCore (safari) - * - * Note that Spidermonkey and JavascriptCore will both incorrectly report some - * UnexpectedByte errors as UnexpectedEndOfInput errors. For example: - * - * @example - * // in JavascriptCore - * JSON.parse('{"a"]: "b"}) - * // => JSON Parse error: Expected ':' before value - * - * JSON.parse('{"a"') - * // => JSON Parse error: Expected ':' before value - * - * // in Chromium (correct) - * JSON.parse('{"a"]: "b"}) - * // => Unexpected token ] in JSON at position 4 - * - * JSON.parse('{"a"') - * // => Unexpected end of JSON input - */ -function isUnexpectedEndOfInput(err) { - const unexpectedEndOfInputRegex = - /((unexpected (end|eof))|(end of data)|(unterminated string)|(json( parse error|\.parse)\: expected '(\:|\}|\])'))/i; - return unexpectedEndOfInputRegex.test(err.message); -} - -/** - * Converts a SyntaxError to an UnexpectedByte error based on the JS runtime. - * - * For Chromium, the unexpected byte and position are reported by the runtime. - * - * For JavascriptCore, only the unexpected byte is reported by the runtime, so - * there is no way to know which position that character is in unless we then - * parse the string again ourselves. So instead, the position is reported as 0. - * - * For Spidermonkey, the position is reported by the runtime as a line and column number - * and the unexpected byte is found using those coordinates. - */ -function toUnexpectedByteError(err, json) { - let converters = [ - v8UnexpectedByteError, - oldV8UnexpectedByteError, - jsCoreUnexpectedByteError, - spidermonkeyUnexpectedByteError, - ]; - - for (let converter of converters) { - let result = converter(err, json); - if (result) return result; - } - - return DecodeError$UnexpectedByte(""); -} - -/** - * Matches unexpected byte messages in: - * - V8 (edge, chrome, node) - * - * Matches the character but not the position as this is no longer reported by - * V8. Boo! - */ -function v8UnexpectedByteError(err) { - const regex = /unexpected token '(.)', ".+" is not valid JSON/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[1]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - V8 (edge, chrome, node) - * - * No longer works in current versions of V8. - * - * Matches the character and its position. - */ -function oldV8UnexpectedByteError(err) { - const regex = /unexpected token (.) in JSON at position (\d+)/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[1]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - Spidermonkey (firefox) - * - * Matches the position in a 2d grid only and not the character. - */ -function spidermonkeyUnexpectedByteError(err, json) { - const regex = - /(unexpected character|expected .*) at line (\d+) column (\d+)/i; - const match = regex.exec(err.message); - if (!match) return null; - const line = Number(match[2]); - const column = Number(match[3]); - const position = getPositionFromMultiline(line, column, json); - const byte = toHex(json[position]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - JavascriptCore (safari) - * - * JavascriptCore only reports what the character is and not its position. - */ -function jsCoreUnexpectedByteError(err) { - const regex = /unexpected (identifier|token) "(.)"/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[2]); - return DecodeError$UnexpectedByte(byte); -} - -function toHex(char) { - return "0x" + char.charCodeAt(0).toString(16).toUpperCase(); -} - -/** - * Gets the position of a character in a flattened (i.e. single line) string - * from a line and column number. Note that the position is 0-indexed and - * the line and column numbers are 1-indexed. - * - * @param {number} line - * @param {number} column - * @param {string} string - */ -function getPositionFromMultiline(line, column, string) { - if (line === 1) return column - 1; - - let currentLn = 1; - let position = 0; - string.split("").find((char, idx) => { - if (char === "\n") currentLn += 1; - if (currentLn === line) { - position = idx + column; - return true; - } - return false; - }); - - return position; -} diff --git a/build/packages/gleam_stdlib/LICENCE b/build/packages/gleam_stdlib/LICENCE deleted file mode 100644 index c1dabd0..0000000 --- a/build/packages/gleam_stdlib/LICENCE +++ /dev/null @@ -1,191 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2018, Louis Pilfold . - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/build/packages/gleam_stdlib/README.md b/build/packages/gleam_stdlib/README.md deleted file mode 100644 index 5e1ed4c..0000000 --- a/build/packages/gleam_stdlib/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# stdlib - -[![Package Version](https://img.shields.io/hexpm/v/gleam_stdlib)](https://hex.pm/packages/gleam_stdlib) -[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/gleam_stdlib/) -[![Discord chat](https://img.shields.io/discord/768594524158427167?color=blue)](https://discord.gg/Fm8Pwmy) - -Gleam's standard library! -Documentation available on [HexDocs](https://hexdocs.pm/gleam_stdlib/). - -## Installation - -Add `gleam_stdlib` to your Gleam project. - -```sh -gleam add gleam_stdlib -``` -```gleam -import gleam/io - -pub fn greet(name: String) -> Nil { - io.println("Hello " <> name <> "!") -} -``` - -## Targets - -Gleam's standard library supports both targets: Erlang and JavaScript. - -### Compatibility - -This library is compatible with all versions of Erlang/OTP 26 and higher, -as well as all NodeJS, Deno, Bun, and major browsers that are currently -supported by their maintainers. If you have a compatibility issue with -any platform open an issue and we'll see what we can do to help. diff --git a/build/packages/gleam_stdlib/gleam.toml b/build/packages/gleam_stdlib/gleam.toml deleted file mode 100644 index 27c3f0e..0000000 --- a/build/packages/gleam_stdlib/gleam.toml +++ /dev/null @@ -1,14 +0,0 @@ -name = "gleam_stdlib" -version = "0.65.0" -gleam = ">= 1.11.0" -licences = ["Apache-2.0"] -description = "A standard library for the Gleam programming language" - -repository = { type = "github", user = "gleam-lang", repo = "stdlib" } -links = [ - { title = "Website", href = "https://gleam.run" }, - { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, -] - -[javascript.deno] -allow_read = ["./"] diff --git a/build/packages/gleam_stdlib/include/gleam@dynamic@decode_DecodeError.hrl b/build/packages/gleam_stdlib/include/gleam@dynamic@decode_DecodeError.hrl deleted file mode 100644 index b1135f2..0000000 --- a/build/packages/gleam_stdlib/include/gleam@dynamic@decode_DecodeError.hrl +++ /dev/null @@ -1,5 +0,0 @@ --record(decode_error, { - expected :: binary(), - found :: binary(), - path :: list(binary()) -}). diff --git a/build/packages/gleam_stdlib/include/gleam@dynamic@decode_Decoder.hrl b/build/packages/gleam_stdlib/include/gleam@dynamic@decode_Decoder.hrl deleted file mode 100644 index a2fcfc6..0000000 --- a/build/packages/gleam_stdlib/include/gleam@dynamic@decode_Decoder.hrl +++ /dev/null @@ -1,4 +0,0 @@ --record(decoder, { - function :: fun((gleam@dynamic:dynamic_()) -> {any(), - list(gleam@dynamic@decode:decode_error())}) -}). diff --git a/build/packages/gleam_stdlib/include/gleam@set_Set.hrl b/build/packages/gleam_stdlib/include/gleam@set_Set.hrl deleted file mode 100644 index 51fb778..0000000 --- a/build/packages/gleam_stdlib/include/gleam@set_Set.hrl +++ /dev/null @@ -1 +0,0 @@ --record(set, {dict :: gleam@dict:dict(any(), list(nil))}). diff --git a/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl b/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl deleted file mode 100644 index 50150f4..0000000 --- a/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl +++ /dev/null @@ -1,9 +0,0 @@ --record(uri, { - scheme :: gleam@option:option(binary()), - userinfo :: gleam@option:option(binary()), - host :: gleam@option:option(binary()), - port :: gleam@option:option(integer()), - path :: binary(), - 'query' :: gleam@option:option(binary()), - fragment :: gleam@option:option(binary()) -}). diff --git a/build/packages/gleam_stdlib/src/dict.mjs b/build/packages/gleam_stdlib/src/dict.mjs deleted file mode 100644 index f39cd54..0000000 --- a/build/packages/gleam_stdlib/src/dict.mjs +++ /dev/null @@ -1,993 +0,0 @@ -/** - * This file uses jsdoc to annotate types. - * These types can be checked using the typescript compiler with "checkjs" option. - */ - -import { isEqual } from "./gleam.mjs"; - -const referenceMap = /* @__PURE__ */ new WeakMap(); -const tempDataView = /* @__PURE__ */ new DataView( - /* @__PURE__ */ new ArrayBuffer(8), -); -let referenceUID = 0; -/** - * hash the object by reference using a weak map and incrementing uid - * @param {any} o - * @returns {number} - */ -function hashByReference(o) { - const known = referenceMap.get(o); - if (known !== undefined) { - return known; - } - const hash = referenceUID++; - if (referenceUID === 0x7fffffff) { - referenceUID = 0; - } - referenceMap.set(o, hash); - return hash; -} - -/** - * merge two hashes in an order sensitive way - * @param {number} a - * @param {number} b - * @returns {number} - */ -function hashMerge(a, b) { - return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; -} - -/** - * standard string hash popularised by java - * @param {string} s - * @returns {number} - */ -function hashString(s) { - let hash = 0; - const len = s.length; - for (let i = 0; i < len; i++) { - hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0; - } - return hash; -} - -/** - * hash a number by converting to two integers and do some jumbling - * @param {number} n - * @returns {number} - */ -function hashNumber(n) { - tempDataView.setFloat64(0, n); - const i = tempDataView.getInt32(0); - const j = tempDataView.getInt32(4); - return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j; -} - -/** - * hash a BigInt by converting it to a string and hashing that - * @param {BigInt} n - * @returns {number} - */ -function hashBigInt(n) { - return hashString(n.toString()); -} - -/** - * hash any js object - * @param {any} o - * @returns {number} - */ -function hashObject(o) { - const proto = Object.getPrototypeOf(o); - if (proto !== null && typeof proto.hashCode === "function") { - try { - const code = o.hashCode(o); - if (typeof code === "number") { - return code; - } - } catch {} - } - if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { - return hashByReference(o); - } - if (o instanceof Date) { - return hashNumber(o.getTime()); - } - let h = 0; - if (o instanceof ArrayBuffer) { - o = new Uint8Array(o); - } - if (Array.isArray(o) || o instanceof Uint8Array) { - for (let i = 0; i < o.length; i++) { - h = (Math.imul(31, h) + getHash(o[i])) | 0; - } - } else if (o instanceof Set) { - o.forEach((v) => { - h = (h + getHash(v)) | 0; - }); - } else if (o instanceof Map) { - o.forEach((v, k) => { - h = (h + hashMerge(getHash(v), getHash(k))) | 0; - }); - } else { - const keys = Object.keys(o); - for (let i = 0; i < keys.length; i++) { - const k = keys[i]; - const v = o[k]; - h = (h + hashMerge(getHash(v), hashString(k))) | 0; - } - } - return h; -} - -/** - * hash any js value - * @param {any} u - * @returns {number} - */ -export function getHash(u) { - if (u === null) return 0x42108422; - if (u === undefined) return 0x42108423; - if (u === true) return 0x42108421; - if (u === false) return 0x42108420; - switch (typeof u) { - case "number": - return hashNumber(u); - case "string": - return hashString(u); - case "bigint": - return hashBigInt(u); - case "object": - return hashObject(u); - case "symbol": - return hashByReference(u); - case "function": - return hashByReference(u); - default: - return 0; // should be unreachable - } -} - -/** - * @template K,V - * @typedef {ArrayNode | IndexNode | CollisionNode} Node - */ -/** - * @template K,V - * @typedef {{ type: typeof ENTRY, k: K, v: V }} Entry - */ -/** - * @template K,V - * @typedef {{ type: typeof ARRAY_NODE, size: number, array: (undefined | Entry | Node)[] }} ArrayNode - */ -/** - * @template K,V - * @typedef {{ type: typeof INDEX_NODE, bitmap: number, array: (Entry | Node)[] }} IndexNode - */ -/** - * @template K,V - * @typedef {{ type: typeof COLLISION_NODE, hash: number, array: Entry[] }} CollisionNode - */ -/** - * @typedef {{ val: boolean }} Flag - */ -const SHIFT = 5; // number of bits you need to shift by to get the next bucket -const BUCKET_SIZE = Math.pow(2, SHIFT); -const MASK = BUCKET_SIZE - 1; // used to zero out all bits not in the bucket -const MAX_INDEX_NODE = BUCKET_SIZE / 2; // when does index node grow into array node -const MIN_ARRAY_NODE = BUCKET_SIZE / 4; // when does array node shrink to index node -const ENTRY = 0; -const ARRAY_NODE = 1; -const INDEX_NODE = 2; -const COLLISION_NODE = 3; - -/** @type {IndexNode} */ -const EMPTY = { - type: INDEX_NODE, - bitmap: 0, - array: [], -}; -/** - * Mask the hash to get only the bucket corresponding to shift - * @param {number} hash - * @param {number} shift - * @returns {number} - */ -function mask(hash, shift) { - return (hash >>> shift) & MASK; -} - -/** - * Set only the Nth bit where N is the masked hash - * @param {number} hash - * @param {number} shift - * @returns {number} - */ -function bitpos(hash, shift) { - return 1 << mask(hash, shift); -} - -/** - * Count the number of 1 bits in a number - * @param {number} x - * @returns {number} - */ -function bitcount(x) { - x -= (x >> 1) & 0x55555555; - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0f0f0f0f; - x += x >> 8; - x += x >> 16; - return x & 0x7f; -} - -/** - * Calculate the array index of an item in a bitmap index node - * @param {number} bitmap - * @param {number} bit - * @returns {number} - */ -function index(bitmap, bit) { - return bitcount(bitmap & (bit - 1)); -} - -/** - * Efficiently copy an array and set one value at an index - * @template T - * @param {T[]} arr - * @param {number} at - * @param {T} val - * @returns {T[]} - */ -function cloneAndSet(arr, at, val) { - const len = arr.length; - const out = new Array(len); - for (let i = 0; i < len; ++i) { - out[i] = arr[i]; - } - out[at] = val; - return out; -} - -/** - * Efficiently copy an array and insert one value at an index - * @template T - * @param {T[]} arr - * @param {number} at - * @param {T} val - * @returns {T[]} - */ -function spliceIn(arr, at, val) { - const len = arr.length; - const out = new Array(len + 1); - let i = 0; - let g = 0; - while (i < at) { - out[g++] = arr[i++]; - } - out[g++] = val; - while (i < len) { - out[g++] = arr[i++]; - } - return out; -} - -/** - * Efficiently copy an array and remove one value at an index - * @template T - * @param {T[]} arr - * @param {number} at - * @returns {T[]} - */ -function spliceOut(arr, at) { - const len = arr.length; - const out = new Array(len - 1); - let i = 0; - let g = 0; - while (i < at) { - out[g++] = arr[i++]; - } - ++i; - while (i < len) { - out[g++] = arr[i++]; - } - return out; -} - -/** - * Create a new node containing two entries - * @template K,V - * @param {number} shift - * @param {K} key1 - * @param {V} val1 - * @param {number} key2hash - * @param {K} key2 - * @param {V} val2 - * @returns {Node} - */ -function createNode(shift, key1, val1, key2hash, key2, val2) { - const key1hash = getHash(key1); - if (key1hash === key2hash) { - return { - type: COLLISION_NODE, - hash: key1hash, - array: [ - { type: ENTRY, k: key1, v: val1 }, - { type: ENTRY, k: key2, v: val2 }, - ], - }; - } - const addedLeaf = { val: false }; - return assoc( - assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf), - shift, - key2hash, - key2, - val2, - addedLeaf, - ); -} - -/** - * @template T,K,V - * @callback AssocFunction - * @param {T} root - * @param {number} shift - * @param {number} hash - * @param {K} key - * @param {V} val - * @param {Flag} addedLeaf - * @returns {Node} - */ -/** - * Associate a node with a new entry, creating a new node - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assoc(root, shift, hash, key, val, addedLeaf) { - switch (root.type) { - case ARRAY_NODE: - return assocArray(root, shift, hash, key, val, addedLeaf); - case INDEX_NODE: - return assocIndex(root, shift, hash, key, val, addedLeaf); - case COLLISION_NODE: - return assocCollision(root, shift, hash, key, val, addedLeaf); - } -} -/** - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assocArray(root, shift, hash, key, val, addedLeaf) { - const idx = mask(hash, shift); - const node = root.array[idx]; - // if the corresponding index is empty set the index to a newly created node - if (node === undefined) { - addedLeaf.val = true; - return { - type: ARRAY_NODE, - size: root.size + 1, - array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), - }; - } - if (node.type === ENTRY) { - // if keys are equal replace the entry - if (isEqual(key, node.k)) { - if (val === node.v) { - return root; - } - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet(root.array, idx, { - type: ENTRY, - k: key, - v: val, - }), - }; - } - // otherwise upgrade the entry to a node and insert - addedLeaf.val = true; - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet( - root.array, - idx, - createNode(shift + SHIFT, node.k, node.v, hash, key, val), - ), - }; - } - // otherwise call assoc on the child node - const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); - // if the child node hasn't changed just return the old root - if (n === node) { - return root; - } - // otherwise set the index to the new node - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet(root.array, idx, n), - }; -} -/** - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assocIndex(root, shift, hash, key, val, addedLeaf) { - const bit = bitpos(hash, shift); - const idx = index(root.bitmap, bit); - // if there is already a item at this hash index.. - if ((root.bitmap & bit) !== 0) { - // if there is a node at the index (not an entry), call assoc on the child node - const node = root.array[idx]; - if (node.type !== ENTRY) { - const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); - if (n === node) { - return root; - } - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet(root.array, idx, n), - }; - } - // otherwise there is an entry at the index - // if the keys are equal replace the entry with the updated value - const nodeKey = node.k; - if (isEqual(key, nodeKey)) { - if (val === node.v) { - return root; - } - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet(root.array, idx, { - type: ENTRY, - k: key, - v: val, - }), - }; - } - // if the keys are not equal, replace the entry with a new child node - addedLeaf.val = true; - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet( - root.array, - idx, - createNode(shift + SHIFT, nodeKey, node.v, hash, key, val), - ), - }; - } else { - // else there is currently no item at the hash index - const n = root.array.length; - // if the number of nodes is at the maximum, expand this node into an array node - if (n >= MAX_INDEX_NODE) { - // create a 32 length array for the new array node (one for each bit in the hash) - const nodes = new Array(32); - // create and insert a node for the new entry - const jdx = mask(hash, shift); - nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf); - let j = 0; - let bitmap = root.bitmap; - // place each item in the index node into the correct spot in the array node - // loop through all 32 bits / array positions - for (let i = 0; i < 32; i++) { - if ((bitmap & 1) !== 0) { - const node = root.array[j++]; - nodes[i] = node; - } - // shift the bitmap to process the next bit - bitmap = bitmap >>> 1; - } - return { - type: ARRAY_NODE, - size: n + 1, - array: nodes, - }; - } else { - // else there is still space in this index node - // simply insert a new entry at the hash index - const newArray = spliceIn(root.array, idx, { - type: ENTRY, - k: key, - v: val, - }); - addedLeaf.val = true; - return { - type: INDEX_NODE, - bitmap: root.bitmap | bit, - array: newArray, - }; - } - } -} -/** - * @template T,K,V - * @type {AssocFunction,K,V>} - */ -function assocCollision(root, shift, hash, key, val, addedLeaf) { - // if there is a hash collision - if (hash === root.hash) { - const idx = collisionIndexOf(root, key); - // if this key already exists replace the entry with the new value - if (idx !== -1) { - const entry = root.array[idx]; - if (entry.v === val) { - return root; - } - return { - type: COLLISION_NODE, - hash: hash, - array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), - }; - } - // otherwise insert the entry at the end of the array - const size = root.array.length; - addedLeaf.val = true; - return { - type: COLLISION_NODE, - hash: hash, - array: cloneAndSet(root.array, size, { type: ENTRY, k: key, v: val }), - }; - } - // if there is no hash collision, upgrade to an index node - return assoc( - { - type: INDEX_NODE, - bitmap: bitpos(root.hash, shift), - array: [root], - }, - shift, - hash, - key, - val, - addedLeaf, - ); -} -/** - * Find the index of a key in the collision node's array - * @template K,V - * @param {CollisionNode} root - * @param {K} key - * @returns {number} - */ -function collisionIndexOf(root, key) { - const size = root.array.length; - for (let i = 0; i < size; i++) { - if (isEqual(key, root.array[i].k)) { - return i; - } - } - return -1; -} -/** - * @template T,K,V - * @callback FindFunction - * @param {T} root - * @param {number} shift - * @param {number} hash - * @param {K} key - * @returns {undefined | Entry} - */ -/** - * Return the found entry or undefined if not present in the root - * @template K,V - * @type {FindFunction,K,V>} - */ -function find(root, shift, hash, key) { - switch (root.type) { - case ARRAY_NODE: - return findArray(root, shift, hash, key); - case INDEX_NODE: - return findIndex(root, shift, hash, key); - case COLLISION_NODE: - return findCollision(root, key); - } -} -/** - * @template K,V - * @type {FindFunction,K,V>} - */ -function findArray(root, shift, hash, key) { - const idx = mask(hash, shift); - const node = root.array[idx]; - if (node === undefined) { - return undefined; - } - if (node.type !== ENTRY) { - return find(node, shift + SHIFT, hash, key); - } - if (isEqual(key, node.k)) { - return node; - } - return undefined; -} -/** - * @template K,V - * @type {FindFunction,K,V>} - */ -function findIndex(root, shift, hash, key) { - const bit = bitpos(hash, shift); - if ((root.bitmap & bit) === 0) { - return undefined; - } - const idx = index(root.bitmap, bit); - const node = root.array[idx]; - if (node.type !== ENTRY) { - return find(node, shift + SHIFT, hash, key); - } - if (isEqual(key, node.k)) { - return node; - } - return undefined; -} -/** - * @template K,V - * @param {CollisionNode} root - * @param {K} key - * @returns {undefined | Entry} - */ -function findCollision(root, key) { - const idx = collisionIndexOf(root, key); - if (idx < 0) { - return undefined; - } - return root.array[idx]; -} -/** - * @template T,K,V - * @callback WithoutFunction - * @param {T} root - * @param {number} shift - * @param {number} hash - * @param {K} key - * @returns {undefined | Node} - */ -/** - * Remove an entry from the root, returning the updated root. - * Returns undefined if the node should be removed from the parent. - * @template K,V - * @type {WithoutFunction,K,V>} - * */ -function without(root, shift, hash, key) { - switch (root.type) { - case ARRAY_NODE: - return withoutArray(root, shift, hash, key); - case INDEX_NODE: - return withoutIndex(root, shift, hash, key); - case COLLISION_NODE: - return withoutCollision(root, key); - } -} -/** - * @template K,V - * @type {WithoutFunction,K,V>} - */ -function withoutArray(root, shift, hash, key) { - const idx = mask(hash, shift); - const node = root.array[idx]; - if (node === undefined) { - return root; // already empty - } - let n = undefined; - // if node is an entry and the keys are not equal there is nothing to remove - // if node is not an entry do a recursive call - if (node.type === ENTRY) { - if (!isEqual(node.k, key)) { - return root; // no changes - } - } else { - n = without(node, shift + SHIFT, hash, key); - if (n === node) { - return root; // no changes - } - } - // if the recursive call returned undefined the node should be removed - if (n === undefined) { - // if the number of child nodes is at the minimum, pack into an index node - if (root.size <= MIN_ARRAY_NODE) { - const arr = root.array; - const out = new Array(root.size - 1); - let i = 0; - let j = 0; - let bitmap = 0; - while (i < idx) { - const nv = arr[i]; - if (nv !== undefined) { - out[j] = nv; - bitmap |= 1 << i; - ++j; - } - ++i; - } - ++i; // skip copying the removed node - while (i < arr.length) { - const nv = arr[i]; - if (nv !== undefined) { - out[j] = nv; - bitmap |= 1 << i; - ++j; - } - ++i; - } - return { - type: INDEX_NODE, - bitmap: bitmap, - array: out, - }; - } - return { - type: ARRAY_NODE, - size: root.size - 1, - array: cloneAndSet(root.array, idx, n), - }; - } - return { - type: ARRAY_NODE, - size: root.size, - array: cloneAndSet(root.array, idx, n), - }; -} -/** - * @template K,V - * @type {WithoutFunction,K,V>} - */ -function withoutIndex(root, shift, hash, key) { - const bit = bitpos(hash, shift); - if ((root.bitmap & bit) === 0) { - return root; // already empty - } - const idx = index(root.bitmap, bit); - const node = root.array[idx]; - // if the item is not an entry - if (node.type !== ENTRY) { - const n = without(node, shift + SHIFT, hash, key); - if (n === node) { - return root; // no changes - } - // if not undefined, the child node still has items, so update it - if (n !== undefined) { - return { - type: INDEX_NODE, - bitmap: root.bitmap, - array: cloneAndSet(root.array, idx, n), - }; - } - // otherwise the child node should be removed - // if it was the only child node, remove this node from the parent - if (root.bitmap === bit) { - return undefined; - } - // otherwise just remove the child node - return { - type: INDEX_NODE, - bitmap: root.bitmap ^ bit, - array: spliceOut(root.array, idx), - }; - } - // otherwise the item is an entry, remove it if the key matches - if (isEqual(key, node.k)) { - if (root.bitmap === bit) { - return undefined; - } - return { - type: INDEX_NODE, - bitmap: root.bitmap ^ bit, - array: spliceOut(root.array, idx), - }; - } - return root; -} -/** - * @template K,V - * @param {CollisionNode} root - * @param {K} key - * @returns {undefined | Node} - */ -function withoutCollision(root, key) { - const idx = collisionIndexOf(root, key); - // if the key not found, no changes - if (idx < 0) { - return root; - } - // otherwise the entry was found, remove it - // if it was the only entry in this node, remove the whole node - if (root.array.length === 1) { - return undefined; - } - // otherwise just remove the entry - return { - type: COLLISION_NODE, - hash: root.hash, - array: spliceOut(root.array, idx), - }; -} -/** - * @template K,V - * @param {undefined | Node} root - * @param {(value:V,key:K)=>void} fn - * @returns {void} - */ -function forEach(root, fn) { - if (root === undefined) { - return; - } - const items = root.array; - const size = items.length; - for (let i = 0; i < size; i++) { - const item = items[i]; - if (item === undefined) { - continue; - } - if (item.type === ENTRY) { - fn(item.v, item.k); - continue; - } - forEach(item, fn); - } -} - -/** - * Extra wrapper to keep track of Dict size and clean up the API - * @template K,V - */ -export default class Dict { - /** - * @template V - * @param {Record} o - * @returns {Dict} - */ - static fromObject(o) { - const keys = Object.keys(o); - /** @type Dict */ - let m = Dict.new(); - for (let i = 0; i < keys.length; i++) { - const k = keys[i]; - m = m.set(k, o[k]); - } - return m; - } - - /** - * @template K,V - * @param {Map} o - * @returns {Dict} - */ - static fromMap(o) { - /** @type Dict */ - let m = Dict.new(); - o.forEach((v, k) => { - m = m.set(k, v); - }); - return m; - } - - static new() { - return new Dict(undefined, 0); - } - - /** - * @param {undefined | Node} root - * @param {number} size - */ - constructor(root, size) { - this.root = root; - this.size = size; - } - /** - * @template NotFound - * @param {K} key - * @param {NotFound} notFound - * @returns {NotFound | V} - */ - get(key, notFound) { - if (this.root === undefined) { - return notFound; - } - const found = find(this.root, 0, getHash(key), key); - if (found === undefined) { - return notFound; - } - return found.v; - } - /** - * @param {K} key - * @param {V} val - * @returns {Dict} - */ - set(key, val) { - const addedLeaf = { val: false }; - const root = this.root === undefined ? EMPTY : this.root; - const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); - if (newRoot === this.root) { - return this; - } - return new Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size); - } - /** - * @param {K} key - * @returns {Dict} - */ - delete(key) { - if (this.root === undefined) { - return this; - } - const newRoot = without(this.root, 0, getHash(key), key); - if (newRoot === this.root) { - return this; - } - if (newRoot === undefined) { - return Dict.new(); - } - return new Dict(newRoot, this.size - 1); - } - /** - * @param {K} key - * @returns {boolean} - */ - has(key) { - if (this.root === undefined) { - return false; - } - return find(this.root, 0, getHash(key), key) !== undefined; - } - /** - * @returns {[K,V][]} - */ - entries() { - if (this.root === undefined) { - return []; - } - /** @type [K,V][] */ - const result = []; - this.forEach((v, k) => result.push([k, v])); - return result; - } - /** - * - * @param {(val:V,key:K)=>void} fn - */ - forEach(fn) { - forEach(this.root, fn); - } - hashCode() { - let h = 0; - this.forEach((v, k) => { - h = (h + hashMerge(getHash(v), getHash(k))) | 0; - }); - return h; - } - /** - * @param {unknown} o - * @returns {boolean} - */ - equals(o) { - if (!(o instanceof Dict) || this.size !== o.size) { - return false; - } - - try { - this.forEach((v, k) => { - if (!isEqual(o.get(k, !v), v)) { - throw unequalDictSymbol; - } - }); - return true; - } catch (e) { - if (e === unequalDictSymbol) { - return false; - } - - throw e; - } - } -} - -// This is thrown internally in Dict.equals() so that it returns false as soon -// as a non-matching key is found -const unequalDictSymbol = /* @__PURE__ */ Symbol(); diff --git a/build/packages/gleam_stdlib/src/gleam/bit_array.gleam b/build/packages/gleam_stdlib/src/gleam/bit_array.gleam deleted file mode 100644 index 544b74a..0000000 --- a/build/packages/gleam_stdlib/src/gleam/bit_array.gleam +++ /dev/null @@ -1,280 +0,0 @@ -//// BitArrays are a sequence of binary data of any length. - -import gleam/int -import gleam/order -import gleam/string - -/// Converts a UTF-8 `String` type into a `BitArray`. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_from_string") -pub fn from_string(x: String) -> BitArray - -/// Returns an integer which is the number of bits in the bit array. -/// -@external(erlang, "erlang", "bit_size") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_bit_size") -pub fn bit_size(x: BitArray) -> Int - -/// Returns an integer which is the number of bytes in the bit array. -/// -@external(erlang, "erlang", "byte_size") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_byte_size") -pub fn byte_size(x: BitArray) -> Int - -/// Pads a bit array with zeros so that it is a whole number of bytes. -/// -@external(erlang, "gleam_stdlib", "bit_array_pad_to_bytes") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_pad_to_bytes") -pub fn pad_to_bytes(x: BitArray) -> BitArray - -/// Creates a new bit array by joining two bit arrays. -/// -/// ## Examples -/// -/// ```gleam -/// append(to: from_string("butter"), suffix: from_string("fly")) -/// // -> from_string("butterfly") -/// ``` -/// -pub fn append(to first: BitArray, suffix second: BitArray) -> BitArray { - concat([first, second]) -} - -/// Extracts a sub-section of a bit array. -/// -/// The slice will start at given position and continue up to specified -/// length. -/// A negative length can be used to extract bytes at the end of a bit array. -/// -/// This function runs in constant time. -/// -@external(erlang, "gleam_stdlib", "bit_array_slice") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_slice") -pub fn slice( - from string: BitArray, - at position: Int, - take length: Int, -) -> Result(BitArray, Nil) - -/// Tests to see whether a bit array is valid UTF-8. -/// -pub fn is_utf8(bits: BitArray) -> Bool { - is_utf8_loop(bits) -} - -@target(erlang) -fn is_utf8_loop(bits: BitArray) -> Bool { - case bits { - <<>> -> True - <<_:utf8, rest:bytes>> -> is_utf8_loop(rest) - _ -> False - } -} - -@target(javascript) -fn is_utf8_loop(bits: BitArray) -> Bool { - case to_string(bits) { - Ok(_) -> True - Error(_) -> False - } -} - -/// Converts a bit array to a string. -/// -/// Returns an error if the bit array is invalid UTF-8 data. -/// -@external(javascript, "../gleam_stdlib.mjs", "bit_array_to_string") -pub fn to_string(bits: BitArray) -> Result(String, Nil) { - case is_utf8(bits) { - True -> Ok(unsafe_to_string(bits)) - False -> Error(Nil) - } -} - -@external(erlang, "gleam_stdlib", "identity") -fn unsafe_to_string(a: BitArray) -> String - -/// Creates a new bit array by joining multiple binaries. -/// -/// ## Examples -/// -/// ```gleam -/// concat([from_string("butter"), from_string("fly")]) -/// // -> from_string("butterfly") -/// ``` -/// -@external(erlang, "gleam_stdlib", "bit_array_concat") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_concat") -pub fn concat(bit_arrays: List(BitArray)) -> BitArray - -/// Encodes a BitArray into a base 64 encoded string. -/// -/// If the bit array does not contain a whole number of bytes then it is padded -/// with zero bits prior to being encoded. -/// -@external(erlang, "gleam_stdlib", "base64_encode") -@external(javascript, "../gleam_stdlib.mjs", "base64_encode") -pub fn base64_encode(input: BitArray, padding: Bool) -> String - -/// Decodes a base 64 encoded string into a `BitArray`. -/// -pub fn base64_decode(encoded: String) -> Result(BitArray, Nil) { - let padded = case byte_size(from_string(encoded)) % 4 { - 0 -> encoded - n -> string.append(encoded, string.repeat("=", 4 - n)) - } - decode64(padded) -} - -@external(erlang, "gleam_stdlib", "base64_decode") -@external(javascript, "../gleam_stdlib.mjs", "base64_decode") -fn decode64(a: String) -> Result(BitArray, Nil) - -/// Encodes a `BitArray` into a base 64 encoded string with URL and filename -/// safe alphabet. -/// -/// If the bit array does not contain a whole number of bytes then it is padded -/// with zero bits prior to being encoded. -/// -pub fn base64_url_encode(input: BitArray, padding: Bool) -> String { - input - |> base64_encode(padding) - |> string.replace("+", "-") - |> string.replace("/", "_") -} - -/// Decodes a base 64 encoded string with URL and filename safe alphabet into a -/// `BitArray`. -/// -pub fn base64_url_decode(encoded: String) -> Result(BitArray, Nil) { - encoded - |> string.replace("-", "+") - |> string.replace("_", "/") - |> base64_decode() -} - -/// Encodes a `BitArray` into a base 16 encoded string. -/// -/// If the bit array does not contain a whole number of bytes then it is padded -/// with zero bits prior to being encoded. -/// -@external(erlang, "gleam_stdlib", "base16_encode") -@external(javascript, "../gleam_stdlib.mjs", "base16_encode") -pub fn base16_encode(input: BitArray) -> String - -/// Decodes a base 16 encoded string into a `BitArray`. -/// -@external(erlang, "gleam_stdlib", "base16_decode") -@external(javascript, "../gleam_stdlib.mjs", "base16_decode") -pub fn base16_decode(input: String) -> Result(BitArray, Nil) - -/// Converts a bit array to a string containing the decimal value of each byte. -/// -/// Use this over `string.inspect` when you have a bit array you want printed -/// in the array syntax even if it is valid UTF-8. -/// -/// ## Examples -/// -/// ```gleam -/// inspect(<<0, 20, 0x20, 255>>) -/// // -> "<<0, 20, 32, 255>>" -/// -/// inspect(<<100, 5:3>>) -/// // -> "<<100, 5:size(3)>>" -/// ``` -/// -pub fn inspect(input: BitArray) -> String { - inspect_loop(input, "<<") <> ">>" -} - -fn inspect_loop(input: BitArray, accumulator: String) -> String { - case input { - <<>> -> accumulator - - <> -> accumulator <> int.to_string(x) <> ":size(1)" - <> -> accumulator <> int.to_string(x) <> ":size(2)" - <> -> accumulator <> int.to_string(x) <> ":size(3)" - <> -> accumulator <> int.to_string(x) <> ":size(4)" - <> -> accumulator <> int.to_string(x) <> ":size(5)" - <> -> accumulator <> int.to_string(x) <> ":size(6)" - <> -> accumulator <> int.to_string(x) <> ":size(7)" - - <> -> { - let suffix = case rest { - <<>> -> "" - _ -> ", " - } - - let accumulator = accumulator <> int.to_string(x) <> suffix - inspect_loop(rest, accumulator) - } - - _ -> accumulator - } -} - -/// Compare two bit arrays as sequences of bytes. -/// -/// ## Examples -/// -/// ```gleam -/// compare(<<1>>, <<2>>) -/// // -> Lt -/// -/// compare(<<"AB":utf8>>, <<"AA":utf8>>) -/// // -> Gt -/// -/// compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>) -/// // -> Eq -/// ``` -/// -pub fn compare(a: BitArray, with b: BitArray) -> order.Order { - case a, b { - <>, <> -> - case first_byte, second_byte { - f, s if f > s -> order.Gt - f, s if f < s -> order.Lt - _, _ -> compare(first_rest, second_rest) - } - - <<>>, <<>> -> order.Eq - // First has more items, example: "AB" > "A": - _, <<>> -> order.Gt - // Second has more items, example: "A" < "AB": - <<>>, _ -> order.Lt - // This happens when there's unusually sized elements. - // Handle these special cases via custom erlang function. - first, second -> - case bit_array_to_int_and_size(first), bit_array_to_int_and_size(second) { - #(a, _), #(b, _) if a > b -> order.Gt - #(a, _), #(b, _) if a < b -> order.Lt - #(_, size_a), #(_, size_b) if size_a > size_b -> order.Gt - #(_, size_a), #(_, size_b) if size_a < size_b -> order.Lt - _, _ -> order.Eq - } - } -} - -@external(erlang, "gleam_stdlib", "bit_array_to_int_and_size") -@external(javascript, "../gleam_stdlib.mjs", "bit_array_to_int_and_size") -fn bit_array_to_int_and_size(a: BitArray) -> #(Int, Int) - -/// Checks whether the first `BitArray` starts with the second one. -/// -/// ## Examples -/// -/// ```gleam -/// starts_with(<<1, 2, 3, 4>>, <<1, 2>>) -/// // -> True -/// ``` -/// -@external(javascript, "../gleam_stdlib.mjs", "bit_array_starts_with") -pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool { - let prefix_size = bit_size(prefix) - - case bits { - <> if pref == prefix -> True - _ -> False - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/bool.gleam b/build/packages/gleam_stdlib/src/gleam/bool.gleam deleted file mode 100644 index 26a6ac4..0000000 --- a/build/packages/gleam_stdlib/src/gleam/bool.gleam +++ /dev/null @@ -1,316 +0,0 @@ -//// A type with two possible values, `True` and `False`. Used to indicate whether -//// things are... true or false! -//// -//// Often is it clearer and offers more type safety to define a custom type -//// than to use `Bool`. For example, rather than having a `is_teacher: Bool` -//// field consider having a `role: SchoolRole` field where `SchoolRole` is a custom -//// type that can be either `Student` or `Teacher`. - -/// Returns the and of two bools, but it evaluates both arguments. -/// -/// It's the function equivalent of the `&&` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// and(True, True) -/// // -> True -/// ``` -/// -/// ```gleam -/// and(False, True) -/// // -> False -/// ``` -/// -/// ```gleam -/// False |> and(True) -/// // -> False -/// ``` -/// -pub fn and(a: Bool, b: Bool) -> Bool { - a && b -} - -/// Returns the or of two bools, but it evaluates both arguments. -/// -/// It's the function equivalent of the `||` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// or(True, True) -/// // -> True -/// ``` -/// -/// ```gleam -/// or(False, True) -/// // -> True -/// ``` -/// -/// ```gleam -/// False |> or(True) -/// // -> True -/// ``` -/// -pub fn or(a: Bool, b: Bool) -> Bool { - a || b -} - -/// Returns the opposite bool value. -/// -/// This is the same as the `!` or `not` operators in some other languages. -/// -/// ## Examples -/// -/// ```gleam -/// negate(True) -/// // -> False -/// ``` -/// -/// ```gleam -/// negate(False) -/// // -> True -/// ``` -/// -pub fn negate(bool: Bool) -> Bool { - !bool -} - -/// Returns the nor of two bools. -/// -/// ## Examples -/// -/// ```gleam -/// nor(False, False) -/// // -> True -/// ``` -/// -/// ```gleam -/// nor(False, True) -/// // -> False -/// ``` -/// -/// ```gleam -/// nor(True, False) -/// // -> False -/// ``` -/// -/// ```gleam -/// nor(True, True) -/// // -> False -/// ``` -/// -pub fn nor(a: Bool, b: Bool) -> Bool { - !{ a || b } -} - -/// Returns the nand of two bools. -/// -/// ## Examples -/// -/// ```gleam -/// nand(False, False) -/// // -> True -/// ``` -/// -/// ```gleam -/// nand(False, True) -/// // -> True -/// ``` -/// -/// ```gleam -/// nand(True, False) -/// // -> True -/// ``` -/// -/// ```gleam -/// nand(True, True) -/// // -> False -/// ``` -/// -pub fn nand(a: Bool, b: Bool) -> Bool { - !{ a && b } -} - -/// Returns the exclusive or of two bools. -/// -/// ## Examples -/// -/// ```gleam -/// exclusive_or(False, False) -/// // -> False -/// ``` -/// -/// ```gleam -/// exclusive_or(False, True) -/// // -> True -/// ``` -/// -/// ```gleam -/// exclusive_or(True, False) -/// // -> True -/// ``` -/// -/// ```gleam -/// exclusive_or(True, True) -/// // -> False -/// ``` -/// -pub fn exclusive_or(a: Bool, b: Bool) -> Bool { - a != b -} - -/// Returns the exclusive nor of two bools. -/// -/// ## Examples -/// -/// ```gleam -/// exclusive_nor(False, False) -/// // -> True -/// ``` -/// -/// ```gleam -/// exclusive_nor(False, True) -/// // -> False -/// ``` -/// -/// ```gleam -/// exclusive_nor(True, False) -/// // -> False -/// ``` -/// -/// ```gleam -/// exclusive_nor(True, True) -/// // -> True -/// ``` -/// -pub fn exclusive_nor(a: Bool, b: Bool) -> Bool { - a == b -} - -/// Returns a string representation of the given bool. -/// -/// ## Examples -/// -/// ```gleam -/// to_string(True) -/// // -> "True" -/// ``` -/// -/// ```gleam -/// to_string(False) -/// // -> "False" -/// ``` -/// -pub fn to_string(bool: Bool) -> String { - case bool { - False -> "False" - True -> "True" - } -} - -/// Run a callback function if the given bool is `False`, otherwise return a -/// default value. -/// -/// With a `use` expression this function can simulate the early-return pattern -/// found in some other programming languages. -/// -/// In a procedural language: -/// -/// ```js -/// if (predicate) return value; -/// // ... -/// ``` -/// -/// In Gleam with a `use` expression: -/// -/// ```gleam -/// use <- guard(when: predicate, return: value) -/// // ... -/// ``` -/// -/// Like everything in Gleam `use` is an expression, so it short circuits the -/// current block, not the entire function. As a result you can assign the value -/// to a variable: -/// -/// ```gleam -/// let x = { -/// use <- guard(when: predicate, return: value) -/// // ... -/// } -/// ``` -/// -/// Note that unlike in procedural languages the `return` value is evaluated -/// even when the predicate is `False`, so it is advisable not to perform -/// expensive computation nor side-effects there. -/// -/// -/// ## Examples -/// -/// ```gleam -/// let name = "" -/// use <- guard(when: name == "", return: "Welcome!") -/// "Hello, " <> name -/// // -> "Welcome!" -/// ``` -/// -/// ```gleam -/// let name = "Kamaka" -/// use <- guard(when: name == "", return: "Welcome!") -/// "Hello, " <> name -/// // -> "Hello, Kamaka" -/// ``` -/// -pub fn guard( - when requirement: Bool, - return consequence: a, - otherwise alternative: fn() -> a, -) -> a { - case requirement { - True -> consequence - False -> alternative() - } -} - -/// Runs a callback function if the given bool is `True`, otherwise runs an -/// alternative callback function. -/// -/// Useful when further computation should be delayed regardless of the given -/// bool's value. -/// -/// See [`guard`](#guard) for more info. -/// -/// ## Examples -/// -/// ```gleam -/// let name = "Kamaka" -/// let inquiry = fn() { "How may we address you?" } -/// use <- lazy_guard(when: name == "", return: inquiry) -/// "Hello, " <> name -/// // -> "Hello, Kamaka" -/// ``` -/// -/// ```gleam -/// import gleam/int -/// -/// let name = "" -/// let greeting = fn() { "Hello, " <> name } -/// use <- lazy_guard(when: name == "", otherwise: greeting) -/// let number = int.random(99) -/// let name = "User " <> int.to_string(number) -/// "Welcome, " <> name -/// // -> "Welcome, User 54" -/// ``` -/// -pub fn lazy_guard( - when requirement: Bool, - return consequence: fn() -> a, - otherwise alternative: fn() -> a, -) -> a { - case requirement { - True -> consequence() - False -> alternative() - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/bytes_tree.gleam b/build/packages/gleam_stdlib/src/gleam/bytes_tree.gleam deleted file mode 100644 index 832fbee..0000000 --- a/build/packages/gleam_stdlib/src/gleam/bytes_tree.gleam +++ /dev/null @@ -1,190 +0,0 @@ -//// `BytesTree` is a type used for efficiently building binary content to be -//// written to a file or a socket. Internally it is represented as tree so to -//// append or prepend to a bytes tree is a constant time operation that -//// allocates a new node in the tree without copying any of the content. When -//// writing to an output stream the tree is traversed and the content is sent -//// directly rather than copying it into a single buffer beforehand. -//// -//// If we append one bit array to another the bit arrays must be copied to a -//// new location in memory so that they can sit together. This behaviour -//// enables efficient reading of the data but copying can be expensive, -//// especially if we want to join many bit arrays together. -//// -//// BytesTree is different in that it can be joined together in constant -//// time using minimal memory, and then can be efficiently converted to a -//// bit array using the `to_bit_array` function. -//// -//// Byte trees are always byte aligned, so that a number of bits that is not -//// divisible by 8 will be padded with 0s. -//// -//// On Erlang this type is compatible with Erlang's iolists. - -import gleam/bit_array -import gleam/list -import gleam/string_tree.{type StringTree} - -pub opaque type BytesTree { - Bytes(BitArray) - Text(StringTree) - Many(List(BytesTree)) -} - -/// Create an empty `BytesTree`. Useful as the start of a pipe chaining many -/// trees together. -/// -pub fn new() -> BytesTree { - concat([]) -} - -/// Prepends a bit array to the start of a bytes tree. -/// -/// Runs in constant time. -/// -pub fn prepend(to second: BytesTree, prefix first: BitArray) -> BytesTree { - append_tree(from_bit_array(first), second) -} - -/// Appends a bit array to the end of a bytes tree. -/// -/// Runs in constant time. -/// -pub fn append(to first: BytesTree, suffix second: BitArray) -> BytesTree { - append_tree(first, from_bit_array(second)) -} - -/// Prepends a bytes tree onto the start of another. -/// -/// Runs in constant time. -/// -pub fn prepend_tree(to second: BytesTree, prefix first: BytesTree) -> BytesTree { - append_tree(first, second) -} - -/// Appends a bytes tree onto the end of another. -/// -/// Runs in constant time. -/// -@external(erlang, "gleam_stdlib", "iodata_append") -pub fn append_tree(to first: BytesTree, suffix second: BytesTree) -> BytesTree { - case second { - Many(trees) -> Many([first, ..trees]) - Text(_) | Bytes(_) -> Many([first, second]) - } -} - -/// Prepends a string onto the start of a bytes tree. -/// -/// Runs in constant time when running on Erlang. -/// Runs in linear time with the length of the string otherwise. -/// -pub fn prepend_string(to second: BytesTree, prefix first: String) -> BytesTree { - append_tree(from_string(first), second) -} - -/// Appends a string onto the end of a bytes tree. -/// -/// Runs in constant time when running on Erlang. -/// Runs in linear time with the length of the string otherwise. -/// -pub fn append_string(to first: BytesTree, suffix second: String) -> BytesTree { - append_tree(first, from_string(second)) -} - -/// Joins a list of bytes trees into a single one. -/// -/// Runs in constant time. -/// -@external(erlang, "gleam_stdlib", "identity") -pub fn concat(trees: List(BytesTree)) -> BytesTree { - Many(trees) -} - -/// Joins a list of bit arrays into a single bytes tree. -/// -/// Runs in constant time. -/// -pub fn concat_bit_arrays(bits: List(BitArray)) -> BytesTree { - bits - |> list.map(from_bit_array) - |> concat() -} - -/// Creates a new bytes tree from a string. -/// -/// Runs in constant time when running on Erlang. -/// Runs in linear time otherwise. -/// -@external(erlang, "gleam_stdlib", "wrap_list") -pub fn from_string(string: String) -> BytesTree { - Text(string_tree.from_string(string)) -} - -/// Creates a new bytes tree from a string tree. -/// -/// Runs in constant time when running on Erlang. -/// Runs in linear time otherwise. -/// -@external(erlang, "gleam_stdlib", "wrap_list") -pub fn from_string_tree(tree: string_tree.StringTree) -> BytesTree { - Text(tree) -} - -/// Creates a new bytes tree from a bit array. -/// -/// Runs in constant time. -/// -pub fn from_bit_array(bits: BitArray) -> BytesTree { - bits - |> bit_array.pad_to_bytes - |> wrap_list -} - -@external(erlang, "gleam_stdlib", "wrap_list") -fn wrap_list(bits: BitArray) -> BytesTree { - Bytes(bits) -} - -/// Turns a bytes tree into a bit array. -/// -/// Runs in linear time. -/// -/// When running on Erlang this function is implemented natively by the -/// virtual machine and is highly optimised. -/// -@external(erlang, "erlang", "list_to_bitstring") -pub fn to_bit_array(tree: BytesTree) -> BitArray { - [[tree]] - |> to_list([]) - |> list.reverse - |> bit_array.concat -} - -fn to_list(stack: List(List(BytesTree)), acc: List(BitArray)) -> List(BitArray) { - case stack { - [] -> acc - - [[], ..remaining_stack] -> to_list(remaining_stack, acc) - - [[Bytes(bits), ..rest], ..remaining_stack] -> - to_list([rest, ..remaining_stack], [bits, ..acc]) - - [[Text(tree), ..rest], ..remaining_stack] -> { - let bits = bit_array.from_string(string_tree.to_string(tree)) - to_list([rest, ..remaining_stack], [bits, ..acc]) - } - - [[Many(trees), ..rest], ..remaining_stack] -> - to_list([trees, rest, ..remaining_stack], acc) - } -} - -/// Returns the size of the bytes tree's content in bytes. -/// -/// Runs in linear time. -/// -@external(erlang, "erlang", "iolist_size") -pub fn byte_size(tree: BytesTree) -> Int { - [[tree]] - |> to_list([]) - |> list.fold(0, fn(acc, bits) { bit_array.byte_size(bits) + acc }) -} diff --git a/build/packages/gleam_stdlib/src/gleam/dict.gleam b/build/packages/gleam_stdlib/src/gleam/dict.gleam deleted file mode 100644 index 2942727..0000000 --- a/build/packages/gleam_stdlib/src/gleam/dict.gleam +++ /dev/null @@ -1,548 +0,0 @@ -import gleam/option.{type Option} - -/// A dictionary of keys and values. -/// -/// Any type can be used for the keys and values of a dict, but all the keys -/// must be of the same type and all the values must be of the same type. -/// -/// Each key can only be present in a dict once. -/// -/// Dicts are not ordered in any way, and any unintentional ordering is not to -/// be relied upon in your code as it may change in future versions of Erlang -/// or Gleam. -/// -/// See [the Erlang map module](https://erlang.org/doc/man/maps.html) for more -/// information. -/// -pub type Dict(key, value) - -/// Determines the number of key-value pairs in the dict. -/// This function runs in constant time and does not need to iterate the dict. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> size -/// // -> 0 -/// ``` -/// -/// ```gleam -/// new() |> insert("key", "value") |> size -/// // -> 1 -/// ``` -/// -@external(erlang, "maps", "size") -@external(javascript, "../gleam_stdlib.mjs", "map_size") -pub fn size(dict: Dict(k, v)) -> Int - -/// Determines whether or not the dict is empty. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> is_empty -/// // -> True -/// ``` -/// -/// ```gleam -/// new() |> insert("b", 1) |> is_empty -/// // -> False -/// ``` -/// -pub fn is_empty(dict: Dict(k, v)) -> Bool { - size(dict) == 0 -} - -/// Converts the dict to a list of 2-element tuples `#(key, value)`, one for -/// each key-value pair in the dict. -/// -/// The tuples in the list have no specific order. -/// -/// ## Examples -/// -/// Calling `to_list` on an empty `dict` returns an empty list. -/// -/// ```gleam -/// new() |> to_list -/// // -> [] -/// ``` -/// -/// The ordering of elements in the resulting list is an implementation detail -/// that should not be relied upon. -/// -/// ```gleam -/// new() |> insert("b", 1) |> insert("a", 0) |> insert("c", 2) |> to_list -/// // -> [#("a", 0), #("b", 1), #("c", 2)] -/// ``` -/// -@external(erlang, "maps", "to_list") -@external(javascript, "../gleam_stdlib.mjs", "map_to_list") -pub fn to_list(dict: Dict(k, v)) -> List(#(k, v)) - -/// Converts a list of 2-element tuples `#(key, value)` to a dict. -/// -/// If two tuples have the same key the last one in the list will be the one -/// that is present in the dict. -/// -@external(erlang, "maps", "from_list") -pub fn from_list(list: List(#(k, v))) -> Dict(k, v) { - from_list_loop(list, new()) -} - -fn from_list_loop( - over list: List(#(k, v)), - from initial: Dict(k, v), -) -> Dict(k, v) { - case list { - [] -> initial - [#(key, value), ..rest] -> from_list_loop(rest, insert(initial, key, value)) - } -} - -/// Determines whether or not a value present in the dict for a given key. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> insert("a", 0) |> has_key("a") -/// // -> True -/// ``` -/// -/// ```gleam -/// new() |> insert("a", 0) |> has_key("b") -/// // -> False -/// ``` -/// -pub fn has_key(dict: Dict(k, v), key: k) -> Bool { - do_has_key(key, dict) -} - -@external(erlang, "maps", "is_key") -fn do_has_key(key: k, dict: Dict(k, v)) -> Bool { - get(dict, key) != Error(Nil) -} - -/// Creates a fresh dict that contains no values. -/// -@external(erlang, "maps", "new") -@external(javascript, "../gleam_stdlib.mjs", "new_map") -pub fn new() -> Dict(k, v) - -/// Fetches a value from a dict for a given key. -/// -/// The dict may not have a value for the key, so the value is wrapped in a -/// `Result`. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> insert("a", 0) |> get("a") -/// // -> Ok(0) -/// ``` -/// -/// ```gleam -/// new() |> insert("a", 0) |> get("b") -/// // -> Error(Nil) -/// ``` -/// -@external(erlang, "gleam_stdlib", "map_get") -@external(javascript, "../gleam_stdlib.mjs", "map_get") -pub fn get(from: Dict(k, v), get: k) -> Result(v, Nil) - -/// Inserts a value into the dict with the given key. -/// -/// If the dict already has a value for the given key then the value is -/// replaced with the new value. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> insert("a", 0) -/// // -> from_list([#("a", 0)]) -/// ``` -/// -/// ```gleam -/// new() |> insert("a", 0) |> insert("a", 5) -/// // -> from_list([#("a", 5)]) -/// ``` -/// -pub fn insert(into dict: Dict(k, v), for key: k, insert value: v) -> Dict(k, v) { - do_insert(key, value, dict) -} - -@external(erlang, "maps", "put") -@external(javascript, "../gleam_stdlib.mjs", "map_insert") -fn do_insert(key: k, value: v, dict: Dict(k, v)) -> Dict(k, v) - -/// Updates all values in a given dict by calling a given function on each key -/// and value. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#(3, 3), #(2, 4)]) -/// |> map_values(fn(key, value) { key * value }) -/// // -> from_list([#(3, 9), #(2, 8)]) -/// ``` -/// -pub fn map_values(in dict: Dict(k, v), with fun: fn(k, v) -> a) -> Dict(k, a) { - do_map_values(fun, dict) -} - -@external(erlang, "maps", "map") -fn do_map_values(f: fn(k, v) -> a, dict: Dict(k, v)) -> Dict(k, a) { - let f = fn(dict, k, v) { insert(dict, k, f(k, v)) } - fold(dict, from: new(), with: f) -} - -/// Gets a list of all keys in a given dict. -/// -/// Dicts are not ordered so the keys are not returned in any specific order. Do -/// not write code that relies on the order keys are returned by this function -/// as it may change in later versions of Gleam or Erlang. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> keys -/// // -> ["a", "b"] -/// ``` -/// -@external(erlang, "maps", "keys") -pub fn keys(dict: Dict(k, v)) -> List(k) { - do_keys_loop(to_list(dict), []) -} - -fn do_keys_loop(list: List(#(k, v)), acc: List(k)) -> List(k) { - case list { - [] -> reverse_and_concat(acc, []) - [#(key, _value), ..rest] -> do_keys_loop(rest, [key, ..acc]) - } -} - -fn reverse_and_concat(remaining: List(a), accumulator: List(a)) -> List(a) { - case remaining { - [] -> accumulator - [first, ..rest] -> reverse_and_concat(rest, [first, ..accumulator]) - } -} - -/// Gets a list of all values in a given dict. -/// -/// Dicts are not ordered so the values are not returned in any specific order. Do -/// not write code that relies on the order values are returned by this function -/// as it may change in later versions of Gleam or Erlang. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> values -/// // -> [0, 1] -/// ``` -/// -@external(erlang, "maps", "values") -pub fn values(dict: Dict(k, v)) -> List(v) { - let list_of_pairs = to_list(dict) - do_values_loop(list_of_pairs, []) -} - -fn do_values_loop(list: List(#(k, v)), acc: List(v)) -> List(v) { - case list { - [] -> reverse_and_concat(acc, []) - [#(_key, value), ..rest] -> do_values_loop(rest, [value, ..acc]) - } -} - -/// Creates a new dict from a given dict, minus any entries that a given function -/// returns `False` for. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) -/// |> filter(fn(key, value) { value != 0 }) -/// // -> from_list([#("b", 1)]) -/// ``` -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) -/// |> filter(fn(key, value) { True }) -/// // -> from_list([#("a", 0), #("b", 1)]) -/// ``` -/// -pub fn filter( - in dict: Dict(k, v), - keeping predicate: fn(k, v) -> Bool, -) -> Dict(k, v) { - do_filter(predicate, dict) -} - -@external(erlang, "maps", "filter") -fn do_filter(f: fn(k, v) -> Bool, dict: Dict(k, v)) -> Dict(k, v) { - let insert = fn(dict, k, v) { - case f(k, v) { - True -> insert(dict, k, v) - False -> dict - } - } - - fold(dict, from: new(), with: insert) -} - -/// Creates a new dict from a given dict, only including any entries for which the -/// keys are in a given list. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) -/// |> take(["b"]) -/// // -> from_list([#("b", 1)]) -/// ``` -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) -/// |> take(["a", "b", "c"]) -/// // -> from_list([#("a", 0), #("b", 1)]) -/// ``` -/// -pub fn take(from dict: Dict(k, v), keeping desired_keys: List(k)) -> Dict(k, v) { - do_take(desired_keys, dict) -} - -@external(erlang, "maps", "with") -fn do_take(desired_keys: List(k), dict: Dict(k, v)) -> Dict(k, v) { - do_take_loop(dict, desired_keys, new()) -} - -fn do_take_loop( - dict: Dict(k, v), - desired_keys: List(k), - acc: Dict(k, v), -) -> Dict(k, v) { - let insert = fn(taken, key) { - case get(dict, key) { - Ok(value) -> insert(taken, key, value) - Error(_) -> taken - } - } - case desired_keys { - [] -> acc - [first, ..rest] -> do_take_loop(dict, rest, insert(acc, first)) - } -} - -/// Creates a new dict from a pair of given dicts by combining their entries. -/// -/// If there are entries with the same keys in both dicts the entry from the -/// second dict takes precedence. -/// -/// ## Examples -/// -/// ```gleam -/// let a = from_list([#("a", 0), #("b", 1)]) -/// let b = from_list([#("b", 2), #("c", 3)]) -/// merge(a, b) -/// // -> from_list([#("a", 0), #("b", 2), #("c", 3)]) -/// ``` -/// -@external(erlang, "maps", "merge") -pub fn merge(into dict: Dict(k, v), from new_entries: Dict(k, v)) -> Dict(k, v) { - new_entries - |> to_list - |> fold_inserts(dict) -} - -fn fold_inserts(new_entries: List(#(k, v)), dict: Dict(k, v)) -> Dict(k, v) { - case new_entries { - [] -> dict - [first, ..rest] -> fold_inserts(rest, insert_pair(dict, first)) - } -} - -fn insert_pair(dict: Dict(k, v), pair: #(k, v)) -> Dict(k, v) { - insert(dict, pair.0, pair.1) -} - -/// Creates a new dict from a given dict with all the same entries except for the -/// one with a given key, if it exists. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> delete("a") -/// // -> from_list([#("b", 1)]) -/// ``` -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> delete("c") -/// // -> from_list([#("a", 0), #("b", 1)]) -/// ``` -/// -pub fn delete(from dict: Dict(k, v), delete key: k) -> Dict(k, v) { - do_delete(key, dict) -} - -@external(erlang, "maps", "remove") -@external(javascript, "../gleam_stdlib.mjs", "map_remove") -fn do_delete(a: k, b: Dict(k, v)) -> Dict(k, v) - -/// Creates a new dict from a given dict with all the same entries except any with -/// keys found in a given list. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> drop(["a"]) -/// // -> from_list([#("b", 1)]) -/// ``` -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> drop(["c"]) -/// // -> from_list([#("a", 0), #("b", 1)]) -/// ``` -/// -/// ```gleam -/// from_list([#("a", 0), #("b", 1)]) |> drop(["a", "b", "c"]) -/// // -> from_list([]) -/// ``` -/// -pub fn drop(from dict: Dict(k, v), drop disallowed_keys: List(k)) -> Dict(k, v) { - case disallowed_keys { - [] -> dict - [first, ..rest] -> drop(delete(dict, first), rest) - } -} - -/// Creates a new dict with one entry inserted or updated using a given function. -/// -/// If there was not an entry in the dict for the given key then the function -/// gets `None` as its argument, otherwise it gets `Some(value)`. -/// -/// ## Example -/// -/// ```gleam -/// let dict = from_list([#("a", 0)]) -/// let increment = fn(x) { -/// case x { -/// Some(i) -> i + 1 -/// None -> 0 -/// } -/// } -/// -/// upsert(dict, "a", increment) -/// // -> from_list([#("a", 1)]) -/// -/// upsert(dict, "b", increment) -/// // -> from_list([#("a", 0), #("b", 0)]) -/// ``` -/// -pub fn upsert( - in dict: Dict(k, v), - update key: k, - with fun: fn(Option(v)) -> v, -) -> Dict(k, v) { - case get(dict, key) { - Ok(value) -> insert(dict, key, fun(option.Some(value))) - Error(_) -> insert(dict, key, fun(option.None)) - } -} - -/// Combines all entries into a single value by calling a given function on each -/// one. -/// -/// Dicts are not ordered so the values are not returned in any specific order. Do -/// not write code that relies on the order entries are used by this function -/// as it may change in later versions of Gleam or Erlang. -/// -/// # Examples -/// -/// ```gleam -/// let dict = from_list([#("a", 1), #("b", 3), #("c", 9)]) -/// fold(dict, 0, fn(accumulator, key, value) { accumulator + value }) -/// // -> 13 -/// ``` -/// -/// ```gleam -/// import gleam/string -/// -/// let dict = from_list([#("a", 1), #("b", 3), #("c", 9)]) -/// fold(dict, "", fn(accumulator, key, value) { -/// string.append(accumulator, key) -/// }) -/// // -> "abc" -/// ``` -/// -pub fn fold( - over dict: Dict(k, v), - from initial: acc, - with fun: fn(acc, k, v) -> acc, -) -> acc { - fold_loop(to_list(dict), initial, fun) -} - -fn fold_loop( - list: List(#(k, v)), - initial: acc, - fun: fn(acc, k, v) -> acc, -) -> acc { - case list { - [] -> initial - [#(k, v), ..rest] -> fold_loop(rest, fun(initial, k, v), fun) - } -} - -/// Calls a function for each key and value in a dict, discarding the return -/// value. -/// -/// Useful for producing a side effect for every item of a dict. -/// -/// ```gleam -/// import gleam/io -/// -/// let dict = from_list([#("a", "apple"), #("b", "banana"), #("c", "cherry")]) -/// -/// each(dict, fn(k, v) { -/// io.println(key <> " => " <> value) -/// }) -/// // -> Nil -/// // a => apple -/// // b => banana -/// // c => cherry -/// ``` -/// -/// The order of elements in the iteration is an implementation detail that -/// should not be relied upon. -/// -pub fn each(dict: Dict(k, v), fun: fn(k, v) -> a) -> Nil { - fold(dict, Nil, fn(nil, k, v) { - fun(k, v) - nil - }) -} - -/// Creates a new dict from a pair of given dicts by combining their entries. -/// -/// If there are entries with the same keys in both dicts the given function is -/// used to determine the new value to use in the resulting dict. -/// -/// ## Examples -/// -/// ```gleam -/// let a = from_list([#("a", 0), #("b", 1)]) -/// let b = from_list([#("a", 2), #("c", 3)]) -/// combine(a, b, fn(one, other) { one + other }) -/// // -> from_list([#("a", 2), #("b", 1), #("c", 3)]) -/// ``` -/// -pub fn combine( - dict: Dict(k, v), - other: Dict(k, v), - with fun: fn(v, v) -> v, -) -> Dict(k, v) { - use acc, key, value <- fold(over: dict, from: other) - case get(acc, key) { - Ok(other_value) -> insert(acc, key, fun(value, other_value)) - Error(_) -> insert(acc, key, value) - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/dynamic.gleam b/build/packages/gleam_stdlib/src/gleam/dynamic.gleam deleted file mode 100644 index 6dfcbe6..0000000 --- a/build/packages/gleam_stdlib/src/gleam/dynamic.gleam +++ /dev/null @@ -1,100 +0,0 @@ -import gleam/dict - -/// `Dynamic` data is data that we don't know the type of yet. -/// We likely get data like this from interop with Erlang, or from -/// IO with the outside world. -/// -/// This module contains code for forming dynamic data, and the -/// `gleam/dynamic/decode` module contains code for turning dynamic data back -/// into Gleam data with known types. You will likely mostly use the other -/// module in your projects. -/// -/// The exact runtime representation of dynamic values will depend on the -/// compilation target used. -/// -pub type Dynamic - -/// Return a string indicating the type of the dynamic value. -/// -/// This function may be useful for constructing error messages or logs. If you -/// want to turn dynamic data into well typed data then you want the -/// `gleam/dynamic/decode` module. -/// -/// ```gleam -/// classify(string("Hello")) -/// // -> "String" -/// ``` -/// -@external(erlang, "gleam_stdlib", "classify_dynamic") -@external(javascript, "../gleam_stdlib.mjs", "classify_dynamic") -pub fn classify(data: Dynamic) -> String - -/// Create a dynamic value from a bool. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn bool(a: Bool) -> Dynamic - -/// Create a dynamic value from a string. -/// -/// On Erlang this will be a binary string rather than a character list. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn string(a: String) -> Dynamic - -/// Create a dynamic value from a float. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn float(a: Float) -> Dynamic - -/// Create a dynamic value from an int. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn int(a: Int) -> Dynamic - -/// Create a dynamic value from a bit array. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn bit_array(a: BitArray) -> Dynamic - -/// Create a dynamic value from a list. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn list(a: List(Dynamic)) -> Dynamic - -/// Create a dynamic value from a list, converting it to a sequential runtime -/// format rather than the regular list format. -/// -/// On Erlang this will be a tuple, on JavaScript this will be an array. -/// -@external(erlang, "erlang", "list_to_tuple") -@external(javascript, "../gleam_stdlib.mjs", "list_to_array") -pub fn array(a: List(Dynamic)) -> Dynamic - -/// Create a dynamic value made an unordered series of keys and values, where -/// the keys are unique. -/// -/// On Erlang this will be a map, on JavaScript this will be a Gleam dict -/// object. -/// -pub fn properties(entries: List(#(Dynamic, Dynamic))) -> Dynamic { - cast(dict.from_list(entries)) -} - -/// A dynamic value representing nothing. -/// -/// On Erlang this will be the atom `nil`, on JavaScript this will be -/// `undefined`. -/// -pub fn nil() -> Dynamic { - cast(Nil) -} - -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -fn cast(a: anything) -> Dynamic diff --git a/build/packages/gleam_stdlib/src/gleam/dynamic/decode.gleam b/build/packages/gleam_stdlib/src/gleam/dynamic/decode.gleam deleted file mode 100644 index 03ee2ac..0000000 --- a/build/packages/gleam_stdlib/src/gleam/dynamic/decode.gleam +++ /dev/null @@ -1,1061 +0,0 @@ -//// The `Dynamic` type is used to represent dynamically typed data. That is, data -//// that we don't know the precise type of yet, so we need to introspect the data to -//// see if it is of the desired type before we can use it. Typically data like this -//// would come from user input or from untyped languages such as Erlang or JavaScript. -//// -//// This module provides the `Decoder` type and associated functions, which provides -//// a type-safe and composable way to convert dynamic data into some desired type, -//// or into errors if the data doesn't have the desired structure. -//// -//// The `Decoder` type is generic and has 1 type parameter, which is the type that -//// it attempts to decode. A `Decoder(String)` can be used to decode strings, and a -//// `Decoder(Option(Int))` can be used to decode `Option(Int)`s -//// -//// Decoders work using _runtime reflection_ and the data structures of the target -//// platform. Differences between Erlang and JavaScript data structures may impact -//// your decoders, so it is important to test your decoders on all supported -//// platforms. -//// -//// The decoding technique used by this module was inspired by Juraj Petráš' -//// [Toy](https://github.com/Hackder/toy), Go's `encoding/json`, and Elm's -//// `Json.Decode`. Thank you to them! -//// -//// # Examples -//// -//// Dynamic data may come from various sources and so many different syntaxes could -//// be used to describe or construct them. In these examples a pseudocode -//// syntax is used to describe the data. -//// -//// ## Simple types -//// -//// This module defines decoders for simple data types such as [`string`](#string), -//// [`int`](#int), [`float`](#float), [`bit_array`](#bit_array), and [`bool`](#bool). -//// -//// ```gleam -//// // Data: -//// // "Hello, Joe!" -//// -//// let result = decode.run(data, decode.string) -//// assert result == Ok("Hello, Joe!") -//// ``` -//// -//// ## Lists -//// -//// The [`list`](#list) decoder decodes `List`s. To use it you must construct it by -//// passing in another decoder into the `list` function, which is the decoder that -//// is to be used for the elements of the list, type checking both the list and its -//// elements. -//// -//// ```gleam -//// // Data: -//// // [1, 2, 3, 4] -//// -//// let result = decode.run(data, decode.list(decode.int)) -//// assert result == Ok([1, 2, 3, 4]) -//// ``` -//// -//// On Erlang this decoder can decode from lists, and on JavaScript it can -//// decode from lists as well as JavaScript arrays. -//// -//// ## Options -//// -//// The [`optional`](#optional) decoder is used to decode values that may or may not -//// be present. In other environment these might be called "nullable" values. -//// -//// Like the `list` decoder, the `optional` decoder takes another decoder, -//// which is used to decode the value if it is present. -//// -//// ```gleam -//// // Data: -//// // 12.45 -//// -//// let result = decode.run(data, decode.optional(decode.float)) -//// assert result == Ok(option.Some(12.45)) -//// ``` -//// ```gleam -//// // Data: -//// // null -//// -//// let result = decode.run(data, decode.optional(decode.int)) -//// assert result == Ok(option.None) -//// ``` -//// -//// This decoder knows how to handle multiple different runtime representations of -//// absent values, including `Nil`, `None`, `null`, and `undefined`. -//// -//// ## Dicts -//// -//// The [`dict`](#dict) decoder decodes `Dicts` and contains two other decoders, one -//// for the keys, one for the values. -//// -//// ```gleam -//// // Data: -//// // { "Lucy" -> 10, "Nubi" -> 20 } -//// -//// let result = decode.run(data, decode.dict(decode.string, decode.int)) -//// assert result == Ok(dict.from_list([ -//// #("Lucy", 10), -//// #("Nubi", 20), -//// ])) -//// ``` -//// -//// ## Indexing objects -//// -//// The [`at`](#at) decoder can be used to decode a value that is nested within -//// key-value containers such as Gleam dicts, Erlang maps, or JavaScript objects. -//// -//// ```gleam -//// // Data: -//// // { "one" -> { "two" -> 123 } } -//// -//// let result = decode.run(data, decode.at(["one", "two"], decode.int)) -//// assert result == Ok(123) -//// ``` -//// -//// ## Indexing arrays -//// -//// If you use ints as keys then the [`at`](#at) decoder can be used to index into -//// array-like containers such as Gleam or Erlang tuples, or JavaScript arrays. -//// -//// ```gleam -//// // Data: -//// // ["one", "two", "three"] -//// -//// let result = decode.run(data, decode.at([1], decode.string)) -//// assert result == Ok("two") -//// ``` -//// -//// ## Records -//// -//// Decoding records from dynamic data is more complex and requires combining a -//// decoder for each field and a special constructor that builds your records with -//// the decoded field values. -//// -//// ```gleam -//// // Data: -//// // { -//// // "score" -> 180, -//// // "name" -> "Mel Smith", -//// // "is-admin" -> false, -//// // "enrolled" -> true, -//// // "colour" -> "Red", -//// // } -//// -//// let decoder = { -//// use name <- decode.field("name", decode.string) -//// use score <- decode.field("score", decode.int) -//// use colour <- decode.field("colour", decode.string) -//// use enrolled <- decode.field("enrolled", decode.bool) -//// decode.success(Player(name:, score:, colour:, enrolled:)) -//// } -//// -//// let result = decode.run(data, decoder) -//// assert result == Ok(Player("Mel Smith", 180, "Red", True)) -//// ``` -//// -//// ## Enum variants -//// -//// Imagine you have a custom type where all the variants do not contain any values. -//// -//// ```gleam -//// pub type PocketMonsterType { -//// Fire -//// Water -//// Grass -//// Electric -//// } -//// ``` -//// -//// You might choose to encode these variants as strings, `"fire"` for `Fire`, -//// `"water"` for `Water`, and so on. To decode them you'll need to decode the dynamic -//// data as a string, but then you'll need to decode it further still as not all -//// strings are valid values for the enum. This can be done with the `then` -//// function, which enables running a second decoder after the first one -//// succeeds. -//// -//// ```gleam -//// let decoder = { -//// use decoded_string <- decode.then(decode.string) -//// case decoded_string { -//// // Return succeeding decoders for valid strings -//// "fire" -> decode.success(Fire) -//// "water" -> decode.success(Water) -//// "grass" -> decode.success(Grass) -//// "electric" -> decode.success(Electric) -//// // Return a failing decoder for any other strings -//// _ -> decode.failure(Fire, "PocketMonsterType") -//// } -//// } -//// -//// let result = decode.run(dynamic.string("water"), decoder) -//// assert result == Ok(Water) -//// -//// let result = decode.run(dynamic.string("wobble"), decoder) -//// assert result == Error([DecodeError("PocketMonsterType", "String", [])]) -//// ``` -//// -//// ## Record variants -//// -//// Decoding type variants that contain other values is done by combining the -//// techniques from the "enum variants" and "records" examples. Imagine you have -//// this custom type that you want to decode: -//// -//// ```gleam -//// pub type PocketMonsterPerson { -//// Trainer(name: String, badge_count: Int) -//// GymLeader(name: String, speciality: PocketMonsterType) -//// } -//// ``` -//// And you would like to be able to decode these from dynamic data like this: -//// ```erlang -//// { -//// "type" -> "trainer", -//// "name" -> "Ash", -//// "badge-count" -> 1, -//// } -//// ``` -//// ```erlang -//// { -//// "type" -> "gym-leader", -//// "name" -> "Misty", -//// "speciality" -> "water", -//// } -//// ``` -//// -//// Notice how both documents have a `"type"` field, which is used to indicate which -//// variant the data is for. -//// -//// First, define decoders for each of the variants: -//// -//// ```gleam -//// let trainer_decoder = { -//// use name <- decode.field("name", decode.string) -//// use badge_count <- decode.field("badge-count", decode.int) -//// decode.success(Trainer(name, badge_count)) -//// } -//// -//// let gym_leader_decoder = { -//// use name <- decode.field("name", decode.string) -//// use speciality <- decode.field("speciality", pocket_monster_type_decoder) -//// decode.success(GymLeader(name, speciality)) -//// } -//// ``` -//// -//// A third decoder can be used to extract and decode the `"type"` field, and the -//// expression can evaluate to whichever decoder is suitable for the document. -//// -//// ```gleam -//// // Data: -//// // { -//// // "type" -> "gym-leader", -//// // "name" -> "Misty", -//// // "speciality" -> "water", -//// // } -//// -//// let decoder = { -//// use tag <- decode.field("type", decode.string) -//// case tag { -//// "gym-leader" -> gym_leader_decoder -//// _ -> trainer_decoder -//// } -//// } -//// -//// let result = decode.run(data, decoder) -//// assert result == Ok(GymLeader("Misty", Water)) -//// ``` - -import gleam/bit_array -import gleam/dict.{type Dict} -import gleam/dynamic -import gleam/int -import gleam/list -import gleam/option.{type Option, None, Some} - -/// `Dynamic` data is data that we don't know the type of yet, originating from -/// external untyped systems. -/// -/// You should never be converting your well typed data to dynamic data. -/// -pub type Dynamic = - dynamic.Dynamic - -/// Error returned when unexpected data is encountered -/// -pub type DecodeError { - DecodeError(expected: String, found: String, path: List(String)) -} - -/// A decoder is a value that can be used to turn dynamically typed `Dynamic` -/// data into typed data using the `run` function. -/// -/// Several smaller decoders can be combined to make larger decoders using -/// functions such as `list` and `field`. -/// -pub opaque type Decoder(t) { - Decoder(function: fn(Dynamic) -> #(t, List(DecodeError))) -} - -/// The same as [`field`](#field), except taking a path to the value rather -/// than a field name. -/// -/// This function will index into dictionaries with any key type, and if the key is -/// an int then it'll also index into Erlang tuples and JavaScript arrays, and -/// the first eight elements of Gleam lists. -/// -/// # Examples -/// -/// ```gleam -/// let data = dynamic.properties([ -/// #(dynamic.string("data"), dynamic.properties([ -/// #(dynamic.string("email"), dynamic.string("lucy@example.com")), -/// #(dynamic.string("name"), dynamic.string("Lucy")), -/// ]) -/// ])) -/// -/// let decoder = { -/// use name <- decode.subfield(["data", "name"], decode.string) -/// use email <- decode.subfield(["data", "email"], decode.string) -/// decode.success(SignUp(name: name, email: email)) -/// } -/// let result = decode.run(data, decoder) -/// assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) -/// ``` -/// -pub fn subfield( - field_path: List(name), - field_decoder: Decoder(t), - next: fn(t) -> Decoder(final), -) -> Decoder(final) { - Decoder(function: fn(data) { - let #(out, errors1) = - index(field_path, [], field_decoder.function, data, fn(data, position) { - let #(default, _) = field_decoder.function(data) - #(default, [DecodeError("Field", "Nothing", [])]) - |> push_path(list.reverse(position)) - }) - let #(out, errors2) = next(out).function(data) - #(out, list.append(errors1, errors2)) - }) -} - -/// Run a decoder on a `Dynamic` value, decoding the value if it is of the -/// desired type, or returning errors. -/// -/// # Examples -/// -/// ```gleam -/// let decoder = { -/// use name <- decode.field("email", decode.string) -/// use email <- decode.field("password", decode.string) -/// decode.success(SignUp(name: name, email: email)) -/// } -/// -/// decode.run(data, decoder) -/// ``` -/// -pub fn run(data: Dynamic, decoder: Decoder(t)) -> Result(t, List(DecodeError)) { - let #(maybe_invalid_data, errors) = decoder.function(data) - case errors { - [] -> Ok(maybe_invalid_data) - [_, ..] -> Error(errors) - } -} - -/// A decoder that decodes a value that is nested within other values. For -/// example, decoding a value that is within some deeply nested JSON objects. -/// -/// This function will index into dictionaries with any key type, and if the key is -/// an int then it'll also index into Erlang tuples and JavaScript arrays, and -/// the first eight elements of Gleam lists. -/// -/// # Examples -/// -/// ```gleam -/// let decoder = decode.at(["one", "two"], decode.int) -/// -/// let data = dynamic.properties([ -/// #(dynamic.string("one"), dynamic.properties([ -/// #(dynamic.string("two"), dynamic.int(1000)), -/// ])), -/// ])) -/// -/// -/// decode.run(data, decoder) -/// // -> Ok(1000) -/// ``` -/// -/// ```gleam -/// dynamic.nil() -/// |> decode.run(decode.optional(decode.int)) -/// // -> Ok(option.None) -/// ``` -/// -pub fn at(path: List(segment), inner: Decoder(a)) -> Decoder(a) { - Decoder(function: fn(data) { - index(path, [], inner.function, data, fn(data, position) { - let #(default, _) = inner.function(data) - #(default, [DecodeError("Field", "Nothing", [])]) - |> push_path(list.reverse(position)) - }) - }) -} - -fn index( - path: List(a), - position: List(a), - inner: fn(Dynamic) -> #(b, List(DecodeError)), - data: Dynamic, - handle_miss: fn(Dynamic, List(a)) -> #(b, List(DecodeError)), -) -> #(b, List(DecodeError)) { - case path { - [] -> { - data - |> inner - |> push_path(list.reverse(position)) - } - - [key, ..path] -> { - case bare_index(data, key) { - Ok(Some(data)) -> { - index(path, [key, ..position], inner, data, handle_miss) - } - Ok(None) -> { - handle_miss(data, [key, ..position]) - } - Error(kind) -> { - let #(default, _) = inner(data) - #(default, [DecodeError(kind, dynamic.classify(data), [])]) - |> push_path(list.reverse(position)) - } - } - } - } -} - -@external(erlang, "gleam_stdlib", "index") -@external(javascript, "../../gleam_stdlib.mjs", "index") -fn bare_index(data: Dynamic, key: anything) -> Result(Option(Dynamic), String) - -fn push_path( - layer: #(t, List(DecodeError)), - path: List(key), -) -> #(t, List(DecodeError)) { - let decoder = one_of(string, [int |> map(int.to_string)]) - let path = - list.map(path, fn(key) { - let key = cast(key) - case run(key, decoder) { - Ok(key) -> key - Error(_) -> "<" <> dynamic.classify(key) <> ">" - } - }) - let errors = - list.map(layer.1, fn(error) { - DecodeError(..error, path: list.append(path, error.path)) - }) - #(layer.0, errors) -} - -/// Finalise a decoder having successfully extracted a value. -/// -/// # Examples -/// -/// ```gleam -/// let data = dynamic.properties([ -/// #(dynamic.string("email"), dynamic.string("lucy@example.com")), -/// #(dynamic.string("name"), dynamic.string("Lucy")), -/// ])) -/// -/// let decoder = { -/// use name <- decode.field("name", string) -/// use email <- decode.field("email", string) -/// decode.success(SignUp(name: name, email: email)) -/// } -/// -/// let result = decode.run(data, decoder) -/// assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) -/// ``` -/// -pub fn success(data: t) -> Decoder(t) { - Decoder(function: fn(_) { #(data, []) }) -} - -/// Construct a decode error for some unexpected dynamic data. -/// -pub fn decode_error( - expected expected: String, - found found: Dynamic, -) -> List(DecodeError) { - [DecodeError(expected: expected, found: dynamic.classify(found), path: [])] -} - -/// Run a decoder on a field of a `Dynamic` value, decoding the value if it is -/// of the desired type, or returning errors. An error is returned if there is -/// no field for the specified key. -/// -/// This function will index into dictionaries with any key type, and if the key is -/// an int then it'll also index into Erlang tuples and JavaScript arrays, and -/// the first eight elements of Gleam lists. -/// -/// # Examples -/// -/// ```gleam -/// let data = dynamic.properties([ -/// #(dynamic.string("email"), dynamic.string("lucy@example.com")), -/// #(dynamic.string("name"), dynamic.string("Lucy")), -/// ])) -/// -/// let decoder = { -/// use name <- decode.field("name", string) -/// use email <- decode.field("email", string) -/// decode.success(SignUp(name: name, email: email)) -/// } -/// -/// let result = decode.run(data, decoder) -/// assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) -/// ``` -/// -/// If you wish to decode a value that is more deeply nested within the dynamic -/// data, see [`subfield`](#subfield) and [`at`](#at). -/// -/// If you wish to return a default in the event that a field is not present, -/// see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at). -/// -pub fn field( - field_name: name, - field_decoder: Decoder(t), - next: fn(t) -> Decoder(final), -) -> Decoder(final) { - subfield([field_name], field_decoder, next) -} - -/// Run a decoder on a field of a `Dynamic` value, decoding the value if it is -/// of the desired type, or returning errors. The given default value is -/// returned if there is no field for the specified key. -/// -/// This function will index into dictionaries with any key type, and if the key is -/// an int then it'll also index into Erlang tuples and JavaScript arrays, and -/// the first eight elements of Gleam lists. -/// -/// # Examples -/// -/// ```gleam -/// let data = dynamic.properties([ -/// #(dynamic.string("name"), dynamic.string("Lucy")), -/// ])) -/// -/// let decoder = { -/// use name <- decode.field("name", string) -/// use email <- decode.optional_field("email", "n/a", string) -/// decode.success(SignUp(name: name, email: email)) -/// } -/// -/// let result = decode.run(data, decoder) -/// assert result == Ok(SignUp(name: "Lucy", email: "n/a")) -/// ``` -/// -pub fn optional_field( - key: name, - default: t, - field_decoder: Decoder(t), - next: fn(t) -> Decoder(final), -) -> Decoder(final) { - Decoder(function: fn(data) { - let #(out, errors1) = - case bare_index(data, key) { - Ok(Some(data)) -> field_decoder.function(data) - Ok(None) -> #(default, []) - Error(kind) -> #(default, [ - DecodeError(kind, dynamic.classify(data), []), - ]) - } - |> push_path([key]) - let #(out, errors2) = next(out).function(data) - #(out, list.append(errors1, errors2)) - }) -} - -/// A decoder that decodes a value that is nested within other values. For -/// example, decoding a value that is within some deeply nested JSON objects. -/// -/// This function will index into dictionaries with any key type, and if the key is -/// an int then it'll also index into Erlang tuples and JavaScript arrays, and -/// the first eight elements of Gleam lists. -/// -/// # Examples -/// -/// ```gleam -/// let decoder = decode.optionally_at(["one", "two"], 100, decode.int) -/// -/// let data = dynamic.properties([ -/// #(dynamic.string("one"), dynamic.properties([])), -/// ])) -/// -/// -/// decode.run(data, decoder) -/// // -> Ok(100) -/// ``` -/// -pub fn optionally_at( - path: List(segment), - default: a, - inner: Decoder(a), -) -> Decoder(a) { - Decoder(function: fn(data) { - index(path, [], inner.function, data, fn(_, _) { #(default, []) }) - }) -} - -fn run_dynamic_function( - data: Dynamic, - name: String, - f: fn(Dynamic) -> Result(t, t), -) -> #(t, List(DecodeError)) { - case f(data) { - Ok(data) -> #(data, []) - Error(zero) -> #(zero, [DecodeError(name, dynamic.classify(data), [])]) - } -} - -/// A decoder that decodes `String` values. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.string("Hello!"), decode.string) -/// assert result == Ok("Hello!") -/// ``` -/// -pub const string: Decoder(String) = Decoder(decode_string) - -fn decode_string(data: Dynamic) -> #(String, List(DecodeError)) { - run_dynamic_function(data, "String", dynamic_string) -} - -@external(javascript, "../../gleam_stdlib.mjs", "string") -fn dynamic_string(from data: Dynamic) -> Result(String, String) { - case dynamic_bit_array(data) { - Ok(data) -> - case bit_array.to_string(data) { - Ok(string) -> Ok(string) - Error(_) -> Error("") - } - Error(_) -> Error("") - } -} - -/// A decoder that decodes `Bool` values. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.bool(True), decode.bool) -/// assert result == Ok(True) -/// ``` -/// -pub const bool: Decoder(Bool) = Decoder(decode_bool) - -fn decode_bool(data: Dynamic) -> #(Bool, List(DecodeError)) { - case cast(True) == data { - True -> #(True, []) - False -> - case cast(False) == data { - True -> #(False, []) - False -> #(False, decode_error("Bool", data)) - } - } -} - -/// A decoder that decodes `Int` values. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.int(147), decode.int) -/// assert result == Ok(147) -/// ``` -/// -pub const int: Decoder(Int) = Decoder(decode_int) - -fn decode_int(data: Dynamic) -> #(Int, List(DecodeError)) { - run_dynamic_function(data, "Int", dynamic_int) -} - -@external(erlang, "gleam_stdlib", "int") -@external(javascript, "../../gleam_stdlib.mjs", "int") -fn dynamic_int(data: Dynamic) -> Result(Int, Int) - -/// A decoder that decodes `Float` values. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.float(3.14), decode.float) -/// assert result == Ok(3.14) -/// ``` -/// -pub const float: Decoder(Float) = Decoder(decode_float) - -fn decode_float(data: Dynamic) -> #(Float, List(DecodeError)) { - run_dynamic_function(data, "Float", dynamic_float) -} - -@external(erlang, "gleam_stdlib", "float") -@external(javascript, "../../gleam_stdlib.mjs", "float") -fn dynamic_float(data: Dynamic) -> Result(Float, Float) - -/// A decoder that decodes `Dynamic` values. This decoder never returns an error. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.float(3.14), decode.dynamic) -/// assert result == Ok(dynamic.float(3.14)) -/// ``` -/// -pub const dynamic: Decoder(Dynamic) = Decoder(decode_dynamic) - -fn decode_dynamic(data: Dynamic) -> #(Dynamic, List(DecodeError)) { - #(data, []) -} - -/// A decoder that decodes `BitArray` values. This decoder never returns an error. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.bit_array(<<5, 7>>), decode.bit_array) -/// assert result == Ok(<<5, 7>>) -/// ``` -/// -pub const bit_array: Decoder(BitArray) = Decoder(decode_bit_array) - -fn decode_bit_array(data: Dynamic) -> #(BitArray, List(DecodeError)) { - run_dynamic_function(data, "BitArray", dynamic_bit_array) -} - -@external(erlang, "gleam_stdlib", "bit_array") -@external(javascript, "../../gleam_stdlib.mjs", "bit_array") -fn dynamic_bit_array(data: Dynamic) -> Result(BitArray, BitArray) - -/// A decoder that decodes lists where all elements are decoded with a given -/// decoder. -/// -/// # Examples -/// -/// ```gleam -/// let result = -/// [1, 2, 3] -/// |> list.map(dynamic.int) -/// |> dynamic.list -/// |> decode.run(decode.list(of: decode.int)) -/// assert result == Ok([1, 2, 3]) -/// ``` -/// -pub fn list(of inner: Decoder(a)) -> Decoder(List(a)) { - Decoder(fn(data) { - decode_list(data, inner.function, fn(p, k) { push_path(p, [k]) }, 0, []) - }) -} - -@external(erlang, "gleam_stdlib", "list") -@external(javascript, "../../gleam_stdlib.mjs", "list") -fn decode_list( - data: Dynamic, - item: fn(Dynamic) -> #(t, List(DecodeError)), - push_path: fn(#(t, List(DecodeError)), key) -> #(t, List(DecodeError)), - index: Int, - acc: List(t), -) -> #(List(t), List(DecodeError)) - -/// A decoder that decodes dicts where all keys and vales are decoded with -/// given decoders. -/// -/// # Examples -/// -/// ```gleam -/// let values = dynamic.properties([ -/// #(dynamic.string("one"), dynamic.int(1)), -/// #(dynamic.string("two"), dynamic.int(2)), -/// ]) -/// -/// let result = -/// decode.run(values, decode.dict(decode.string, decode.int)) -/// assert result == Ok(values) -/// ``` -/// -pub fn dict( - key: Decoder(key), - value: Decoder(value), -) -> Decoder(Dict(key, value)) { - Decoder(fn(data) { - case decode_dict(data) { - Error(_) -> #(dict.new(), decode_error("Dict", data)) - Ok(dict) -> - dict.fold(dict, #(dict.new(), []), fn(a, k, v) { - // If there are any errors from previous key-value pairs then we - // don't need to run the decoders, instead return the existing acc. - case a.1 { - [] -> fold_dict(a, k, v, key.function, value.function) - [_, ..] -> a - } - }) - } - }) -} - -fn fold_dict( - acc: #(Dict(k, v), List(DecodeError)), - key: Dynamic, - value: Dynamic, - key_decoder: fn(Dynamic) -> #(k, List(DecodeError)), - value_decoder: fn(Dynamic) -> #(v, List(DecodeError)), -) -> #(Dict(k, v), List(DecodeError)) { - // First we decode the key. - case key_decoder(key) { - #(key, []) -> - // Then we decode the value. - case value_decoder(value) { - #(value, []) -> { - // It worked! Insert the new key-value pair so we can move onto the next. - let dict = dict.insert(acc.0, key, value) - #(dict, acc.1) - } - #(_, errors) -> push_path(#(dict.new(), errors), ["values"]) - } - #(_, errors) -> push_path(#(dict.new(), errors), ["keys"]) - } -} - -@external(erlang, "gleam_stdlib", "dict") -@external(javascript, "../../gleam_stdlib.mjs", "dict") -fn decode_dict(data: Dynamic) -> Result(Dict(Dynamic, Dynamic), Nil) - -/// A decoder that decodes nullable values of a type decoded by with a given -/// decoder. -/// -/// This function can handle common representations of null on all runtimes, such as -/// `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on -/// JavaScript. -/// -/// # Examples -/// -/// ```gleam -/// let result = decode.run(dynamic.int(100), decode.optional(decode.int)) -/// assert result == Ok(option.Some(100)) -/// ``` -/// -/// ```gleam -/// let result = decode.run(dynamic.nil(), decode.optional(decode.int)) -/// assert result == Ok(option.None) -/// ``` -/// -pub fn optional(inner: Decoder(a)) -> Decoder(Option(a)) { - Decoder(function: fn(data) { - case is_null(data) { - True -> #(option.None, []) - False -> { - let #(data, errors) = inner.function(data) - #(option.Some(data), errors) - } - } - }) -} - -/// Apply a transformation function to any value decoded by the decoder. -/// -/// # Examples -/// -/// ```gleam -/// let decoder = decode.int |> decode.map(int.to_string) -/// let result = decode.run(dynamic.int(1000), decoder) -/// assert result == Ok("1000") -/// ``` -/// -pub fn map(decoder: Decoder(a), transformer: fn(a) -> b) -> Decoder(b) { - Decoder(function: fn(d) { - let #(data, errors) = decoder.function(d) - #(transformer(data), errors) - }) -} - -/// Apply a transformation function to any errors returned by the decoder. -/// -pub fn map_errors( - decoder: Decoder(a), - transformer: fn(List(DecodeError)) -> List(DecodeError), -) -> Decoder(a) { - Decoder(function: fn(d) { - let #(data, errors) = decoder.function(d) - #(data, transformer(errors)) - }) -} - -/// Replace all errors produced by a decoder with one single error for a named -/// expected type. -/// -/// This function may be useful if you wish to simplify errors before -/// presenting them to a user, particularly when using the `one_of` function. -/// -/// # Examples -/// -/// ```gleam -/// let decoder = decode.string |> decode.collapse_errors("MyThing") -/// let result = decode.run(dynamic.int(1000), decoder) -/// assert result == Error([DecodeError("MyThing", "Int", [])]) -/// ``` -/// -pub fn collapse_errors(decoder: Decoder(a), name: String) -> Decoder(a) { - Decoder(function: fn(dynamic_data) { - let #(data, errors) as layer = decoder.function(dynamic_data) - case errors { - [] -> layer - [_, ..] -> #(data, decode_error(name, dynamic_data)) - } - }) -} - -/// Create a new decoder based upon the value of a previous decoder. -/// -/// This may be useful to run one previous decoder to use in further decoding. -/// -pub fn then(decoder: Decoder(a), next: fn(a) -> Decoder(b)) -> Decoder(b) { - Decoder(function: fn(dynamic_data) { - let #(data, errors) = decoder.function(dynamic_data) - let decoder = next(data) - let #(data, _) as layer = decoder.function(dynamic_data) - case errors { - [] -> layer - [_, ..] -> #(data, errors) - } - }) -} - -/// Create a new decoder from several other decoders. Each of the inner -/// decoders is run in turn, and the value from the first to succeed is used. -/// -/// If no decoder succeeds then the errors from the first decoder is used. -/// If you wish for different errors then you may wish to use the -/// `collapse_errors` or `map_errors` functions. -/// -/// # Examples -/// -/// ```gleam -/// let decoder = decode.one_of(decode.string, or: [ -/// decode.int |> decode.map(int.to_string), -/// decode.float |> decode.map(float.to_string), -/// ]) -/// decode.run(dynamic.int(1000), decoder) -/// // -> Ok("1000") -/// ``` -/// -pub fn one_of( - first: Decoder(a), - or alternatives: List(Decoder(a)), -) -> Decoder(a) { - Decoder(function: fn(dynamic_data) { - let #(_, errors) as layer = first.function(dynamic_data) - case errors { - [] -> layer - [_, ..] -> run_decoders(dynamic_data, layer, alternatives) - } - }) -} - -fn run_decoders( - data: Dynamic, - failure: #(a, List(DecodeError)), - decoders: List(Decoder(a)), -) -> #(a, List(DecodeError)) { - case decoders { - [] -> failure - - [decoder, ..decoders] -> { - let #(_, errors) as layer = decoder.function(data) - case errors { - [] -> layer - [_, ..] -> run_decoders(data, failure, decoders) - } - } - } -} - -/// Define a decoder that always fails. The parameter for this function is the -/// name of the type that has failed to decode. -/// -pub fn failure(zero: a, expected: String) -> Decoder(a) { - Decoder(function: fn(d) { #(zero, decode_error(expected, d)) }) -} - -/// Create a decoder for a new data type from a decoding function. -/// -/// This function is used for new primitive types. For example, you might -/// define a decoder for Erlang's pid type. -/// -/// A default "zero" value is also required to make a decoder. When this -/// decoder is used as part of a larger decoder this zero value used as -/// a placeholder so that the rest of the decoder can continue to run and -/// collect all decoding errors. -/// -/// If you were to make a decoder for the `String` type (rather than using the -/// build-in `string` decoder) you would define it like so: -/// -/// ```gleam -/// pub fn string_decoder() -> decode.Decoder(String) { -/// let default = "" -/// decode.new_primitive_decoder("String", fn(data) { -/// case dynamic.string(data) { -/// Ok(x) -> Ok(x) -/// Error(_) -> Error(default) -/// } -/// }) -/// } -/// ``` -/// -pub fn new_primitive_decoder( - name: String, - decoding_function: fn(Dynamic) -> Result(t, t), -) -> Decoder(t) { - Decoder(function: fn(d) { - case decoding_function(d) { - Ok(t) -> #(t, []) - Error(zero) -> #(zero, [DecodeError(name, dynamic.classify(d), [])]) - } - }) -} - -/// Create a decoder that can refer to itself, useful for decoding deeply -/// nested data. -/// -/// Attempting to create a recursive decoder without this function could result -/// in an infinite loop. If you are using `field` or other `use`able functions -/// then you may not need to use this function. -/// -/// ```gleam -/// type Nested { -/// Nested(List(Nested)) -/// Value(String) -/// } -/// -/// fn nested_decoder() -> decode.Decoder(Nested) { -/// use <- decode.recursive -/// decode.one_of(decode.string |> decode.map(Value), [ -/// decode.list(nested_decoder()) |> decode.map(Nested), -/// ]) -/// } -/// ``` -/// -pub fn recursive(inner: fn() -> Decoder(a)) -> Decoder(a) { - Decoder(function: fn(data) { - let decoder = inner() - decoder.function(data) - }) -} - -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../../gleam_stdlib.mjs", "identity") -fn cast(a: anything) -> Dynamic - -@external(erlang, "gleam_stdlib", "is_null") -@external(javascript, "../../gleam_stdlib.mjs", "is_null") -fn is_null(a: Dynamic) -> Bool diff --git a/build/packages/gleam_stdlib/src/gleam/float.gleam b/build/packages/gleam_stdlib/src/gleam/float.gleam deleted file mode 100644 index 83bfa6e..0000000 --- a/build/packages/gleam_stdlib/src/gleam/float.gleam +++ /dev/null @@ -1,661 +0,0 @@ -//// Functions for working with floats. -//// -//// ## Float representation -//// -//// Floats are represented as 64 bit floating point numbers on both the Erlang -//// and JavaScript runtimes. The floating point behaviour is native to their -//// respective runtimes, so their exact behaviour will be slightly different on -//// the two runtimes. -//// -//// ### Infinity and NaN -//// -//// Under the JavaScript runtime, exceeding the maximum (or minimum) -//// representable value for a floating point value will result in Infinity (or -//// -Infinity). Should you try to divide two infinities you will get NaN as a -//// result. -//// -//// When running on BEAM, exceeding the maximum (or minimum) representable -//// value for a floating point value will raise an error. -//// -//// ## Division by zero -//// -//// Gleam runs on the Erlang virtual machine, which does not follow the IEEE -//// 754 standard for floating point arithmetic and does not have an `Infinity` -//// value. In Erlang division by zero results in a crash, however Gleam does -//// not have partial functions and operators in core so instead division by zero -//// returns zero, a behaviour taken from Pony, Coq, and Lean. -//// -//// This may seem unexpected at first, but it is no less mathematically valid -//// than crashing or returning a special value. Division by zero is undefined -//// in mathematics. - -import gleam/order.{type Order} - -/// Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was -/// not possible. -/// -/// ## Examples -/// -/// ```gleam -/// parse("2.3") -/// // -> Ok(2.3) -/// ``` -/// -/// ```gleam -/// parse("ABC") -/// // -> Error(Nil) -/// ``` -/// -@external(erlang, "gleam_stdlib", "parse_float") -@external(javascript, "../gleam_stdlib.mjs", "parse_float") -pub fn parse(string: String) -> Result(Float, Nil) - -/// Returns the string representation of the provided `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// to_string(2.3) -/// // -> "2.3" -/// ``` -/// -@external(erlang, "gleam_stdlib", "float_to_string") -@external(javascript, "../gleam_stdlib.mjs", "float_to_string") -pub fn to_string(x: Float) -> String - -/// Restricts a `Float` between a lower and upper bound. -/// -/// ## Examples -/// -/// ```gleam -/// clamp(1.2, min: 1.4, max: 1.6) -/// // -> 1.4 -/// ``` -/// -pub fn clamp(x: Float, min min_bound: Float, max max_bound: Float) -> Float { - x - |> min(max_bound) - |> max(min_bound) -} - -/// Compares two `Float`s, returning an `Order`: -/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. -/// -/// ## Examples -/// -/// ```gleam -/// compare(2.0, 2.3) -/// // -> Lt -/// ``` -/// -/// To handle -/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) -/// you may use [`loosely_compare`](#loosely_compare) instead. -/// -pub fn compare(a: Float, with b: Float) -> Order { - case a == b { - True -> order.Eq - False -> - case a <. b { - True -> order.Lt - False -> order.Gt - } - } -} - -/// Compares two `Float`s within a tolerance, returning an `Order`: -/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. -/// -/// This function allows Float comparison while handling -/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). -/// -/// Notice: For `Float`s the tolerance won't be exact: -/// `5.3 - 5.0` is not exactly `0.3`. -/// -/// ## Examples -/// -/// ```gleam -/// loosely_compare(5.0, with: 5.3, tolerating: 0.5) -/// // -> Eq -/// ``` -/// -/// If you want to check only for equality you may use -/// [`loosely_equals`](#loosely_equals) instead. -/// -pub fn loosely_compare( - a: Float, - with b: Float, - tolerating tolerance: Float, -) -> Order { - let difference = absolute_value(a -. b) - case difference <=. tolerance { - True -> order.Eq - False -> compare(a, b) - } -} - -/// Checks for equality of two `Float`s within a tolerance, -/// returning an `Bool`. -/// -/// This function allows Float comparison while handling -/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). -/// -/// Notice: For `Float`s the tolerance won't be exact: -/// `5.3 - 5.0` is not exactly `0.3`. -/// -/// ## Examples -/// -/// ```gleam -/// loosely_equals(5.0, with: 5.3, tolerating: 0.5) -/// // -> True -/// ``` -/// -/// ```gleam -/// loosely_equals(5.0, with: 5.1, tolerating: 0.1) -/// // -> False -/// ``` -/// -pub fn loosely_equals( - a: Float, - with b: Float, - tolerating tolerance: Float, -) -> Bool { - let difference = absolute_value(a -. b) - difference <=. tolerance -} - -/// Compares two `Float`s, returning the smaller of the two. -/// -/// ## Examples -/// -/// ```gleam -/// min(2.0, 2.3) -/// // -> 2.0 -/// ``` -/// -pub fn min(a: Float, b: Float) -> Float { - case a <. b { - True -> a - False -> b - } -} - -/// Compares two `Float`s, returning the larger of the two. -/// -/// ## Examples -/// -/// ```gleam -/// max(2.0, 2.3) -/// // -> 2.3 -/// ``` -/// -pub fn max(a: Float, b: Float) -> Float { - case a >. b { - True -> a - False -> b - } -} - -/// Rounds the value to the next highest whole number as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// ceiling(2.3) -/// // -> 3.0 -/// ``` -/// -@external(erlang, "math", "ceil") -@external(javascript, "../gleam_stdlib.mjs", "ceiling") -pub fn ceiling(x: Float) -> Float - -/// Rounds the value to the next lowest whole number as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// floor(2.3) -/// // -> 2.0 -/// ``` -/// -@external(erlang, "math", "floor") -@external(javascript, "../gleam_stdlib.mjs", "floor") -pub fn floor(x: Float) -> Float - -/// Rounds the value to the nearest whole number as an `Int`. -/// -/// ## Examples -/// -/// ```gleam -/// round(2.3) -/// // -> 2 -/// ``` -/// -/// ```gleam -/// round(2.5) -/// // -> 3 -/// ``` -/// -@external(erlang, "erlang", "round") -pub fn round(x: Float) -> Int { - case x >=. 0.0 { - True -> js_round(x) - False -> 0 - js_round(negate(x)) - } -} - -@external(javascript, "../gleam_stdlib.mjs", "round") -fn js_round(a: Float) -> Int - -/// Returns the value as an `Int`, truncating all decimal digits. -/// -/// ## Examples -/// -/// ```gleam -/// truncate(2.4343434847383438) -/// // -> 2 -/// ``` -/// -@external(erlang, "erlang", "trunc") -@external(javascript, "../gleam_stdlib.mjs", "truncate") -pub fn truncate(x: Float) -> Int - -/// Converts the value to a given precision as a `Float`. -/// The precision is the number of allowed decimal places. -/// Negative precisions are allowed and force rounding -/// to the nearest tenth, hundredth, thousandth etc. -/// -/// ## Examples -/// -/// ```gleam -/// to_precision(2.43434348473, precision: 2) -/// // -> 2.43 -/// ``` -/// -/// ```gleam -/// to_precision(547890.453444, precision: -3) -/// // -> 548000.0 -/// ``` -/// -pub fn to_precision(x: Float, precision: Int) -> Float { - case precision <= 0 { - True -> { - let factor = do_power(10.0, do_to_float(-precision)) - do_to_float(round(x /. factor)) *. factor - } - False -> { - let factor = do_power(10.0, do_to_float(precision)) - do_to_float(round(x *. factor)) /. factor - } - } -} - -@external(erlang, "erlang", "float") -@external(javascript, "../gleam_stdlib.mjs", "identity") -fn do_to_float(a: Int) -> Float - -/// Returns the absolute value of the input as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// absolute_value(-12.5) -/// // -> 12.5 -/// ``` -/// -/// ```gleam -/// absolute_value(10.2) -/// // -> 10.2 -/// ``` -/// -pub fn absolute_value(x: Float) -> Float { - case x >=. 0.0 { - True -> x - False -> 0.0 -. x - } -} - -/// Returns the results of the base being raised to the power of the -/// exponent, as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// power(2.0, -1.0) -/// // -> Ok(0.5) -/// ``` -/// -/// ```gleam -/// power(2.0, 2.0) -/// // -> Ok(4.0) -/// ``` -/// -/// ```gleam -/// power(8.0, 1.5) -/// // -> Ok(22.627416997969522) -/// ``` -/// -/// ```gleam -/// 4.0 |> power(of: 2.0) -/// // -> Ok(16.0) -/// ``` -/// -/// ```gleam -/// power(-1.0, 0.5) -/// // -> Error(Nil) -/// ``` -/// -pub fn power(base: Float, of exponent: Float) -> Result(Float, Nil) { - let fractional: Bool = ceiling(exponent) -. exponent >. 0.0 - // In the following check: - // 1. If the base is negative and the exponent is fractional then - // return an error as it will otherwise be an imaginary number - // 2. If the base is 0 and the exponent is negative then the expression - // is equivalent to the exponent divided by 0 and an error should be - // returned - case base <. 0.0 && fractional || base == 0.0 && exponent <. 0.0 { - True -> Error(Nil) - False -> Ok(do_power(base, exponent)) - } -} - -@external(erlang, "math", "pow") -@external(javascript, "../gleam_stdlib.mjs", "power") -fn do_power(a: Float, b: Float) -> Float - -/// Returns the square root of the input as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// square_root(4.0) -/// // -> Ok(2.0) -/// ``` -/// -/// ```gleam -/// square_root(-16.0) -/// // -> Error(Nil) -/// ``` -/// -pub fn square_root(x: Float) -> Result(Float, Nil) { - power(x, 0.5) -} - -/// Returns the negative of the value provided. -/// -/// ## Examples -/// -/// ```gleam -/// negate(1.0) -/// // -> -1.0 -/// ``` -/// -pub fn negate(x: Float) -> Float { - -1.0 *. x -} - -/// Sums a list of `Float`s. -/// -/// ## Example -/// -/// ```gleam -/// sum([1.0, 2.2, 3.3]) -/// // -> 6.5 -/// ``` -/// -pub fn sum(numbers: List(Float)) -> Float { - sum_loop(numbers, 0.0) -} - -fn sum_loop(numbers: List(Float), initial: Float) -> Float { - case numbers { - [first, ..rest] -> sum_loop(rest, first +. initial) - [] -> initial - } -} - -/// Multiplies a list of `Float`s and returns the product. -/// -/// ## Example -/// -/// ```gleam -/// product([2.5, 3.2, 4.2]) -/// // -> 33.6 -/// ``` -/// -pub fn product(numbers: List(Float)) -> Float { - product_loop(numbers, 1.0) -} - -fn product_loop(numbers: List(Float), initial: Float) -> Float { - case numbers { - [first, ..rest] -> product_loop(rest, first *. initial) - [] -> initial - } -} - -/// Generates a random float between the given zero (inclusive) and one -/// (exclusive). -/// -/// On Erlang this updates the random state in the process dictionary. -/// See: -/// -/// ## Examples -/// -/// ```gleam -/// random() -/// // -> 0.646355926896028 -/// ``` -/// -@external(erlang, "rand", "uniform") -@external(javascript, "../gleam_stdlib.mjs", "random_uniform") -pub fn random() -> Float - -/// Computes the modulo of an float division of inputs as a `Result`. -/// -/// Returns division of the inputs as a `Result`: If the given divisor equals -/// `0`, this function returns an `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// modulo(13.3, by: 3.3) -/// // -> Ok(0.1) -/// ``` -/// -/// ```gleam -/// modulo(-13.3, by: 3.3) -/// // -> Ok(3.2) -/// ``` -/// -/// ```gleam -/// modulo(13.3, by: -3.3) -/// // -> Ok(-3.2) -/// ``` -/// -/// ```gleam -/// modulo(-13.3, by: -3.3) -/// // -> Ok(-0.1) -/// ``` -/// -pub fn modulo(dividend: Float, by divisor: Float) -> Result(Float, Nil) { - case divisor { - 0.0 -> Error(Nil) - _ -> Ok(dividend -. floor(dividend /. divisor) *. divisor) - } -} - -/// Returns division of the inputs as a `Result`. -/// -/// ## Examples -/// -/// ```gleam -/// divide(0.0, 1.0) -/// // -> Ok(0.0) -/// ``` -/// -/// ```gleam -/// divide(1.0, 0.0) -/// // -> Error(Nil) -/// ``` -/// -pub fn divide(a: Float, by b: Float) -> Result(Float, Nil) { - case b { - 0.0 -> Error(Nil) - b -> Ok(a /. b) - } -} - -/// Adds two floats together. -/// -/// It's the function equivalent of the `+.` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// add(1.0, 2.0) -/// // -> 3.0 -/// ``` -/// -/// ```gleam -/// import gleam/list -/// -/// list.fold([1.0, 2.0, 3.0], 0.0, add) -/// // -> 6.0 -/// ``` -/// -/// ```gleam -/// 3.0 |> add(2.0) -/// // -> 5.0 -/// ``` -/// -pub fn add(a: Float, b: Float) -> Float { - a +. b -} - -/// Multiplies two floats together. -/// -/// It's the function equivalent of the `*.` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// multiply(2.0, 4.0) -/// // -> 8.0 -/// ``` -/// -/// ```gleam -/// import gleam/list -/// -/// list.fold([2.0, 3.0, 4.0], 1.0, multiply) -/// // -> 24.0 -/// ``` -/// -/// ```gleam -/// 3.0 |> multiply(2.0) -/// // -> 6.0 -/// ``` -/// -pub fn multiply(a: Float, b: Float) -> Float { - a *. b -} - -/// Subtracts one float from another. -/// -/// It's the function equivalent of the `-.` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// subtract(3.0, 1.0) -/// // -> 2.0 -/// ``` -/// -/// ```gleam -/// import gleam/list -/// -/// list.fold([1.0, 2.0, 3.0], 10.0, subtract) -/// // -> 4.0 -/// ``` -/// -/// ```gleam -/// 3.0 |> subtract(_, 2.0) -/// // -> 1.0 -/// ``` -/// -/// ```gleam -/// 3.0 |> subtract(2.0, _) -/// // -> -1.0 -/// ``` -/// -pub fn subtract(a: Float, b: Float) -> Float { - a -. b -} - -/// Returns the natural logarithm (base e) of the given as a `Result`. If the -/// input is less than or equal to 0, returns `Error(Nil)`. -/// -/// ## Examples -/// -/// ```gleam -/// logarithm(1.0) -/// // -> Ok(0.0) -/// ``` -/// -/// ```gleam -/// logarithm(2.718281828459045) // e -/// // -> Ok(1.0) -/// ``` -/// -/// ```gleam -/// logarithm(0.0) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// logarithm(-1.0) -/// // -> Error(Nil) -/// ``` -/// -pub fn logarithm(x: Float) -> Result(Float, Nil) { - // In the following check: - // 1. If x is negative then return an error as the natural logarithm - // of a negative number is undefined (would be a complex number) - // 2. If x is 0 then return an error as the natural logarithm of 0 - // approaches negative infinity - case x <=. 0.0 { - True -> Error(Nil) - False -> Ok(do_log(x)) - } -} - -@external(erlang, "math", "log") -@external(javascript, "../gleam_stdlib.mjs", "log") -fn do_log(x: Float) -> Float - -/// Returns e (Euler's number) raised to the power of the given exponent, as -/// a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// exponential(0.0) -/// // -> Ok(1.0) -/// ``` -/// -/// ```gleam -/// exponential(1.0) -/// // -> Ok(2.718281828459045) -/// ``` -/// -/// ```gleam -/// exponential(-1.0) -/// // -> Ok(0.36787944117144233) -/// ``` -/// -@external(erlang, "math", "exp") -@external(javascript, "../gleam_stdlib.mjs", "exp") -pub fn exponential(x: Float) -> Float diff --git a/build/packages/gleam_stdlib/src/gleam/function.gleam b/build/packages/gleam_stdlib/src/gleam/function.gleam deleted file mode 100644 index 6ae3a62..0000000 --- a/build/packages/gleam_stdlib/src/gleam/function.gleam +++ /dev/null @@ -1,15 +0,0 @@ -/// Takes a single argument and always returns its input value. -/// -pub fn identity(x: a) -> a { - x -} - -/// Takes an argument and a single function, calls that function with that -/// argument and returns that argument instead of the function return value. -/// -/// Useful for running synchronous side effects in a pipeline. -/// -pub fn tap(arg: a, effect: fn(a) -> b) -> a { - effect(arg) - arg -} diff --git a/build/packages/gleam_stdlib/src/gleam/int.gleam b/build/packages/gleam_stdlib/src/gleam/int.gleam deleted file mode 100644 index fa8aaef..0000000 --- a/build/packages/gleam_stdlib/src/gleam/int.gleam +++ /dev/null @@ -1,828 +0,0 @@ -//// Functions for working with integers. -//// -//// ## Division by zero -//// -//// In Erlang division by zero results in a crash, however Gleam does not have -//// partial functions and operators in core so instead division by zero returns -//// zero, a behaviour taken from Pony, Coq, and Lean. -//// -//// This may seem unexpected at first, but it is no less mathematically valid -//// than crashing or returning a special value. Division by zero is undefined -//// in mathematics. - -import gleam/float -import gleam/order.{type Order} - -/// Returns the absolute value of the input. -/// -/// ## Examples -/// -/// ```gleam -/// absolute_value(-12) -/// // -> 12 -/// ``` -/// -/// ```gleam -/// absolute_value(10) -/// // -> 10 -/// ``` -/// -pub fn absolute_value(x: Int) -> Int { - case x >= 0 { - True -> x - False -> x * -1 - } -} - -/// Returns the results of the base being raised to the power of the -/// exponent, as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// power(2, -1.0) -/// // -> Ok(0.5) -/// ``` -/// -/// ```gleam -/// power(2, 2.0) -/// // -> Ok(4.0) -/// ``` -/// -/// ```gleam -/// power(8, 1.5) -/// // -> Ok(22.627416997969522) -/// ``` -/// -/// ```gleam -/// 4 |> power(of: 2.0) -/// // -> Ok(16.0) -/// ``` -/// -/// ```gleam -/// power(-1, 0.5) -/// // -> Error(Nil) -/// ``` -/// -pub fn power(base: Int, of exponent: Float) -> Result(Float, Nil) { - base - |> to_float - |> float.power(exponent) -} - -/// Returns the square root of the input as a `Float`. -/// -/// ## Examples -/// -/// ```gleam -/// square_root(4) -/// // -> Ok(2.0) -/// ``` -/// -/// ```gleam -/// square_root(-16) -/// // -> Error(Nil) -/// ``` -/// -pub fn square_root(x: Int) -> Result(Float, Nil) { - x - |> to_float - |> float.square_root() -} - -/// Parses a given string as an int if possible. -/// -/// ## Examples -/// -/// ```gleam -/// parse("2") -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// parse("ABC") -/// // -> Error(Nil) -/// ``` -/// -@external(erlang, "gleam_stdlib", "parse_int") -@external(javascript, "../gleam_stdlib.mjs", "parse_int") -pub fn parse(string: String) -> Result(Int, Nil) - -/// Parses a given string as an int in a given base if possible. -/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. -/// -/// ## Examples -/// -/// ```gleam -/// base_parse("10", 2) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// base_parse("30", 16) -/// // -> Ok(48) -/// ``` -/// -/// ```gleam -/// base_parse("1C", 36) -/// // -> Ok(48) -/// ``` -/// -/// ```gleam -/// base_parse("48", 1) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// base_parse("48", 37) -/// // -> Error(Nil) -/// ``` -/// -pub fn base_parse(string: String, base: Int) -> Result(Int, Nil) { - case base >= 2 && base <= 36 { - True -> do_base_parse(string, base) - False -> Error(Nil) - } -} - -@external(erlang, "gleam_stdlib", "int_from_base_string") -@external(javascript, "../gleam_stdlib.mjs", "int_from_base_string") -fn do_base_parse(a: String, b: Int) -> Result(Int, Nil) - -/// Prints a given int to a string. -/// -/// ## Examples -/// -/// ```gleam -/// to_string(2) -/// // -> "2" -/// ``` -/// -@external(erlang, "erlang", "integer_to_binary") -@external(javascript, "../gleam_stdlib.mjs", "to_string") -pub fn to_string(x: Int) -> String - -/// Prints a given int to a string using the base number provided. -/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. -/// For common bases (2, 8, 16, 36), use the `to_baseN` functions. -/// -/// ## Examples -/// -/// ```gleam -/// to_base_string(2, 2) -/// // -> Ok("10") -/// ``` -/// -/// ```gleam -/// to_base_string(48, 16) -/// // -> Ok("30") -/// ``` -/// -/// ```gleam -/// to_base_string(48, 36) -/// // -> Ok("1C") -/// ``` -/// -/// ```gleam -/// to_base_string(48, 1) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// to_base_string(48, 37) -/// // -> Error(Nil) -/// ``` -/// -pub fn to_base_string(x: Int, base: Int) -> Result(String, Nil) { - case base >= 2 && base <= 36 { - True -> Ok(do_to_base_string(x, base)) - False -> Error(Nil) - } -} - -@external(erlang, "erlang", "integer_to_binary") -@external(javascript, "../gleam_stdlib.mjs", "int_to_base_string") -fn do_to_base_string(a: Int, b: Int) -> String - -/// Prints a given int to a string using base-2. -/// -/// ## Examples -/// -/// ```gleam -/// to_base2(2) -/// // -> "10" -/// ``` -/// -pub fn to_base2(x: Int) -> String { - do_to_base_string(x, 2) -} - -/// Prints a given int to a string using base-8. -/// -/// ## Examples -/// -/// ```gleam -/// to_base8(15) -/// // -> "17" -/// ``` -/// -pub fn to_base8(x: Int) -> String { - do_to_base_string(x, 8) -} - -/// Prints a given int to a string using base-16. -/// -/// ## Examples -/// -/// ```gleam -/// to_base16(48) -/// // -> "30" -/// ``` -/// -pub fn to_base16(x: Int) -> String { - do_to_base_string(x, 16) -} - -/// Prints a given int to a string using base-36. -/// -/// ## Examples -/// -/// ```gleam -/// to_base36(48) -/// // -> "1C" -/// ``` -/// -pub fn to_base36(x: Int) -> String { - do_to_base_string(x, 36) -} - -/// Takes an int and returns its value as a float. -/// -/// ## Examples -/// -/// ```gleam -/// to_float(5) -/// // -> 5.0 -/// ``` -/// -/// ```gleam -/// to_float(0) -/// // -> 0.0 -/// ``` -/// -/// ```gleam -/// to_float(-3) -/// // -> -3.0 -/// ``` -/// -@external(erlang, "erlang", "float") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn to_float(x: Int) -> Float - -/// Restricts an int between a lower and upper bound. -/// -/// ## Examples -/// -/// ```gleam -/// clamp(40, min: 50, max: 60) -/// // -> 50 -/// ``` -/// -pub fn clamp(x: Int, min min_bound: Int, max max_bound: Int) -> Int { - x - |> min(max_bound) - |> max(min_bound) -} - -/// Compares two ints, returning an order. -/// -/// ## Examples -/// -/// ```gleam -/// compare(2, 3) -/// // -> Lt -/// ``` -/// -/// ```gleam -/// compare(4, 3) -/// // -> Gt -/// ``` -/// -/// ```gleam -/// compare(3, 3) -/// // -> Eq -/// ``` -/// -pub fn compare(a: Int, with b: Int) -> Order { - case a == b { - True -> order.Eq - False -> - case a < b { - True -> order.Lt - False -> order.Gt - } - } -} - -/// Compares two ints, returning the smaller of the two. -/// -/// ## Examples -/// -/// ```gleam -/// min(2, 3) -/// // -> 2 -/// ``` -/// -pub fn min(a: Int, b: Int) -> Int { - case a < b { - True -> a - False -> b - } -} - -/// Compares two ints, returning the larger of the two. -/// -/// ## Examples -/// -/// ```gleam -/// max(2, 3) -/// // -> 3 -/// ``` -/// -pub fn max(a: Int, b: Int) -> Int { - case a > b { - True -> a - False -> b - } -} - -/// Returns whether the value provided is even. -/// -/// ## Examples -/// -/// ```gleam -/// is_even(2) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_even(3) -/// // -> False -/// ``` -/// -pub fn is_even(x: Int) -> Bool { - x % 2 == 0 -} - -/// Returns whether the value provided is odd. -/// -/// ## Examples -/// -/// ```gleam -/// is_odd(3) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_odd(2) -/// // -> False -/// ``` -/// -pub fn is_odd(x: Int) -> Bool { - x % 2 != 0 -} - -/// Returns the negative of the value provided. -/// -/// ## Examples -/// -/// ```gleam -/// negate(1) -/// // -> -1 -/// ``` -/// -pub fn negate(x: Int) -> Int { - -1 * x -} - -/// Sums a list of ints. -/// -/// ## Example -/// -/// ```gleam -/// sum([1, 2, 3]) -/// // -> 6 -/// ``` -/// -pub fn sum(numbers: List(Int)) -> Int { - sum_loop(numbers, 0) -} - -fn sum_loop(numbers: List(Int), initial: Int) -> Int { - case numbers { - [first, ..rest] -> sum_loop(rest, first + initial) - [] -> initial - } -} - -/// Multiplies a list of ints and returns the product. -/// -/// ## Example -/// -/// ```gleam -/// product([2, 3, 4]) -/// // -> 24 -/// ``` -/// -pub fn product(numbers: List(Int)) -> Int { - product_loop(numbers, 1) -} - -fn product_loop(numbers: List(Int), initial: Int) -> Int { - case numbers { - [first, ..rest] -> product_loop(rest, first * initial) - [] -> initial - } -} - -@deprecated("Vendor this function into your codebase") -pub fn digits(x: Int, base: Int) -> Result(List(Int), Nil) { - case base < 2 { - True -> Error(Nil) - False -> Ok(digits_loop(x, base, [])) - } -} - -fn digits_loop(x: Int, base: Int, acc: List(Int)) -> List(Int) { - case absolute_value(x) < base { - True -> [x, ..acc] - False -> digits_loop(x / base, base, [x % base, ..acc]) - } -} - -@deprecated("Vendor this function into your codebase") -pub fn undigits(numbers: List(Int), base: Int) -> Result(Int, Nil) { - case base < 2 { - True -> Error(Nil) - False -> undigits_loop(numbers, base, 0) - } -} - -fn undigits_loop(numbers: List(Int), base: Int, acc: Int) -> Result(Int, Nil) { - case numbers { - [] -> Ok(acc) - [digit, ..] if digit >= base -> Error(Nil) - [digit, ..rest] -> undigits_loop(rest, base, acc * base + digit) - } -} - -/// Generates a random int between zero and the given maximum. -/// -/// The lower number is inclusive, the upper number is exclusive. -/// -/// ## Examples -/// -/// ```gleam -/// random(10) -/// // -> 4 -/// ``` -/// -/// ```gleam -/// random(1) -/// // -> 0 -/// ``` -/// -/// ```gleam -/// random(-1) -/// // -> -1 -/// ``` -/// -pub fn random(max: Int) -> Int { - { float.random() *. to_float(max) } - |> float.floor - |> float.round -} - -/// Performs a truncated integer division. -/// -/// Returns division of the inputs as a `Result`: If the given divisor equals -/// `0`, this function returns an `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// divide(0, 1) -/// // -> Ok(0) -/// ``` -/// -/// ```gleam -/// divide(1, 0) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// divide(5, 2) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// divide(-99, 2) -/// // -> Ok(-49) -/// ``` -/// -pub fn divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) { - case divisor { - 0 -> Error(Nil) - divisor -> Ok(dividend / divisor) - } -} - -/// Computes the remainder of an integer division of inputs as a `Result`. -/// -/// Returns division of the inputs as a `Result`: If the given divisor equals -/// `0`, this function returns an `Error`. -/// -/// Most the time you will want to use the `%` operator instead of this -/// function. -/// -/// ## Examples -/// -/// ```gleam -/// remainder(3, 2) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// remainder(1, 0) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// remainder(10, -1) -/// // -> Ok(0) -/// ``` -/// -/// ```gleam -/// remainder(13, by: 3) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// remainder(-13, by: 3) -/// // -> Ok(-1) -/// ``` -/// -/// ```gleam -/// remainder(13, by: -3) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// remainder(-13, by: -3) -/// // -> Ok(-1) -/// ``` -/// -pub fn remainder(dividend: Int, by divisor: Int) -> Result(Int, Nil) { - case divisor { - 0 -> Error(Nil) - divisor -> Ok(dividend % divisor) - } -} - -/// Computes the modulo of an integer division of inputs as a `Result`. -/// -/// Returns division of the inputs as a `Result`: If the given divisor equals -/// `0`, this function returns an `Error`. -/// -/// Most the time you will want to use the `%` operator instead of this -/// function. -/// -/// ## Examples -/// -/// ```gleam -/// modulo(3, 2) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// modulo(1, 0) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// modulo(10, -1) -/// // -> Ok(0) -/// ``` -/// -/// ```gleam -/// modulo(13, by: 3) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// modulo(-13, by: 3) -/// // -> Ok(2) -/// ``` -/// -pub fn modulo(dividend: Int, by divisor: Int) -> Result(Int, Nil) { - case divisor { - 0 -> Error(Nil) - _ -> { - let remainder = dividend % divisor - case remainder * divisor < 0 { - True -> Ok(remainder + divisor) - False -> Ok(remainder) - } - } - } -} - -/// Performs a *floored* integer division, which means that the result will -/// always be rounded towards negative infinity. -/// -/// If you want to perform truncated integer division (rounding towards zero), -/// use `int.divide()` or the `/` operator instead. -/// -/// Returns division of the inputs as a `Result`: If the given divisor equals -/// `0`, this function returns an `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// floor_divide(1, 0) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// floor_divide(5, 2) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// floor_divide(6, -4) -/// // -> Ok(-2) -/// ``` -/// -/// ```gleam -/// floor_divide(-99, 2) -/// // -> Ok(-50) -/// ``` -/// -pub fn floor_divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) { - case divisor { - 0 -> Error(Nil) - divisor -> - case dividend * divisor < 0 && dividend % divisor != 0 { - True -> Ok(dividend / divisor - 1) - False -> Ok(dividend / divisor) - } - } -} - -/// Adds two integers together. -/// -/// It's the function equivalent of the `+` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// add(1, 2) -/// // -> 3 -/// ``` -/// -/// ```gleam -/// import gleam/list -/// list.fold([1, 2, 3], 0, add) -/// // -> 6 -/// ``` -/// -/// ```gleam -/// 3 |> add(2) -/// // -> 5 -/// ``` -/// -pub fn add(a: Int, b: Int) -> Int { - a + b -} - -/// Multiplies two integers together. -/// -/// It's the function equivalent of the `*` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// multiply(2, 4) -/// // -> 8 -/// ``` -/// -/// ```gleam -/// import gleam/list -/// -/// list.fold([2, 3, 4], 1, multiply) -/// // -> 24 -/// ``` -/// -/// ```gleam -/// 3 |> multiply(2) -/// // -> 6 -/// ``` -/// -pub fn multiply(a: Int, b: Int) -> Int { - a * b -} - -/// Subtracts one int from another. -/// -/// It's the function equivalent of the `-` operator. -/// This function is useful in higher order functions or pipes. -/// -/// ## Examples -/// -/// ```gleam -/// subtract(3, 1) -/// // -> 2 -/// ``` -/// -/// ```gleam -/// import gleam/list -/// -/// list.fold([1, 2, 3], 10, subtract) -/// // -> 4 -/// ``` -/// -/// ```gleam -/// 3 |> subtract(2) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// 3 |> subtract(2, _) -/// // -> -1 -/// ``` -/// -pub fn subtract(a: Int, b: Int) -> Int { - a - b -} - -/// Calculates the bitwise AND of its arguments. -/// -/// The exact behaviour of this function depends on the target platform. -/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it -/// is equivalent to bitwise operations on big-ints. -/// -@external(erlang, "erlang", "band") -@external(javascript, "../gleam_stdlib.mjs", "bitwise_and") -pub fn bitwise_and(x: Int, y: Int) -> Int - -/// Calculates the bitwise NOT of its argument. -/// -/// The exact behaviour of this function depends on the target platform. -/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it -/// is equivalent to bitwise operations on big-ints. -/// -@external(erlang, "erlang", "bnot") -@external(javascript, "../gleam_stdlib.mjs", "bitwise_not") -pub fn bitwise_not(x: Int) -> Int - -/// Calculates the bitwise OR of its arguments. -/// -/// The exact behaviour of this function depends on the target platform. -/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it -/// is equivalent to bitwise operations on big-ints. -/// -@external(erlang, "erlang", "bor") -@external(javascript, "../gleam_stdlib.mjs", "bitwise_or") -pub fn bitwise_or(x: Int, y: Int) -> Int - -/// Calculates the bitwise XOR of its arguments. -/// -/// The exact behaviour of this function depends on the target platform. -/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it -/// is equivalent to bitwise operations on big-ints. -/// -@external(erlang, "erlang", "bxor") -@external(javascript, "../gleam_stdlib.mjs", "bitwise_exclusive_or") -pub fn bitwise_exclusive_or(x: Int, y: Int) -> Int - -/// Calculates the result of an arithmetic left bitshift. -/// -/// The exact behaviour of this function depends on the target platform. -/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it -/// is equivalent to bitwise operations on big-ints. -/// -@external(erlang, "erlang", "bsl") -@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_left") -pub fn bitwise_shift_left(x: Int, y: Int) -> Int - -/// Calculates the result of an arithmetic right bitshift. -/// -/// The exact behaviour of this function depends on the target platform. -/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it -/// is equivalent to bitwise operations on big-ints. -/// -@external(erlang, "erlang", "bsr") -@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_right") -pub fn bitwise_shift_right(x: Int, y: Int) -> Int diff --git a/build/packages/gleam_stdlib/src/gleam/io.gleam b/build/packages/gleam_stdlib/src/gleam/io.gleam deleted file mode 100644 index 67088eb..0000000 --- a/build/packages/gleam_stdlib/src/gleam/io.gleam +++ /dev/null @@ -1,59 +0,0 @@ -/// Writes a string to standard output (stdout). -/// -/// If you want your output to be printed on its own line see `println`. -/// -/// ## Example -/// -/// ```gleam -/// io.print("Hi mum") -/// // -> Nil -/// // Hi mum -/// ``` -/// -@external(erlang, "gleam_stdlib", "print") -@external(javascript, "../gleam_stdlib.mjs", "print") -pub fn print(string: String) -> Nil - -/// Writes a string to standard error (stderr). -/// -/// If you want your output to be printed on its own line see `println_error`. -/// -/// ## Example -/// -/// ``` -/// io.print_error("Hi pop") -/// // -> Nil -/// // Hi pop -/// ``` -/// -@external(erlang, "gleam_stdlib", "print_error") -@external(javascript, "../gleam_stdlib.mjs", "print_error") -pub fn print_error(string: String) -> Nil - -/// Writes a string to standard output (stdout), appending a newline to the end. -/// -/// ## Example -/// -/// ```gleam -/// io.println("Hi mum") -/// // -> Nil -/// // Hi mum -/// ``` -/// -@external(erlang, "gleam_stdlib", "println") -@external(javascript, "../gleam_stdlib.mjs", "console_log") -pub fn println(string: String) -> Nil - -/// Writes a string to standard error (stderr), appending a newline to the end. -/// -/// ## Example -/// -/// ```gleam -/// io.println_error("Hi pop") -/// // -> Nil -/// // Hi pop -/// ``` -/// -@external(erlang, "gleam_stdlib", "println_error") -@external(javascript, "../gleam_stdlib.mjs", "console_error") -pub fn println_error(string: String) -> Nil diff --git a/build/packages/gleam_stdlib/src/gleam/list.gleam b/build/packages/gleam_stdlib/src/gleam/list.gleam deleted file mode 100644 index 6373efb..0000000 --- a/build/packages/gleam_stdlib/src/gleam/list.gleam +++ /dev/null @@ -1,2426 +0,0 @@ -//// Lists are an ordered sequence of elements and are one of the most common -//// data types in Gleam. -//// -//// New elements can be added and removed from the front of a list in -//// constant time, while adding and removing from the end requires traversing -//// and copying the whole list, so keep this in mind when designing your -//// programs. -//// -//// There is a dedicated syntax for prefixing to a list: -//// -//// ```gleam -//// let new_list = [1, 2, ..existing_list] -//// ``` -//// -//// And a matching syntax for getting the first elements of a list: -//// -//// ```gleam -//// case list { -//// [first_element, ..rest] -> first_element -//// _ -> "this pattern matches when the list is empty" -//// } -//// ``` -//// - -import gleam/dict.{type Dict} -import gleam/float -import gleam/int -import gleam/order.{type Order} - -/// Counts the number of elements in a given list. -/// -/// This function has to traverse the list to determine the number of elements, -/// so it runs in linear time. -/// -/// This function is natively implemented by the virtual machine and is highly -/// optimised. -/// -/// ## Examples -/// -/// ```gleam -/// length([]) -/// // -> 0 -/// ``` -/// -/// ```gleam -/// length([1]) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// length([1, 2]) -/// // -> 2 -/// ``` -/// -@external(erlang, "erlang", "length") -pub fn length(of list: List(a)) -> Int { - length_loop(list, 0) -} - -fn length_loop(list: List(a), count: Int) -> Int { - case list { - [_, ..list] -> length_loop(list, count + 1) - [] -> count - } -} - -/// Counts the number of elements in a given list satisfying a given predicate. -/// -/// This function has to traverse the list to determine the number of elements, -/// so it runs in linear time. -/// -/// ## Examples -/// -/// ```gleam -/// count([], fn(a) { a > 0 }) -/// // -> 0 -/// ``` -/// -/// ```gleam -/// count([1], fn(a) { a > 0 }) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// count([1, 2, 3], int.is_odd) -/// // -> 2 -/// ``` -/// -pub fn count(list: List(a), where predicate: fn(a) -> Bool) -> Int { - count_loop(list, predicate, 0) -} - -fn count_loop(list: List(a), predicate: fn(a) -> Bool, acc: Int) -> Int { - case list { - [] -> acc - [first, ..rest] -> - case predicate(first) { - True -> count_loop(rest, predicate, acc + 1) - False -> count_loop(rest, predicate, acc) - } - } -} - -/// Creates a new list from a given list containing the same elements but in the -/// opposite order. -/// -/// This function has to traverse the list to create the new reversed list, so -/// it runs in linear time. -/// -/// This function is natively implemented by the virtual machine and is highly -/// optimised. -/// -/// ## Examples -/// -/// ```gleam -/// reverse([]) -/// // -> [] -/// ``` -/// -/// ```gleam -/// reverse([1]) -/// // -> [1] -/// ``` -/// -/// ```gleam -/// reverse([1, 2]) -/// // -> [2, 1] -/// ``` -/// -@external(erlang, "lists", "reverse") -pub fn reverse(list: List(a)) -> List(a) { - reverse_and_prepend(list, []) -} - -/// Reverses a list and prepends it to another list. -/// This function runs in linear time, proportional to the length of the list -/// to prepend. -/// -@external(erlang, "lists", "reverse") -fn reverse_and_prepend(list prefix: List(a), to suffix: List(a)) -> List(a) { - case prefix { - [] -> suffix - [first, ..rest] -> reverse_and_prepend(list: rest, to: [first, ..suffix]) - } -} - -/// Determines whether or not the list is empty. -/// -/// This function runs in constant time. -/// -/// ## Examples -/// -/// ```gleam -/// is_empty([]) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_empty([1]) -/// // -> False -/// ``` -/// -/// ```gleam -/// is_empty([1, 1]) -/// // -> False -/// ``` -/// -pub fn is_empty(list: List(a)) -> Bool { - list == [] -} - -/// Determines whether or not a given element exists within a given list. -/// -/// This function traverses the list to find the element, so it runs in linear -/// time. -/// -/// ## Examples -/// -/// ```gleam -/// [] |> contains(any: 0) -/// // -> False -/// ``` -/// -/// ```gleam -/// [0] |> contains(any: 0) -/// // -> True -/// ``` -/// -/// ```gleam -/// [1] |> contains(any: 0) -/// // -> False -/// ``` -/// -/// ```gleam -/// [1, 1] |> contains(any: 0) -/// // -> False -/// ``` -/// -/// ```gleam -/// [1, 0] |> contains(any: 0) -/// // -> True -/// ``` -/// -pub fn contains(list: List(a), any elem: a) -> Bool { - case list { - [] -> False - [first, ..] if first == elem -> True - [_, ..rest] -> contains(rest, elem) - } -} - -/// Gets the first element from the start of the list, if there is one. -/// -/// ## Examples -/// -/// ```gleam -/// first([]) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// first([0]) -/// // -> Ok(0) -/// ``` -/// -/// ```gleam -/// first([1, 2]) -/// // -> Ok(1) -/// ``` -/// -pub fn first(list: List(a)) -> Result(a, Nil) { - case list { - [] -> Error(Nil) - [first, ..] -> Ok(first) - } -} - -/// Returns the list minus the first element. If the list is empty, `Error(Nil)` is -/// returned. -/// -/// This function runs in constant time and does not make a copy of the list. -/// -/// ## Examples -/// -/// ```gleam -/// rest([]) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// rest([0]) -/// // -> Ok([]) -/// ``` -/// -/// ```gleam -/// rest([1, 2]) -/// // -> Ok([2]) -/// ``` -/// -pub fn rest(list: List(a)) -> Result(List(a), Nil) { - case list { - [] -> Error(Nil) - [_, ..rest] -> Ok(rest) - } -} - -/// Groups the elements from the given list by the given key function. -/// -/// Does not preserve the initial value order. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/dict -/// -/// [Ok(3), Error("Wrong"), Ok(200), Ok(73)] -/// |> group(by: fn(i) { -/// case i { -/// Ok(_) -> "Successful" -/// Error(_) -> "Failed" -/// } -/// }) -/// |> dict.to_list -/// // -> [ -/// // #("Failed", [Error("Wrong")]), -/// // #("Successful", [Ok(73), Ok(200), Ok(3)]) -/// // ] -/// ``` -/// -/// ```gleam -/// import gleam/dict -/// -/// group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 }) -/// |> dict.to_list -/// // -> [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])] -/// ``` -/// -pub fn group(list: List(v), by key: fn(v) -> k) -> Dict(k, List(v)) { - group_loop(list, key, dict.new()) -} - -fn group_loop( - list: List(v), - to_key: fn(v) -> k, - groups: Dict(k, List(v)), -) -> Dict(k, List(v)) { - case list { - [] -> groups - [first, ..rest] -> { - let key = to_key(first) - let groups = case dict.get(groups, key) { - Error(_) -> dict.insert(groups, key, [first]) - Ok(existing) -> dict.insert(groups, key, [first, ..existing]) - } - group_loop(rest, to_key, groups) - } - } -} - -/// Returns a new list containing only the elements from the first list for -/// which the given functions returns `True`. -/// -/// ## Examples -/// -/// ```gleam -/// filter([2, 4, 6, 1], fn(x) { x > 2 }) -/// // -> [4, 6] -/// ``` -/// -/// ```gleam -/// filter([2, 4, 6, 1], fn(x) { x > 6 }) -/// // -> [] -/// ``` -/// -pub fn filter(list: List(a), keeping predicate: fn(a) -> Bool) -> List(a) { - filter_loop(list, predicate, []) -} - -fn filter_loop(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) { - case list { - [] -> reverse(acc) - [first, ..rest] -> { - let new_acc = case fun(first) { - True -> [first, ..acc] - False -> acc - } - filter_loop(rest, fun, new_acc) - } - } -} - -/// Returns a new list containing only the elements from the first list for -/// which the given functions returns `Ok(_)`. -/// -/// ## Examples -/// -/// ```gleam -/// filter_map([2, 4, 6, 1], Error) -/// // -> [] -/// ``` -/// -/// ```gleam -/// filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) -/// // -> [3, 5, 7, 2] -/// ``` -/// -pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) { - filter_map_loop(list, fun, []) -} - -fn filter_map_loop( - list: List(a), - fun: fn(a) -> Result(b, e), - acc: List(b), -) -> List(b) { - case list { - [] -> reverse(acc) - [first, ..rest] -> { - let new_acc = case fun(first) { - Ok(first) -> [first, ..acc] - Error(_) -> acc - } - filter_map_loop(rest, fun, new_acc) - } - } -} - -/// Returns a new list containing only the elements of the first list after the -/// function has been applied to each one. -/// -/// ## Examples -/// -/// ```gleam -/// map([2, 4, 6], fn(x) { x * 2 }) -/// // -> [4, 8, 12] -/// ``` -/// -pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) { - map_loop(list, fun, []) -} - -fn map_loop(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) { - case list { - [] -> reverse(acc) - [first, ..rest] -> map_loop(rest, fun, [fun(first), ..acc]) - } -} - -/// Combines two lists into a single list using the given function. -/// -/// If a list is longer than the other the extra elements are dropped. -/// -/// ## Examples -/// -/// ```gleam -/// map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) -/// // -> [5, 7, 9] -/// ``` -/// -/// ```gleam -/// map2([1, 2], ["a", "b", "c"], fn(i, x) { #(i, x) }) -/// // -> [#(1, "a"), #(2, "b")] -/// ``` -/// -pub fn map2(list1: List(a), list2: List(b), with fun: fn(a, b) -> c) -> List(c) { - map2_loop(list1, list2, fun, []) -} - -fn map2_loop( - list1: List(a), - list2: List(b), - fun: fn(a, b) -> c, - acc: List(c), -) -> List(c) { - case list1, list2 { - [], _ | _, [] -> reverse(acc) - [a, ..as_], [b, ..bs] -> map2_loop(as_, bs, fun, [fun(a, b), ..acc]) - } -} - -/// Similar to `map` but also lets you pass around an accumulated value. -/// -/// ## Examples -/// -/// ```gleam -/// map_fold( -/// over: [1, 2, 3], -/// from: 100, -/// with: fn(memo, i) { #(memo + i, i * 2) } -/// ) -/// // -> #(106, [2, 4, 6]) -/// ``` -/// -pub fn map_fold( - over list: List(a), - from initial: acc, - with fun: fn(acc, a) -> #(acc, b), -) -> #(acc, List(b)) { - map_fold_loop(list, fun, initial, []) -} - -fn map_fold_loop( - list: List(a), - fun: fn(acc, a) -> #(acc, b), - acc: acc, - list_acc: List(b), -) -> #(acc, List(b)) { - case list { - [] -> #(acc, reverse(list_acc)) - [first, ..rest] -> { - let #(acc, first) = fun(acc, first) - map_fold_loop(rest, fun, acc, [first, ..list_acc]) - } - } -} - -/// Returns a new list containing only the elements of the first list after the -/// function has been applied to each one and their index. -/// -/// The index starts at 0, so the first element is 0, the second is 1, and so -/// on. -/// -/// ## Examples -/// -/// ```gleam -/// index_map(["a", "b"], fn(x, i) { #(i, x) }) -/// // -> [#(0, "a"), #(1, "b")] -/// ``` -/// -pub fn index_map(list: List(a), with fun: fn(a, Int) -> b) -> List(b) { - index_map_loop(list, fun, 0, []) -} - -fn index_map_loop( - list: List(a), - fun: fn(a, Int) -> b, - index: Int, - acc: List(b), -) -> List(b) { - case list { - [] -> reverse(acc) - [first, ..rest] -> { - let acc = [fun(first, index), ..acc] - index_map_loop(rest, fun, index + 1, acc) - } - } -} - -/// Takes a function that returns a `Result` and applies it to each element in a -/// given list in turn. -/// -/// If the function returns `Ok(new_value)` for all elements in the list then a -/// list of the new values is returned. -/// -/// If the function returns `Error(reason)` for any of the elements then it is -/// returned immediately. None of the elements in the list are processed after -/// one returns an `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// try_map([1, 2, 3], fn(x) { Ok(x + 2) }) -/// // -> Ok([3, 4, 5]) -/// ``` -/// -/// ```gleam -/// try_map([1, 2, 3], fn(_) { Error(0) }) -/// // -> Error(0) -/// ``` -/// -/// ```gleam -/// try_map([[1], [2, 3]], first) -/// // -> Ok([1, 2]) -/// ``` -/// -/// ```gleam -/// try_map([[1], [], [2]], first) -/// // -> Error(Nil) -/// ``` -/// -pub fn try_map( - over list: List(a), - with fun: fn(a) -> Result(b, e), -) -> Result(List(b), e) { - try_map_loop(list, fun, []) -} - -fn try_map_loop( - list: List(a), - fun: fn(a) -> Result(b, e), - acc: List(b), -) -> Result(List(b), e) { - case list { - [] -> Ok(reverse(acc)) - [first, ..rest] -> - case fun(first) { - Ok(first) -> try_map_loop(rest, fun, [first, ..acc]) - Error(error) -> Error(error) - } - } -} - -/// Returns a list that is the given list with up to the given number of -/// elements removed from the front of the list. -/// -/// If the element has less than the number of elements an empty list is -/// returned. -/// -/// This function runs in linear time but does not copy the list. -/// -/// ## Examples -/// -/// ```gleam -/// drop([1, 2, 3, 4], 2) -/// // -> [3, 4] -/// ``` -/// -/// ```gleam -/// drop([1, 2, 3, 4], 9) -/// // -> [] -/// ``` -/// -pub fn drop(from list: List(a), up_to n: Int) -> List(a) { - case n <= 0 { - True -> list - False -> - case list { - [] -> [] - [_, ..rest] -> drop(rest, n - 1) - } - } -} - -/// Returns a list containing the first given number of elements from the given -/// list. -/// -/// If the element has less than the number of elements then the full list is -/// returned. -/// -/// This function runs in linear time. -/// -/// ## Examples -/// -/// ```gleam -/// take([1, 2, 3, 4], 2) -/// // -> [1, 2] -/// ``` -/// -/// ```gleam -/// take([1, 2, 3, 4], 9) -/// // -> [1, 2, 3, 4] -/// ``` -/// -pub fn take(from list: List(a), up_to n: Int) -> List(a) { - take_loop(list, n, []) -} - -fn take_loop(list: List(a), n: Int, acc: List(a)) -> List(a) { - case n <= 0 { - True -> reverse(acc) - False -> - case list { - [] -> reverse(acc) - [first, ..rest] -> take_loop(rest, n - 1, [first, ..acc]) - } - } -} - -/// Returns a new empty list. -/// -/// ## Examples -/// -/// ```gleam -/// new() -/// // -> [] -/// ``` -/// -pub fn new() -> List(a) { - [] -} - -/// Returns the given item wrapped in a list. -/// -/// ## Examples -/// -/// ```gleam -/// wrap(1) -/// // -> [1] -/// -/// wrap(["a", "b", "c"]) -/// // -> [["a", "b", "c"]] -/// -/// wrap([[]]) -/// // -> [[[]]] -/// ``` -/// -/// -pub fn wrap(item: a) -> List(a) { - [item] -} - -/// Joins one list onto the end of another. -/// -/// This function runs in linear time, and it traverses and copies the first -/// list. -/// -/// ## Examples -/// -/// ```gleam -/// append([1, 2], [3]) -/// // -> [1, 2, 3] -/// ``` -/// -@external(erlang, "lists", "append") -pub fn append(first: List(a), second: List(a)) -> List(a) { - append_loop(reverse(first), second) -} - -fn append_loop(first: List(a), second: List(a)) -> List(a) { - case first { - [] -> second - [first, ..rest] -> append_loop(rest, [first, ..second]) - } -} - -/// Prefixes an item to a list. This can also be done using the dedicated -/// syntax instead -/// -/// ```gleam -/// let existing_list = [2, 3, 4] -/// -/// [1, ..existing_list] -/// // -> [1, 2, 3, 4] -/// -/// prepend(to: existing_list, this: 1) -/// // -> [1, 2, 3, 4] -/// ``` -/// -pub fn prepend(to list: List(a), this item: a) -> List(a) { - [item, ..list] -} - -/// Joins a list of lists into a single list. -/// -/// This function traverses all elements twice on the JavaScript target. -/// This function traverses all elements once on the Erlang target. -/// -/// ## Examples -/// -/// ```gleam -/// flatten([[1], [2, 3], []]) -/// // -> [1, 2, 3] -/// ``` -/// -@external(erlang, "lists", "append") -pub fn flatten(lists: List(List(a))) -> List(a) { - flatten_loop(lists, []) -} - -fn flatten_loop(lists: List(List(a)), acc: List(a)) -> List(a) { - case lists { - [] -> reverse(acc) - [list, ..further_lists] -> - flatten_loop(further_lists, reverse_and_prepend(list, to: acc)) - } -} - -/// Maps the list with the given function into a list of lists, and then flattens it. -/// -/// ## Examples -/// -/// ```gleam -/// flat_map([2, 4, 6], fn(x) { [x, x + 1] }) -/// // -> [2, 3, 4, 5, 6, 7] -/// ``` -/// -pub fn flat_map(over list: List(a), with fun: fn(a) -> List(b)) -> List(b) { - flatten(map(list, fun)) -} - -/// Reduces a list of elements into a single value by calling a given function -/// on each element, going from left to right. -/// -/// `fold([1, 2, 3], 0, add)` is the equivalent of -/// `add(add(add(0, 1), 2), 3)`. -/// -/// This function runs in linear time. -/// -pub fn fold( - over list: List(a), - from initial: acc, - with fun: fn(acc, a) -> acc, -) -> acc { - case list { - [] -> initial - [first, ..rest] -> fold(rest, fun(initial, first), fun) - } -} - -/// Reduces a list of elements into a single value by calling a given function -/// on each element, going from right to left. -/// -/// `fold_right([1, 2, 3], 0, add)` is the equivalent of -/// `add(add(add(0, 3), 2), 1)`. -/// -/// This function runs in linear time. -/// -/// Unlike `fold` this function is not tail recursive. Where possible use -/// `fold` instead as it will use less memory. -/// -pub fn fold_right( - over list: List(a), - from initial: acc, - with fun: fn(acc, a) -> acc, -) -> acc { - case list { - [] -> initial - [first, ..rest] -> fun(fold_right(rest, initial, fun), first) - } -} - -/// Like fold but the folding function also receives the index of the current element. -/// -/// ## Examples -/// -/// ```gleam -/// ["a", "b", "c"] -/// |> index_fold("", fn(acc, item, index) { -/// acc <> int.to_string(index) <> ":" <> item <> " " -/// }) -/// // -> "0:a 1:b 2:c" -/// ``` -/// -/// ```gleam -/// [10, 20, 30] -/// |> index_fold(0, fn(acc, item, index) { acc + item * index }) -/// // -> 80 -/// ``` -/// -pub fn index_fold( - over list: List(a), - from initial: acc, - with fun: fn(acc, a, Int) -> acc, -) -> acc { - index_fold_loop(list, initial, fun, 0) -} - -fn index_fold_loop( - over: List(a), - acc: acc, - with: fn(acc, a, Int) -> acc, - index: Int, -) -> acc { - case over { - [] -> acc - [first, ..rest] -> - index_fold_loop(rest, with(acc, first, index), with, index + 1) - } -} - -/// A variant of fold that might fail. -/// -/// The folding function should return `Result(accumulator, error)`. -/// If the returned value is `Ok(accumulator)` try_fold will try the next value in the list. -/// If the returned value is `Error(error)` try_fold will stop and return that error. -/// -/// ## Examples -/// -/// ```gleam -/// [1, 2, 3, 4] -/// |> try_fold(0, fn(acc, i) { -/// case i < 3 { -/// True -> Ok(acc + i) -/// False -> Error(Nil) -/// } -/// }) -/// // -> Error(Nil) -/// ``` -/// -pub fn try_fold( - over list: List(a), - from initial: acc, - with fun: fn(acc, a) -> Result(acc, e), -) -> Result(acc, e) { - case list { - [] -> Ok(initial) - [first, ..rest] -> - case fun(initial, first) { - Ok(result) -> try_fold(rest, result, fun) - Error(_) as error -> error - } - } -} - -pub type ContinueOrStop(a) { - Continue(a) - Stop(a) -} - -/// A variant of fold that allows to stop folding earlier. -/// -/// The folding function should return `ContinueOrStop(accumulator)`. -/// If the returned value is `Continue(accumulator)` fold_until will try the next value in the list. -/// If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator. -/// -/// ## Examples -/// -/// ```gleam -/// [1, 2, 3, 4] -/// |> fold_until(0, fn(acc, i) { -/// case i < 3 { -/// True -> Continue(acc + i) -/// False -> Stop(acc) -/// } -/// }) -/// // -> 3 -/// ``` -/// -pub fn fold_until( - over list: List(a), - from initial: acc, - with fun: fn(acc, a) -> ContinueOrStop(acc), -) -> acc { - case list { - [] -> initial - [first, ..rest] -> - case fun(initial, first) { - Continue(next_accumulator) -> fold_until(rest, next_accumulator, fun) - Stop(b) -> b - } - } -} - -/// Finds the first element in a given list for which the given function returns -/// `True`. -/// -/// Returns `Error(Nil)` if no such element is found. -/// -/// ## Examples -/// -/// ```gleam -/// find([1, 2, 3], fn(x) { x > 2 }) -/// // -> Ok(3) -/// ``` -/// -/// ```gleam -/// find([1, 2, 3], fn(x) { x > 4 }) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// find([], fn(_) { True }) -/// // -> Error(Nil) -/// ``` -/// -pub fn find( - in list: List(a), - one_that is_desired: fn(a) -> Bool, -) -> Result(a, Nil) { - case list { - [] -> Error(Nil) - [first, ..rest] -> - case is_desired(first) { - True -> Ok(first) - False -> find(in: rest, one_that: is_desired) - } - } -} - -/// Finds the first element in a given list for which the given function returns -/// `Ok(new_value)`, then returns the wrapped `new_value`. -/// -/// Returns `Error(Nil)` if no such element is found. -/// -/// ## Examples -/// -/// ```gleam -/// find_map([[], [2], [3]], first) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// find_map([[], []], first) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// find_map([], first) -/// // -> Error(Nil) -/// ``` -/// -pub fn find_map( - in list: List(a), - with fun: fn(a) -> Result(b, c), -) -> Result(b, Nil) { - case list { - [] -> Error(Nil) - [first, ..rest] -> - case fun(first) { - Ok(first) -> Ok(first) - Error(_) -> find_map(in: rest, with: fun) - } - } -} - -/// Returns `True` if the given function returns `True` for all the elements in -/// the given list. If the function returns `False` for any of the elements it -/// immediately returns `False` without checking the rest of the list. -/// -/// ## Examples -/// -/// ```gleam -/// all([], fn(x) { x > 3 }) -/// // -> True -/// ``` -/// -/// ```gleam -/// all([4, 5], fn(x) { x > 3 }) -/// // -> True -/// ``` -/// -/// ```gleam -/// all([4, 3], fn(x) { x > 3 }) -/// // -> False -/// ``` -/// -pub fn all(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool { - case list { - [] -> True - [first, ..rest] -> - case predicate(first) { - True -> all(rest, predicate) - False -> False - } - } -} - -/// Returns `True` if the given function returns `True` for any the elements in -/// the given list. If the function returns `True` for any of the elements it -/// immediately returns `True` without checking the rest of the list. -/// -/// ## Examples -/// -/// ```gleam -/// any([], fn(x) { x > 3 }) -/// // -> False -/// ``` -/// -/// ```gleam -/// any([4, 5], fn(x) { x > 3 }) -/// // -> True -/// ``` -/// -/// ```gleam -/// any([4, 3], fn(x) { x > 4 }) -/// // -> False -/// ``` -/// -/// ```gleam -/// any([3, 4], fn(x) { x > 3 }) -/// // -> True -/// ``` -/// -pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool { - case list { - [] -> False - [first, ..rest] -> - case predicate(first) { - True -> True - False -> any(rest, predicate) - } - } -} - -/// Takes two lists and returns a single list of 2-element tuples. -/// -/// If one of the lists is longer than the other, the remaining elements from -/// the longer list are not used. -/// -/// ## Examples -/// -/// ```gleam -/// zip([], []) -/// // -> [] -/// ``` -/// -/// ```gleam -/// zip([1, 2], [3]) -/// // -> [#(1, 3)] -/// ``` -/// -/// ```gleam -/// zip([1], [3, 4]) -/// // -> [#(1, 3)] -/// ``` -/// -/// ```gleam -/// zip([1, 2], [3, 4]) -/// // -> [#(1, 3), #(2, 4)] -/// ``` -/// -pub fn zip(list: List(a), with other: List(b)) -> List(#(a, b)) { - zip_loop(list, other, []) -} - -fn zip_loop(one: List(a), other: List(b), acc: List(#(a, b))) -> List(#(a, b)) { - case one, other { - [first_one, ..rest_one], [first_other, ..rest_other] -> - zip_loop(rest_one, rest_other, [#(first_one, first_other), ..acc]) - _, _ -> reverse(acc) - } -} - -/// Takes two lists and returns a single list of 2-element tuples. -/// -/// If one of the lists is longer than the other, an `Error` is returned. -/// -/// ## Examples -/// -/// ```gleam -/// strict_zip([], []) -/// // -> Ok([]) -/// ``` -/// -/// ```gleam -/// strict_zip([1, 2], [3]) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// strict_zip([1], [3, 4]) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// strict_zip([1, 2], [3, 4]) -/// // -> Ok([#(1, 3), #(2, 4)]) -/// ``` -/// -pub fn strict_zip( - list: List(a), - with other: List(b), -) -> Result(List(#(a, b)), Nil) { - strict_zip_loop(list, other, []) -} - -fn strict_zip_loop( - one: List(a), - other: List(b), - acc: List(#(a, b)), -) -> Result(List(#(a, b)), Nil) { - case one, other { - [], [] -> Ok(reverse(acc)) - [], _ | _, [] -> Error(Nil) - [first_one, ..rest_one], [first_other, ..rest_other] -> - strict_zip_loop(rest_one, rest_other, [#(first_one, first_other), ..acc]) - } -} - -/// Takes a single list of 2-element tuples and returns two lists. -/// -/// ## Examples -/// -/// ```gleam -/// unzip([#(1, 2), #(3, 4)]) -/// // -> #([1, 3], [2, 4]) -/// ``` -/// -/// ```gleam -/// unzip([]) -/// // -> #([], []) -/// ``` -/// -pub fn unzip(input: List(#(a, b))) -> #(List(a), List(b)) { - unzip_loop(input, [], []) -} - -fn unzip_loop( - input: List(#(a, b)), - one: List(a), - other: List(b), -) -> #(List(a), List(b)) { - case input { - [] -> #(reverse(one), reverse(other)) - [#(first_one, first_other), ..rest] -> - unzip_loop(rest, [first_one, ..one], [first_other, ..other]) - } -} - -/// Inserts a given value between each existing element in a given list. -/// -/// This function runs in linear time and copies the list. -/// -/// ## Examples -/// -/// ```gleam -/// intersperse([1, 1, 1], 2) -/// // -> [1, 2, 1, 2, 1] -/// ``` -/// -/// ```gleam -/// intersperse([], 2) -/// // -> [] -/// ``` -/// -pub fn intersperse(list: List(a), with elem: a) -> List(a) { - case list { - [] | [_] -> list - [first, ..rest] -> intersperse_loop(rest, elem, [first]) - } -} - -fn intersperse_loop(list: List(a), separator: a, acc: List(a)) -> List(a) { - case list { - [] -> reverse(acc) - [first, ..rest] -> - intersperse_loop(rest, separator, [first, separator, ..acc]) - } -} - -/// Removes any duplicate elements from a given list. -/// -/// This function returns in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// unique([1, 1, 1, 4, 7, 3, 3, 4]) -/// // -> [1, 4, 7, 3] -/// ``` -/// -pub fn unique(list: List(a)) -> List(a) { - unique_loop(list, dict.new(), []) -} - -fn unique_loop(list: List(a), seen: Dict(a, Nil), acc: List(a)) -> List(a) { - case list { - [] -> reverse(acc) - [first, ..rest] -> - case dict.has_key(seen, first) { - True -> unique_loop(rest, seen, acc) - False -> - unique_loop(rest, dict.insert(seen, first, Nil), [first, ..acc]) - } - } -} - -/// Sorts from smallest to largest based upon the ordering specified by a given -/// function. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// -/// sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) -/// // -> [1, 2, 3, 4, 4, 5, 6] -/// ``` -/// -pub fn sort(list: List(a), by compare: fn(a, a) -> Order) -> List(a) { - // This is a natural, tail recursive, stable merge sort: - // - natural: it is very efficient if you call it on a list that is already - // (pre)sorted because it works on slices of the original list. - // - tail recursive: the stack won't grow linearly with the size of the list. - // - stable: if two items are considered to be equal then their original - // relative order is preserved. - case list { - // If the list has zero/one item then it's already sorted. - [] -> [] - [x] -> [x] - - // Otherwise the algorithm works as follow: we split the list in sequences - // of already sorted values as they appear in the list and then we merge - // those together two by two using `merge_all`. - [x, y, ..rest] -> { - // We need to compare the first two items to properly call `sequences` - // with the correct initial values. If the second item is <= than the - // first, then we know we'll start by growing a descending sequence - // (and an ascending one in the opposite case). - let direction = case compare(x, y) { - order.Lt | order.Eq -> Ascending - order.Gt -> Descending - } - - // `sequences` produces sequences in ascending order so we call the - // `merge_all` function saying it to expect all sequences to be sorted - // that way. - let sequences = sequences(rest, compare, [x], direction, y, []) - merge_all(sequences, Ascending, compare) - } - } -} - -type Sorting { - Ascending - Descending -} - -/// Given a list it returns slices of it that are locally sorted in ascending -/// order. -/// -/// Imagine you have this list: -/// -/// ``` -/// [1, 2, 3, 2, 1, 0] -/// ^^^^^^^ ^^^^^^^ This is a slice in descending order -/// | -/// | This is a slice that is sorted in ascending order -/// ``` -/// -/// So the produced result will contain these two slices, each one sorted in -/// ascending order: `[[1, 2, 3], [0, 1, 2]]`. -/// -/// - `growing` is an accumulator with the current slice being grown -/// - `direction` is the growing direction of the slice being grown, it could -/// either be ascending or strictly descending -/// - `prev` is the previous element that needs to be added to the growing slice -/// it is carried around to check whether we have to keep growing the current -/// slice or not -/// - `acc` is the accumulator containing the slices sorted in ascending order -/// -fn sequences( - list: List(a), - compare: fn(a, a) -> Order, - growing: List(a), - direction: Sorting, - prev: a, - acc: List(List(a)), -) -> List(List(a)) { - // First of all we must not forget to add the previous element to the - // currently growing slice. - let growing = [prev, ..growing] - - case list { - [] -> - case direction { - // Notice how we have to reverse the accumulator we're growing: since - // we always add items to the head, `growing` is built in the opposite - // sorting order of what it actually is in the original list. - Ascending -> [reverse(growing), ..acc] - Descending -> [growing, ..acc] - } - - [new, ..rest] -> - case compare(prev, new), direction { - // In case the new element respects the ordering of the growing - // sequence, then we just keep growing it. - // Notice how a growing sequence is weakly growing (that is it can have - // consecutive equal items) while a decreasing sequence is strictly - // decreasing (no consecutive equal items), this is needed to make the - // algorithm stable! - order.Gt, Descending | order.Lt, Ascending | order.Eq, Ascending -> - sequences(rest, compare, growing, direction, new, acc) - - // We were growing an ascending (descending) sequence and the new item - // is smaller (bigger) than the previous one, this means we have to stop - // growing this sequence and start with a new one whose first item will - // be the one we just found. - order.Gt, Ascending | order.Lt, Descending | order.Eq, Descending -> { - let acc = case direction { - Ascending -> [reverse(growing), ..acc] - Descending -> [growing, ..acc] - } - case rest { - // The list is over so we just create a sequence containing the last - // item we saw and add it to the accumulator before returning it. - [] -> [[new], ..acc] - - // If the list is not over we have a peek at the next item to decide - // in which direction is growing the new sequence and make the - // recursive call with the appropriate arguments. - [next, ..rest] -> { - let direction = case compare(new, next) { - order.Lt | order.Eq -> Ascending - order.Gt -> Descending - } - sequences(rest, compare, [new], direction, next, acc) - } - } - } - } - } -} - -/// Given some some sorted sequences (assumed to be sorted in `direction`) it -/// merges them all together until we're left with just a list sorted in -/// ascending order. -/// -fn merge_all( - sequences: List(List(a)), - direction: Sorting, - compare: fn(a, a) -> Order, -) -> List(a) { - case sequences, direction { - [], _ -> [] - - // If we have a single list in ascending order then we're done. - [sequence], Ascending -> sequence - - // If we have a single list in descending order, we reverse it to make sure - // it's in ascending order and we're done. - [sequence], Descending -> reverse(sequence) - - // Merging together sequences that are in ascending (descending) order - // reverses their order, so the recursive call will assume to be merging - // lists sorted in the opposite order! - _, Ascending -> { - let sequences = merge_ascending_pairs(sequences, compare, []) - merge_all(sequences, Descending, compare) - } - - _, Descending -> { - let sequences = merge_descending_pairs(sequences, compare, []) - merge_all(sequences, Ascending, compare) - } - } -} - -/// Given a list of ascending lists, it merges adjacent pairs into a single -/// descending list, halving their number. -/// It returns a list of the remaining descending lists. -/// -fn merge_ascending_pairs( - sequences: List(List(a)), - compare: fn(a, a) -> Order, - acc: List(List(a)), -) { - case sequences { - [] -> reverse(acc) - - // Beware, if we have just one item left we must reverse it: we take - // ascending lists as input and have to return descending ones. - // If we returned it like it is it would be sorted in ascending order. - [sequence] -> reverse([reverse(sequence), ..acc]) - - [ascending1, ascending2, ..rest] -> { - let descending = merge_ascendings(ascending1, ascending2, compare, []) - merge_ascending_pairs(rest, compare, [descending, ..acc]) - } - } -} - -/// This is the same as merge_ascending_pairs but flipped for descending lists. -/// -fn merge_descending_pairs( - sequences: List(List(a)), - compare: fn(a, a) -> Order, - acc: List(List(a)), -) { - case sequences { - [] -> reverse(acc) - - [sequence] -> reverse([reverse(sequence), ..acc]) - - [descending1, descending2, ..rest] -> { - let ascending = merge_descendings(descending1, descending2, compare, []) - merge_descending_pairs(rest, compare, [ascending, ..acc]) - } - } -} - -/// Merges two lists sorted in ascending order into a single list sorted in -/// descending order according to the given comparator function. -/// -/// This reversing of the sort order is not avoidable if we want to implement -/// merge as a tail recursive function. We could reverse the accumulator before -/// returning it but that would end up being less efficient; so the merging -/// algorithm has to play around this. -/// -fn merge_ascendings( - list1: List(a), - list2: List(a), - compare: fn(a, a) -> Order, - acc: List(a), -) -> List(a) { - case list1, list2 { - [], list | list, [] -> reverse_and_prepend(list, acc) - - [first1, ..rest1], [first2, ..rest2] -> - case compare(first1, first2) { - order.Lt -> merge_ascendings(rest1, list2, compare, [first1, ..acc]) - order.Gt | order.Eq -> - merge_ascendings(list1, rest2, compare, [first2, ..acc]) - } - } -} - -/// This is exactly the same as merge_ascendings but mirrored: it merges two -/// lists sorted in descending order into a single list sorted in ascending -/// order according to the given comparator function. -/// -/// This reversing of the sort order is not avoidable if we want to implement -/// merge as a tail recursive function. We could reverse the accumulator before -/// returning it but that would end up being less efficient; so the merging -/// algorithm has to play around this. -/// -fn merge_descendings( - list1: List(a), - list2: List(a), - compare: fn(a, a) -> Order, - acc: List(a), -) -> List(a) { - case list1, list2 { - [], list | list, [] -> reverse_and_prepend(list, acc) - [first1, ..rest1], [first2, ..rest2] -> - case compare(first1, first2) { - order.Lt -> merge_descendings(list1, rest2, compare, [first2, ..acc]) - order.Gt | order.Eq -> - merge_descendings(rest1, list2, compare, [first1, ..acc]) - } - } -} - -/// Creates a list of ints ranging from a given start and finish. -/// -/// ## Examples -/// -/// ```gleam -/// range(0, 0) -/// // -> [0] -/// ``` -/// -/// ```gleam -/// range(0, 5) -/// // -> [0, 1, 2, 3, 4, 5] -/// ``` -/// -/// ```gleam -/// range(1, -5) -/// // -> [1, 0, -1, -2, -3, -4, -5] -/// ``` -/// -pub fn range(from start: Int, to stop: Int) -> List(Int) { - range_loop(start, stop, []) -} - -fn range_loop(start: Int, stop: Int, acc: List(Int)) -> List(Int) { - case int.compare(start, stop) { - order.Eq -> [stop, ..acc] - order.Gt -> range_loop(start, stop + 1, [stop, ..acc]) - order.Lt -> range_loop(start, stop - 1, [stop, ..acc]) - } -} - -/// Builds a list of a given value a given number of times. -/// -/// ## Examples -/// -/// ```gleam -/// repeat("a", times: 0) -/// // -> [] -/// ``` -/// -/// ```gleam -/// repeat("a", times: 5) -/// // -> ["a", "a", "a", "a", "a"] -/// ``` -/// -pub fn repeat(item a: a, times times: Int) -> List(a) { - repeat_loop(a, times, []) -} - -fn repeat_loop(item: a, times: Int, acc: List(a)) -> List(a) { - case times <= 0 { - True -> acc - False -> repeat_loop(item, times - 1, [item, ..acc]) - } -} - -/// Splits a list in two before the given index. -/// -/// If the list is not long enough to have the given index the before list will -/// be the input list, and the after list will be empty. -/// -/// ## Examples -/// -/// ```gleam -/// split([6, 7, 8, 9], 0) -/// // -> #([], [6, 7, 8, 9]) -/// ``` -/// -/// ```gleam -/// split([6, 7, 8, 9], 2) -/// // -> #([6, 7], [8, 9]) -/// ``` -/// -/// ```gleam -/// split([6, 7, 8, 9], 4) -/// // -> #([6, 7, 8, 9], []) -/// ``` -/// -pub fn split(list list: List(a), at index: Int) -> #(List(a), List(a)) { - split_loop(list, index, []) -} - -fn split_loop(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) { - case n <= 0 { - True -> #(reverse(taken), list) - False -> - case list { - [] -> #(reverse(taken), []) - [first, ..rest] -> split_loop(rest, n - 1, [first, ..taken]) - } - } -} - -/// Splits a list in two before the first element that a given function returns -/// `False` for. -/// -/// If the function returns `True` for all elements the first list will be the -/// input list, and the second list will be empty. -/// -/// ## Examples -/// -/// ```gleam -/// split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 }) -/// // -> #([1, 2, 3], [4, 5]) -/// ``` -/// -/// ```gleam -/// split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 }) -/// // -> #([1, 2, 3, 4, 5], []) -/// ``` -/// -pub fn split_while( - list list: List(a), - satisfying predicate: fn(a) -> Bool, -) -> #(List(a), List(a)) { - split_while_loop(list, predicate, []) -} - -fn split_while_loop( - list: List(a), - f: fn(a) -> Bool, - acc: List(a), -) -> #(List(a), List(a)) { - case list { - [] -> #(reverse(acc), []) - [first, ..rest] -> - case f(first) { - True -> split_while_loop(rest, f, [first, ..acc]) - False -> #(reverse(acc), list) - } - } -} - -/// Given a list of 2-element tuples, finds the first tuple that has a given -/// key as the first element and returns the second element. -/// -/// If no tuple is found with the given key then `Error(Nil)` is returned. -/// -/// This function may be useful for interacting with Erlang code where lists of -/// tuples are common. -/// -/// ## Examples -/// -/// ```gleam -/// key_find([#("a", 0), #("b", 1)], "a") -/// // -> Ok(0) -/// ``` -/// -/// ```gleam -/// key_find([#("a", 0), #("b", 1)], "b") -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// key_find([#("a", 0), #("b", 1)], "c") -/// // -> Error(Nil) -/// ``` -/// -pub fn key_find( - in keyword_list: List(#(k, v)), - find desired_key: k, -) -> Result(v, Nil) { - find_map(keyword_list, fn(keyword) { - let #(key, value) = keyword - case key == desired_key { - True -> Ok(value) - False -> Error(Nil) - } - }) -} - -/// Given a list of 2-element tuples, finds all tuples that have a given -/// key as the first element and returns the second element. -/// -/// This function may be useful for interacting with Erlang code where lists of -/// tuples are common. -/// -/// ## Examples -/// -/// ```gleam -/// key_filter([#("a", 0), #("b", 1), #("a", 2)], "a") -/// // -> [0, 2] -/// ``` -/// -/// ```gleam -/// key_filter([#("a", 0), #("b", 1)], "c") -/// // -> [] -/// ``` -/// -pub fn key_filter( - in keyword_list: List(#(k, v)), - find desired_key: k, -) -> List(v) { - filter_map(keyword_list, fn(keyword) { - let #(key, value) = keyword - case key == desired_key { - True -> Ok(value) - False -> Error(Nil) - } - }) -} - -/// Given a list of 2-element tuples, finds the first tuple that has a given -/// key as the first element. This function will return the second element -/// of the found tuple and list with tuple removed. -/// -/// If no tuple is found with the given key then `Error(Nil)` is returned. -/// -/// ## Examples -/// -/// ```gleam -/// key_pop([#("a", 0), #("b", 1)], "a") -/// // -> Ok(#(0, [#("b", 1)])) -/// ``` -/// -/// ```gleam -/// key_pop([#("a", 0), #("b", 1)], "b") -/// // -> Ok(#(1, [#("a", 0)])) -/// ``` -/// -/// ```gleam -/// key_pop([#("a", 0), #("b", 1)], "c") -/// // -> Error(Nil) -/// ``` -/// -pub fn key_pop(list: List(#(k, v)), key: k) -> Result(#(v, List(#(k, v))), Nil) { - key_pop_loop(list, key, []) -} - -fn key_pop_loop( - list: List(#(k, v)), - key: k, - checked: List(#(k, v)), -) -> Result(#(v, List(#(k, v))), Nil) { - case list { - [] -> Error(Nil) - [#(k, v), ..rest] if k == key -> - Ok(#(v, reverse_and_prepend(checked, rest))) - [first, ..rest] -> key_pop_loop(rest, key, [first, ..checked]) - } -} - -/// Given a list of 2-element tuples, inserts a key and value into the list. -/// -/// If there was already a tuple with the key then it is replaced, otherwise it -/// is added to the end of the list. -/// -/// ## Examples -/// -/// ```gleam -/// key_set([#(5, 0), #(4, 1)], 4, 100) -/// // -> [#(5, 0), #(4, 100)] -/// ``` -/// -/// ```gleam -/// key_set([#(5, 0), #(4, 1)], 1, 100) -/// // -> [#(5, 0), #(4, 1), #(1, 100)] -/// ``` -/// -pub fn key_set(list: List(#(k, v)), key: k, value: v) -> List(#(k, v)) { - key_set_loop(list, key, value, []) -} - -fn key_set_loop( - list: List(#(k, v)), - key: k, - value: v, - inspected: List(#(k, v)), -) -> List(#(k, v)) { - case list { - [#(k, _), ..rest] if k == key -> - reverse_and_prepend(inspected, [#(k, value), ..rest]) - [first, ..rest] -> key_set_loop(rest, key, value, [first, ..inspected]) - [] -> reverse([#(key, value), ..inspected]) - } -} - -/// Calls a function for each element in a list, discarding the return value. -/// -/// Useful for calling a side effect for every item of a list. -/// -/// ```gleam -/// import gleam/io -/// -/// each(["1", "2", "3"], io.println) -/// // -> Nil -/// // 1 -/// // 2 -/// // 3 -/// ``` -/// -pub fn each(list: List(a), f: fn(a) -> b) -> Nil { - case list { - [] -> Nil - [first, ..rest] -> { - f(first) - each(rest, f) - } - } -} - -/// Calls a `Result` returning function for each element in a list, discarding -/// the return value. If the function returns `Error` then the iteration is -/// stopped and the error is returned. -/// -/// Useful for calling a side effect for every item of a list. -/// -/// ## Examples -/// -/// ```gleam -/// try_each( -/// over: [1, 2, 3], -/// with: function_that_might_fail, -/// ) -/// // -> Ok(Nil) -/// ``` -/// -pub fn try_each( - over list: List(a), - with fun: fn(a) -> Result(b, e), -) -> Result(Nil, e) { - case list { - [] -> Ok(Nil) - [first, ..rest] -> - case fun(first) { - Ok(_) -> try_each(over: rest, with: fun) - Error(e) -> Error(e) - } - } -} - -/// Partitions a list into a tuple/pair of lists -/// by a given categorisation function. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// -/// [1, 2, 3, 4, 5] |> partition(int.is_odd) -/// // -> #([1, 3, 5], [2, 4]) -/// ``` -/// -pub fn partition( - list: List(a), - with categorise: fn(a) -> Bool, -) -> #(List(a), List(a)) { - partition_loop(list, categorise, [], []) -} - -fn partition_loop(list, categorise, trues, falses) { - case list { - [] -> #(reverse(trues), reverse(falses)) - [first, ..rest] -> - case categorise(first) { - True -> partition_loop(rest, categorise, [first, ..trues], falses) - False -> partition_loop(rest, categorise, trues, [first, ..falses]) - } - } -} - -/// Returns all the permutations of a list. -/// -/// ## Examples -/// -/// ```gleam -/// permutations([1, 2]) -/// // -> [[1, 2], [2, 1]] -/// ``` -/// -pub fn permutations(list: List(a)) -> List(List(a)) { - case list { - [] -> [[]] - l -> permutation_zip(l, [], []) - } -} - -fn permutation_zip( - list: List(a), - rest: List(a), - acc: List(List(a)), -) -> List(List(a)) { - case list { - [] -> reverse(acc) - [head, ..tail] -> - permutation_prepend( - head, - permutations(reverse_and_prepend(rest, tail)), - tail, - [head, ..rest], - acc, - ) - } -} - -fn permutation_prepend( - el: a, - permutations: List(List(a)), - list_1: List(a), - list_2: List(a), - acc: List(List(a)), -) -> List(List(a)) { - case permutations { - [] -> permutation_zip(list_1, list_2, acc) - [head, ..tail] -> - permutation_prepend(el, tail, list_1, list_2, [[el, ..head], ..acc]) - } -} - -/// Returns a list of sliding windows. -/// -/// ## Examples -/// -/// ```gleam -/// window([1,2,3,4,5], 3) -/// // -> [[1, 2, 3], [2, 3, 4], [3, 4, 5]] -/// ``` -/// -/// ```gleam -/// window([1, 2], 4) -/// // -> [] -/// ``` -/// -pub fn window(list: List(a), by n: Int) -> List(List(a)) { - case n <= 0 { - True -> [] - False -> window_loop([], list, n) - } -} - -fn window_loop(acc: List(List(a)), list: List(a), n: Int) -> List(List(a)) { - let window = take(list, n) - - case length(window) == n { - True -> window_loop([window, ..acc], drop(list, 1), n) - False -> reverse(acc) - } -} - -/// Returns a list of tuples containing two contiguous elements. -/// -/// ## Examples -/// -/// ```gleam -/// window_by_2([1,2,3,4]) -/// // -> [#(1, 2), #(2, 3), #(3, 4)] -/// ``` -/// -/// ```gleam -/// window_by_2([1]) -/// // -> [] -/// ``` -/// -pub fn window_by_2(list: List(a)) -> List(#(a, a)) { - zip(list, drop(list, 1)) -} - -/// Drops the first elements in a given list for which the predicate function returns `True`. -/// -/// ## Examples -/// -/// ```gleam -/// drop_while([1, 2, 3, 4], fn (x) { x < 3 }) -/// // -> [3, 4] -/// ``` -/// -pub fn drop_while( - in list: List(a), - satisfying predicate: fn(a) -> Bool, -) -> List(a) { - case list { - [] -> [] - [first, ..rest] -> - case predicate(first) { - True -> drop_while(rest, predicate) - False -> [first, ..rest] - } - } -} - -/// Takes the first elements in a given list for which the predicate function returns `True`. -/// -/// ## Examples -/// -/// ```gleam -/// take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) -/// // -> [1, 2] -/// ``` -/// -pub fn take_while( - in list: List(a), - satisfying predicate: fn(a) -> Bool, -) -> List(a) { - take_while_loop(list, predicate, []) -} - -fn take_while_loop( - list: List(a), - predicate: fn(a) -> Bool, - acc: List(a), -) -> List(a) { - case list { - [] -> reverse(acc) - [first, ..rest] -> - case predicate(first) { - True -> take_while_loop(rest, predicate, [first, ..acc]) - False -> reverse(acc) - } - } -} - -/// Returns a list of chunks in which -/// the return value of calling `f` on each element is the same. -/// -/// ## Examples -/// -/// ```gleam -/// [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 }) -/// // -> [[1], [2, 2], [3], [4, 4, 6], [7, 7]] -/// ``` -/// -pub fn chunk(in list: List(a), by f: fn(a) -> k) -> List(List(a)) { - case list { - [] -> [] - [first, ..rest] -> chunk_loop(rest, f, f(first), [first], []) - } -} - -fn chunk_loop( - list: List(a), - f: fn(a) -> k, - previous_key: k, - current_chunk: List(a), - acc: List(List(a)), -) -> List(List(a)) { - case list { - [first, ..rest] -> { - let key = f(first) - case key == previous_key { - True -> chunk_loop(rest, f, key, [first, ..current_chunk], acc) - False -> { - let new_acc = [reverse(current_chunk), ..acc] - chunk_loop(rest, f, key, [first], new_acc) - } - } - } - [] -> reverse([reverse(current_chunk), ..acc]) - } -} - -/// Returns a list of chunks containing `count` elements each. -/// -/// If the last chunk does not have `count` elements, it is instead -/// a partial chunk, with less than `count` elements. -/// -/// For any `count` less than 1 this function behaves as if it was set to 1. -/// -/// ## Examples -/// -/// ```gleam -/// [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2) -/// // -> [[1, 2], [3, 4], [5, 6]] -/// ``` -/// -/// ```gleam -/// [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3) -/// // -> [[1, 2, 3], [4, 5, 6], [7, 8]] -/// ``` -/// -pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) { - sized_chunk_loop(list, count, count, [], []) -} - -fn sized_chunk_loop( - list: List(a), - count: Int, - left: Int, - current_chunk: List(a), - acc: List(List(a)), -) -> List(List(a)) { - case list { - [] -> - case current_chunk { - [] -> reverse(acc) - remaining -> reverse([reverse(remaining), ..acc]) - } - [first, ..rest] -> { - let chunk = [first, ..current_chunk] - case left > 1 { - True -> sized_chunk_loop(rest, count, left - 1, chunk, acc) - False -> - sized_chunk_loop(rest, count, count, [], [reverse(chunk), ..acc]) - } - } - } -} - -/// This function acts similar to fold, but does not take an initial state. -/// Instead, it starts from the first element in the list -/// and combines it with each subsequent element in turn using the given -/// function. The function is called as `fun(accumulator, current_element)`. -/// -/// Returns `Ok` to indicate a successful run, and `Error` if called on an -/// empty list. -/// -/// ## Examples -/// -/// ```gleam -/// [] |> reduce(fn(acc, x) { acc + x }) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) -/// // -> Ok(15) -/// ``` -/// -pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) { - case list { - [] -> Error(Nil) - [first, ..rest] -> Ok(fold(rest, first, fun)) - } -} - -/// Similar to `fold`, but yields the state of the accumulator at each stage. -/// -/// ## Examples -/// -/// ```gleam -/// scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i }) -/// // -> [101, 103, 106] -/// ``` -/// -pub fn scan( - over list: List(a), - from initial: acc, - with fun: fn(acc, a) -> acc, -) -> List(acc) { - scan_loop(list, initial, [], fun) -} - -fn scan_loop( - list: List(a), - accumulator: acc, - accumulated: List(acc), - fun: fn(acc, a) -> acc, -) -> List(acc) { - case list { - [] -> reverse(accumulated) - [first, ..rest] -> { - let next = fun(accumulator, first) - scan_loop(rest, next, [next, ..accumulated], fun) - } - } -} - -/// Returns the last element in the given list. -/// -/// Returns `Error(Nil)` if the list is empty. -/// -/// This function runs in linear time. -/// -/// ## Examples -/// -/// ```gleam -/// last([]) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// last([1, 2, 3, 4, 5]) -/// // -> Ok(5) -/// ``` -/// -pub fn last(list: List(a)) -> Result(a, Nil) { - case list { - [] -> Error(Nil) - [last] -> Ok(last) - [_, ..rest] -> last(rest) - } -} - -/// Return unique combinations of elements in the list. -/// -/// ## Examples -/// -/// ```gleam -/// combinations([1, 2, 3], 2) -/// // -> [[1, 2], [1, 3], [2, 3]] -/// ``` -/// -/// ```gleam -/// combinations([1, 2, 3, 4], 3) -/// // -> [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]] -/// ``` -/// -pub fn combinations(items: List(a), by n: Int) -> List(List(a)) { - case n, items { - 0, _ -> [[]] - _, [] -> [] - _, [first, ..rest] -> - rest - |> combinations(n - 1) - |> map(fn(combination) { [first, ..combination] }) - |> reverse - |> fold(combinations(rest, n), fn(acc, c) { [c, ..acc] }) - } -} - -/// Return unique pair combinations of elements in the list. -/// -/// ## Examples -/// -/// ```gleam -/// combination_pairs([1, 2, 3]) -/// // -> [#(1, 2), #(1, 3), #(2, 3)] -/// ``` -/// -pub fn combination_pairs(items: List(a)) -> List(#(a, a)) { - combination_pairs_loop(items, []) -} - -fn combination_pairs_loop(items: List(a), acc: List(#(a, a))) -> List(#(a, a)) { - case items { - [] -> reverse(acc) - [first, ..rest] -> { - let first_combinations = map(rest, with: fn(other) { #(first, other) }) - let acc = reverse_and_prepend(first_combinations, acc) - combination_pairs_loop(rest, acc) - } - } -} - -/// Make a list alternating the elements from the given lists -/// -/// ## Examples -/// -/// ```gleam -/// interleave([[1, 2], [101, 102], [201, 202]]) -/// // -> [1, 101, 201, 2, 102, 202] -/// ``` -/// -pub fn interleave(list: List(List(a))) -> List(a) { - list - |> transpose - |> flatten -} - -/// Transpose rows and columns of the list of lists. -/// -/// Notice: This function is not tail recursive, -/// and thus may exceed stack size if called, -/// with large lists (on the JavaScript target). -/// -/// ## Examples -/// -/// ```gleam -/// transpose([[1, 2, 3], [101, 102, 103]]) -/// // -> [[1, 101], [2, 102], [3, 103]] -/// ``` -/// -pub fn transpose(list_of_lists: List(List(a))) -> List(List(a)) { - transpose_loop(list_of_lists, []) -} - -fn transpose_loop(rows: List(List(a)), columns: List(List(a))) -> List(List(a)) { - case rows { - [] -> reverse(columns) - _ -> { - let #(column, rest) = take_firsts(rows, [], []) - case column { - [_, ..] -> transpose_loop(rest, [column, ..columns]) - [] -> transpose_loop(rest, columns) - } - } - } -} - -fn take_firsts( - rows: List(List(a)), - column: List(a), - remaining_rows: List(List(a)), -) -> #(List(a), List(List(a))) { - case rows { - [] -> #(reverse(column), reverse(remaining_rows)) - [[], ..rest] -> take_firsts(rest, column, remaining_rows) - [[first, ..remaining_row], ..rest_rows] -> { - let remaining_rows = [remaining_row, ..remaining_rows] - take_firsts(rest_rows, [first, ..column], remaining_rows) - } - } -} - -/// Takes a list, randomly sorts all items and returns the shuffled list. -/// -/// This function uses `float.random` to decide the order of the elements. -/// -/// ## Example -/// -/// ```gleam -/// range(1, 10) |> shuffle() -/// // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5] -/// ``` -/// -pub fn shuffle(list: List(a)) -> List(a) { - list - |> fold(from: [], with: fn(acc, a) { [#(float.random(), a), ..acc] }) - |> do_shuffle_by_pair_indexes() - |> shuffle_pair_unwrap_loop([]) -} - -fn shuffle_pair_unwrap_loop(list: List(#(Float, a)), acc: List(a)) -> List(a) { - case list { - [] -> acc - [elem_pair, ..enumerable] -> - shuffle_pair_unwrap_loop(enumerable, [elem_pair.1, ..acc]) - } -} - -fn do_shuffle_by_pair_indexes( - list_of_pairs: List(#(Float, a)), -) -> List(#(Float, a)) { - sort(list_of_pairs, fn(a_pair: #(Float, a), b_pair: #(Float, a)) -> Order { - float.compare(a_pair.0, b_pair.0) - }) -} - -/// Takes a list and a comparator, and returns the maximum element in the list -/// -/// -/// ## Example -/// -/// ```gleam -/// range(1, 10) |> list.max(int.compare) -/// // -> Ok(10) -/// ``` -/// -/// ```gleam -/// ["a", "c", "b"] |> list.max(string.compare) -/// // -> Ok("c") -/// ``` -pub fn max( - over list: List(a), - with compare: fn(a, a) -> Order, -) -> Result(a, Nil) { - case list { - [] -> Error(Nil) - [first, ..rest] -> Ok(max_loop(rest, compare, first)) - } -} - -fn max_loop(list, compare, max) { - case list { - [] -> max - [first, ..rest] -> - case compare(first, max) { - order.Gt -> max_loop(rest, compare, first) - order.Lt | order.Eq -> max_loop(rest, compare, max) - } - } -} - -/// Returns a random sample of up to n elements from a list using reservoir -/// sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L). -/// Returns an empty list if the sample size is less than or equal to 0. -/// -/// Order is not random, only selection is. -/// -/// ## Examples -/// -/// ```gleam -/// reservoir_sample([1, 2, 3, 4, 5], 3) -/// // -> [2, 4, 5] // A random sample of 3 items -/// ``` -/// -pub fn sample(from list: List(a), up_to n: Int) -> List(a) { - let #(reservoir, rest) = build_reservoir(from: list, sized: n) - - case dict.is_empty(reservoir) { - // If the reservoire is empty that means we were asking to sample 0 or - // less items. That doesn't make much sense, so we just return an empty - // list. - True -> [] - - // Otherwise we keep looping over the remaining part of the list replacing - // random elements in the reservoir. - False -> { - let w = float.exponential(log_random() /. int.to_float(n)) - dict.values(sample_loop(rest, reservoir, n, w)) - } - } -} - -fn sample_loop( - list: List(a), - reservoir: Dict(Int, a), - n: Int, - w: Float, -) -> Dict(Int, a) { - let skip = { - let assert Ok(log) = float.logarithm(1.0 -. w) - float.round(float.floor(log_random() /. log)) - } - - case drop(list, skip) { - [] -> reservoir - [first, ..rest] -> { - let reservoir = dict.insert(reservoir, int.random(n), first) - let w = w *. float.exponential(log_random() /. int.to_float(n)) - sample_loop(rest, reservoir, n, w) - } - } -} - -const min_positive = 2.2250738585072014e-308 - -fn log_random() -> Float { - let assert Ok(random) = float.logarithm(float.random() +. min_positive) - random -} - -/// Builds the initial reservoir used by Algorithm L. -/// This is a dictionary with keys ranging from `0` up to `n - 1` where each -/// value is the corresponding element at that position in `list`. -/// -/// This also returns the remaining elements of `list` that didn't end up in -/// the reservoir. -/// -fn build_reservoir(from list: List(a), sized n: Int) -> #(Dict(Int, a), List(a)) { - build_reservoir_loop(list, n, dict.new()) -} - -fn build_reservoir_loop( - list: List(a), - size: Int, - reservoir: Dict(Int, a), -) -> #(Dict(Int, a), List(a)) { - let reservoir_size = dict.size(reservoir) - case reservoir_size >= size { - // The reservoir already has the size we wanted. - True -> #(reservoir, list) - - // Otherwise we add another element from the list to the reservoir - False -> - case list { - [] -> #(reservoir, []) - [first, ..rest] -> { - let reservoir = dict.insert(reservoir, reservoir_size, first) - build_reservoir_loop(rest, size, reservoir) - } - } - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/option.gleam b/build/packages/gleam_stdlib/src/gleam/option.gleam deleted file mode 100644 index af5d864..0000000 --- a/build/packages/gleam_stdlib/src/gleam/option.gleam +++ /dev/null @@ -1,358 +0,0 @@ -/// `Option` represents a value that may be present or not. `Some` means the value is -/// present, `None` means the value is not. -/// -/// This is Gleam's alternative to having a value that could be Null, as is -/// possible in some other languages. -/// -/// ## `Option` and `Result` -/// -/// In other languages fallible functions may return either `Result` or -/// `Option` depending on whether there is more information to be given about the -/// failure. In Gleam all fallible functions return `Result`, and `Nil` is used -/// as the error if there is no extra detail to give. This consistency removes -/// the boilerplate that would otherwise be needed to convert between `Option` -/// and `Result` types, and makes APIs more predictable. -/// -/// The `Option` type should only be used for taking optional values as -/// function arguments, or for storing them in other data structures. -/// -pub type Option(a) { - Some(a) - None -} - -/// Combines a list of `Option`s into a single `Option`. -/// If all elements in the list are `Some` then returns a `Some` holding the list of values. -/// If any element is `None` then returns`None`. -/// -/// ## Examples -/// -/// ```gleam -/// all([Some(1), Some(2)]) -/// // -> Some([1, 2]) -/// ``` -/// -/// ```gleam -/// all([Some(1), None]) -/// // -> None -/// ``` -/// -pub fn all(list: List(Option(a))) -> Option(List(a)) { - all_loop(list, []) -} - -fn all_loop(list: List(Option(a)), acc: List(a)) -> Option(List(a)) { - case list { - [] -> Some(reverse(acc)) - [None, ..] -> None - [Some(first), ..rest] -> all_loop(rest, [first, ..acc]) - } -} - -// This is copied from the list module and not imported as importing it would -// result in a circular dependency! -@external(erlang, "lists", "reverse") -fn reverse(list: List(a)) -> List(a) { - reverse_and_prepend(list, []) -} - -fn reverse_and_prepend(list prefix: List(a), to suffix: List(a)) -> List(a) { - case prefix { - [] -> suffix - [first, ..rest] -> reverse_and_prepend(list: rest, to: [first, ..suffix]) - } -} - -/// Checks whether the `Option` is a `Some` value. -/// -/// ## Examples -/// -/// ```gleam -/// is_some(Some(1)) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_some(None) -/// // -> False -/// ``` -/// -pub fn is_some(option: Option(a)) -> Bool { - option != None -} - -/// Checks whether the `Option` is a `None` value. -/// -/// ## Examples -/// -/// ```gleam -/// is_none(Some(1)) -/// // -> False -/// ``` -/// -/// ```gleam -/// is_none(None) -/// // -> True -/// ``` -/// -pub fn is_none(option: Option(a)) -> Bool { - option == None -} - -/// Converts an `Option` type to a `Result` type. -/// -/// ## Examples -/// -/// ```gleam -/// to_result(Some(1), "some_error") -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// to_result(None, "some_error") -/// // -> Error("some_error") -/// ``` -/// -pub fn to_result(option: Option(a), e) -> Result(a, e) { - case option { - Some(a) -> Ok(a) - None -> Error(e) - } -} - -/// Converts a `Result` type to an `Option` type. -/// -/// ## Examples -/// -/// ```gleam -/// from_result(Ok(1)) -/// // -> Some(1) -/// ``` -/// -/// ```gleam -/// from_result(Error("some_error")) -/// // -> None -/// ``` -/// -pub fn from_result(result: Result(a, e)) -> Option(a) { - case result { - Ok(a) -> Some(a) - Error(_) -> None - } -} - -/// Extracts the value from an `Option`, returning a default value if there is none. -/// -/// ## Examples -/// -/// ```gleam -/// unwrap(Some(1), 0) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// unwrap(None, 0) -/// // -> 0 -/// ``` -/// -pub fn unwrap(option: Option(a), or default: a) -> a { - case option { - Some(x) -> x - None -> default - } -} - -/// Extracts the value from an `Option`, evaluating the default function if the option is `None`. -/// -/// ## Examples -/// -/// ```gleam -/// lazy_unwrap(Some(1), fn() { 0 }) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// lazy_unwrap(None, fn() { 0 }) -/// // -> 0 -/// ``` -/// -pub fn lazy_unwrap(option: Option(a), or default: fn() -> a) -> a { - case option { - Some(x) -> x - None -> default() - } -} - -/// Updates a value held within the `Some` of an `Option` by calling a given function -/// on it. -/// -/// If the `Option` is a `None` rather than `Some`, the function is not called and the -/// `Option` stays the same. -/// -/// ## Examples -/// -/// ```gleam -/// map(over: Some(1), with: fn(x) { x + 1 }) -/// // -> Some(2) -/// ``` -/// -/// ```gleam -/// map(over: None, with: fn(x) { x + 1 }) -/// // -> None -/// ``` -/// -pub fn map(over option: Option(a), with fun: fn(a) -> b) -> Option(b) { - case option { - Some(x) -> Some(fun(x)) - None -> None - } -} - -/// Merges a nested `Option` into a single layer. -/// -/// ## Examples -/// -/// ```gleam -/// flatten(Some(Some(1))) -/// // -> Some(1) -/// ``` -/// -/// ```gleam -/// flatten(Some(None)) -/// // -> None -/// ``` -/// -/// ```gleam -/// flatten(None) -/// // -> None -/// ``` -/// -pub fn flatten(option: Option(Option(a))) -> Option(a) { - case option { - Some(x) -> x - None -> None - } -} - -/// Updates a value held within the `Some` of an `Option` by calling a given function -/// on it, where the given function also returns an `Option`. The two options are -/// then merged together into one `Option`. -/// -/// If the `Option` is a `None` rather than `Some` the function is not called and the -/// option stays the same. -/// -/// This function is the equivalent of calling `map` followed by `flatten`, and -/// it is useful for chaining together multiple functions that return `Option`. -/// -/// ## Examples -/// -/// ```gleam -/// then(Some(1), fn(x) { Some(x + 1) }) -/// // -> Some(2) -/// ``` -/// -/// ```gleam -/// then(Some(1), fn(x) { Some(#("a", x)) }) -/// // -> Some(#("a", 1)) -/// ``` -/// -/// ```gleam -/// then(Some(1), fn(_) { None }) -/// // -> None -/// ``` -/// -/// ```gleam -/// then(None, fn(x) { Some(x + 1) }) -/// // -> None -/// ``` -/// -pub fn then(option: Option(a), apply fun: fn(a) -> Option(b)) -> Option(b) { - case option { - Some(x) -> fun(x) - None -> None - } -} - -/// Returns the first value if it is `Some`, otherwise returns the second value. -/// -/// ## Examples -/// -/// ```gleam -/// or(Some(1), Some(2)) -/// // -> Some(1) -/// ``` -/// -/// ```gleam -/// or(Some(1), None) -/// // -> Some(1) -/// ``` -/// -/// ```gleam -/// or(None, Some(2)) -/// // -> Some(2) -/// ``` -/// -/// ```gleam -/// or(None, None) -/// // -> None -/// ``` -/// -pub fn or(first: Option(a), second: Option(a)) -> Option(a) { - case first { - Some(_) -> first - None -> second - } -} - -/// Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value. -/// -/// ## Examples -/// -/// ```gleam -/// lazy_or(Some(1), fn() { Some(2) }) -/// // -> Some(1) -/// ``` -/// -/// ```gleam -/// lazy_or(Some(1), fn() { None }) -/// // -> Some(1) -/// ``` -/// -/// ```gleam -/// lazy_or(None, fn() { Some(2) }) -/// // -> Some(2) -/// ``` -/// -/// ```gleam -/// lazy_or(None, fn() { None }) -/// // -> None -/// ``` -/// -pub fn lazy_or(first: Option(a), second: fn() -> Option(a)) -> Option(a) { - case first { - Some(_) -> first - None -> second() - } -} - -/// Given a list of `Option`s, -/// returns only the values inside `Some`. -/// -/// ## Examples -/// -/// ```gleam -/// values([Some(1), None, Some(3)]) -/// // -> [1, 3] -/// ``` -/// -pub fn values(options: List(Option(a))) -> List(a) { - values_loop(options, []) -} - -fn values_loop(list: List(Option(a)), acc: List(a)) -> List(a) { - case list { - [] -> reverse(acc) - [None, ..rest] -> values_loop(rest, acc) - [Some(first), ..rest] -> values_loop(rest, [first, ..acc]) - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/order.gleam b/build/packages/gleam_stdlib/src/gleam/order.gleam deleted file mode 100644 index be8b599..0000000 --- a/build/packages/gleam_stdlib/src/gleam/order.gleam +++ /dev/null @@ -1,156 +0,0 @@ -/// Represents the result of a single comparison to determine the precise -/// ordering of two values. -/// -pub type Order { - /// Less-than - Lt - - /// Equal - Eq - - /// Greater than - Gt -} - -/// Inverts an order, so less-than becomes greater-than and greater-than -/// becomes less-than. -/// -/// ## Examples -/// -/// ```gleam -/// negate(Lt) -/// // -> Gt -/// ``` -/// -/// ```gleam -/// negate(Eq) -/// // -> Eq -/// ``` -/// -/// ```gleam -/// negate(Gt) -/// // -> Lt -/// ``` -/// -pub fn negate(order: Order) -> Order { - case order { - Lt -> Gt - Eq -> Eq - Gt -> Lt - } -} - -/// Produces a numeric representation of the order. -/// -/// ## Examples -/// -/// ```gleam -/// to_int(Lt) -/// // -> -1 -/// ``` -/// -/// ```gleam -/// to_int(Eq) -/// // -> 0 -/// ``` -/// -/// ```gleam -/// to_int(Gt) -/// // -> 1 -/// ``` -/// -pub fn to_int(order: Order) -> Int { - case order { - Lt -> -1 - Eq -> 0 - Gt -> 1 - } -} - -/// Compares two `Order` values to one another, producing a new `Order`. -/// -/// ## Examples -/// -/// ```gleam -/// compare(Eq, with: Lt) -/// // -> Gt -/// ``` -/// -pub fn compare(a: Order, with b: Order) -> Order { - case a, b { - x, y if x == y -> Eq - Lt, _ | Eq, Gt -> Lt - _, _ -> Gt - } -} - -/// Inverts an ordering function, so less-than becomes greater-than and greater-than -/// becomes less-than. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// import gleam/list -/// -/// list.sort([1, 5, 4], by: reverse(int.compare)) -/// // -> [5, 4, 1] -/// ``` -/// -pub fn reverse(orderer: fn(a, a) -> Order) -> fn(a, a) -> Order { - fn(a, b) { orderer(b, a) } -} - -/// Return a fallback `Order` in case the first argument is `Eq`. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// -/// break_tie(in: int.compare(1, 1), with: Lt) -/// // -> Lt -/// ``` -/// -/// ```gleam -/// import gleam/int -/// -/// break_tie(in: int.compare(1, 0), with: Eq) -/// // -> Gt -/// ``` -/// -pub fn break_tie(in order: Order, with other: Order) -> Order { - case order { - Lt | Gt -> order - Eq -> other - } -} - -/// Invokes a fallback function returning an `Order` in case the first argument -/// is `Eq`. -/// -/// This can be useful when the fallback comparison might be expensive and it -/// needs to be delayed until strictly necessary. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// -/// lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt }) -/// // -> Lt -/// ``` -/// -/// ```gleam -/// import gleam/int -/// -/// lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq }) -/// // -> Gt -/// ``` -/// -pub fn lazy_break_tie(in order: Order, with comparison: fn() -> Order) -> Order { - case order { - Lt | Gt -> order - Eq -> comparison() - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/pair.gleam b/build/packages/gleam_stdlib/src/gleam/pair.gleam deleted file mode 100644 index 566fc9c..0000000 --- a/build/packages/gleam_stdlib/src/gleam/pair.gleam +++ /dev/null @@ -1,85 +0,0 @@ -/// Returns the first element in a pair. -/// -/// ## Examples -/// -/// ```gleam -/// first(#(1, 2)) -/// // -> 1 -/// ``` -/// -pub fn first(pair: #(a, b)) -> a { - let #(a, _) = pair - a -} - -/// Returns the second element in a pair. -/// -/// ## Examples -/// -/// ```gleam -/// second(#(1, 2)) -/// // -> 2 -/// ``` -/// -pub fn second(pair: #(a, b)) -> b { - let #(_, a) = pair - a -} - -/// Returns a new pair with the elements swapped. -/// -/// ## Examples -/// -/// ```gleam -/// swap(#(1, 2)) -/// // -> #(2, 1) -/// ``` -/// -pub fn swap(pair: #(a, b)) -> #(b, a) { - let #(a, b) = pair - #(b, a) -} - -/// Returns a new pair with the first element having had `with` applied to -/// it. -/// -/// ## Examples -/// -/// ```gleam -/// #(1, 2) |> map_first(fn(n) { n * 2 }) -/// // -> #(2, 2) -/// ``` -/// -pub fn map_first(of pair: #(a, b), with fun: fn(a) -> c) -> #(c, b) { - let #(a, b) = pair - #(fun(a), b) -} - -/// Returns a new pair with the second element having had `with` applied to -/// it. -/// -/// ## Examples -/// -/// ```gleam -/// #(1, 2) |> map_second(fn(n) { n * 2 }) -/// // -> #(1, 4) -/// ``` -/// -pub fn map_second(of pair: #(a, b), with fun: fn(b) -> c) -> #(a, c) { - let #(a, b) = pair - #(a, fun(b)) -} - -/// Returns a new pair with the given elements. This can also be done using the dedicated -/// syntax instead: `new(1, 2) == #(1, 2)`. -/// -/// ## Examples -/// -/// ```gleam -/// new(1, 2) -/// // -> #(1, 2) -/// ``` -/// -pub fn new(first: a, second: b) -> #(a, b) { - #(first, second) -} diff --git a/build/packages/gleam_stdlib/src/gleam/result.gleam b/build/packages/gleam_stdlib/src/gleam/result.gleam deleted file mode 100644 index 741754d..0000000 --- a/build/packages/gleam_stdlib/src/gleam/result.gleam +++ /dev/null @@ -1,453 +0,0 @@ -//// Result represents the result of something that may succeed or not. -//// `Ok` means it was successful, `Error` means it was not successful. - -import gleam/list - -/// Checks whether the result is an `Ok` value. -/// -/// ## Examples -/// -/// ```gleam -/// is_ok(Ok(1)) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_ok(Error(Nil)) -/// // -> False -/// ``` -/// -pub fn is_ok(result: Result(a, e)) -> Bool { - case result { - Error(_) -> False - Ok(_) -> True - } -} - -/// Checks whether the result is an `Error` value. -/// -/// ## Examples -/// -/// ```gleam -/// is_error(Ok(1)) -/// // -> False -/// ``` -/// -/// ```gleam -/// is_error(Error(Nil)) -/// // -> True -/// ``` -/// -pub fn is_error(result: Result(a, e)) -> Bool { - case result { - Ok(_) -> False - Error(_) -> True - } -} - -/// Updates a value held within the `Ok` of a result by calling a given function -/// on it. -/// -/// If the result is an `Error` rather than `Ok` the function is not called and the -/// result stays the same. -/// -/// ## Examples -/// -/// ```gleam -/// map(over: Ok(1), with: fn(x) { x + 1 }) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// map(over: Error(1), with: fn(x) { x + 1 }) -/// // -> Error(1) -/// ``` -/// -pub fn map(over result: Result(a, e), with fun: fn(a) -> b) -> Result(b, e) { - case result { - Ok(x) -> Ok(fun(x)) - Error(e) -> Error(e) - } -} - -/// Updates a value held within the `Error` of a result by calling a given function -/// on it. -/// -/// If the result is `Ok` rather than `Error` the function is not called and the -/// result stays the same. -/// -/// ## Examples -/// -/// ```gleam -/// map_error(over: Error(1), with: fn(x) { x + 1 }) -/// // -> Error(2) -/// ``` -/// -/// ```gleam -/// map_error(over: Ok(1), with: fn(x) { x + 1 }) -/// // -> Ok(1) -/// ``` -/// -pub fn map_error( - over result: Result(a, e), - with fun: fn(e) -> f, -) -> Result(a, f) { - case result { - Ok(x) -> Ok(x) - Error(error) -> Error(fun(error)) - } -} - -/// Merges a nested `Result` into a single layer. -/// -/// ## Examples -/// -/// ```gleam -/// flatten(Ok(Ok(1))) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// flatten(Ok(Error(""))) -/// // -> Error("") -/// ``` -/// -/// ```gleam -/// flatten(Error(Nil)) -/// // -> Error(Nil) -/// ``` -/// -pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) { - case result { - Ok(x) -> x - Error(error) -> Error(error) - } -} - -/// "Updates" an `Ok` result by passing its value to a function that yields a result, -/// and returning the yielded result. (This may "replace" the `Ok` with an `Error`.) -/// -/// If the input is an `Error` rather than an `Ok`, the function is not called and -/// the original `Error` is returned. -/// -/// This function is the equivalent of calling `map` followed by `flatten`, and -/// it is useful for chaining together multiple functions that may fail. -/// -/// ## Examples -/// -/// ```gleam -/// try(Ok(1), fn(x) { Ok(x + 1) }) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// try(Ok(1), fn(x) { Ok(#("a", x)) }) -/// // -> Ok(#("a", 1)) -/// ``` -/// -/// ```gleam -/// try(Ok(1), fn(_) { Error("Oh no") }) -/// // -> Error("Oh no") -/// ``` -/// -/// ```gleam -/// try(Error(Nil), fn(x) { Ok(x + 1) }) -/// // -> Error(Nil) -/// ``` -/// -pub fn try( - result: Result(a, e), - apply fun: fn(a) -> Result(b, e), -) -> Result(b, e) { - case result { - Ok(x) -> fun(x) - Error(e) -> Error(e) - } -} - -@deprecated("This function is an alias of result.try, use that instead") -pub fn then( - result: Result(a, e), - apply fun: fn(a) -> Result(b, e), -) -> Result(b, e) { - try(result, fun) -} - -/// Extracts the `Ok` value from a result, returning a default value if the result -/// is an `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// unwrap(Ok(1), 0) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// unwrap(Error(""), 0) -/// // -> 0 -/// ``` -/// -pub fn unwrap(result: Result(a, e), or default: a) -> a { - case result { - Ok(v) -> v - Error(_) -> default - } -} - -/// Extracts the `Ok` value from a result, evaluating the default function if the result -/// is an `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// lazy_unwrap(Ok(1), fn() { 0 }) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// lazy_unwrap(Error(""), fn() { 0 }) -/// // -> 0 -/// ``` -/// -pub fn lazy_unwrap(result: Result(a, e), or default: fn() -> a) -> a { - case result { - Ok(v) -> v - Error(_) -> default() - } -} - -/// Extracts the `Error` value from a result, returning a default value if the result -/// is an `Ok`. -/// -/// ## Examples -/// -/// ```gleam -/// unwrap_error(Error(1), 0) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// unwrap_error(Ok(""), 0) -/// // -> 0 -/// ``` -/// -pub fn unwrap_error(result: Result(a, e), or default: e) -> e { - case result { - Ok(_) -> default - Error(e) -> e - } -} - -@deprecated("Use a case expression instead of this function") -pub fn unwrap_both(result: Result(a, a)) -> a { - case result { - Ok(a) -> a - Error(a) -> a - } -} - -/// Returns the first value if it is `Ok`, otherwise returns the second value. -/// -/// ## Examples -/// -/// ```gleam -/// or(Ok(1), Ok(2)) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// or(Ok(1), Error("Error 2")) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// or(Error("Error 1"), Ok(2)) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// or(Error("Error 1"), Error("Error 2")) -/// // -> Error("Error 2") -/// ``` -/// -pub fn or(first: Result(a, e), second: Result(a, e)) -> Result(a, e) { - case first { - Ok(_) -> first - Error(_) -> second - } -} - -/// Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value. -/// -/// If you need access to the initial error value, use `result.try_recover`. -/// -/// ## Examples -/// -/// ```gleam -/// lazy_or(Ok(1), fn() { Ok(2) }) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// lazy_or(Ok(1), fn() { Error("Error 2") }) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// lazy_or(Error("Error 1"), fn() { Ok(2) }) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// lazy_or(Error("Error 1"), fn() { Error("Error 2") }) -/// // -> Error("Error 2") -/// ``` -/// -pub fn lazy_or( - first: Result(a, e), - second: fn() -> Result(a, e), -) -> Result(a, e) { - case first { - Ok(_) -> first - Error(_) -> second() - } -} - -/// Combines a list of results into a single result. -/// If all elements in the list are `Ok` then returns an `Ok` holding the list of values. -/// If any element is `Error` then returns the first error. -/// -/// ## Examples -/// -/// ```gleam -/// all([Ok(1), Ok(2)]) -/// // -> Ok([1, 2]) -/// ``` -/// -/// ```gleam -/// all([Ok(1), Error("e")]) -/// // -> Error("e") -/// ``` -/// -pub fn all(results: List(Result(a, e))) -> Result(List(a), e) { - list.try_map(results, fn(result) { result }) -} - -/// Given a list of results, returns a pair where the first element is a list -/// of all the values inside `Ok` and the second element is a list with all the -/// values inside `Error`. The values in both lists appear in reverse order with -/// respect to their position in the original list of results. -/// -/// ## Examples -/// -/// ```gleam -/// partition([Ok(1), Error("a"), Error("b"), Ok(2)]) -/// // -> #([2, 1], ["b", "a"]) -/// ``` -/// -pub fn partition(results: List(Result(a, e))) -> #(List(a), List(e)) { - partition_loop(results, [], []) -} - -fn partition_loop(results: List(Result(a, e)), oks: List(a), errors: List(e)) { - case results { - [] -> #(oks, errors) - [Ok(a), ..rest] -> partition_loop(rest, [a, ..oks], errors) - [Error(e), ..rest] -> partition_loop(rest, oks, [e, ..errors]) - } -} - -/// Replace the value within a result -/// -/// ## Examples -/// -/// ```gleam -/// replace(Ok(1), Nil) -/// // -> Ok(Nil) -/// ``` -/// -/// ```gleam -/// replace(Error(1), Nil) -/// // -> Error(1) -/// ``` -/// -pub fn replace(result: Result(a, e), value: b) -> Result(b, e) { - case result { - Ok(_) -> Ok(value) - Error(error) -> Error(error) - } -} - -/// Replace the error within a result -/// -/// ## Examples -/// -/// ```gleam -/// replace_error(Error(1), Nil) -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// replace_error(Ok(1), Nil) -/// // -> Ok(1) -/// ``` -/// -pub fn replace_error(result: Result(a, e), error: f) -> Result(a, f) { - case result { - Ok(x) -> Ok(x) - Error(_) -> Error(error) - } -} - -/// Given a list of results, returns only the values inside `Ok`. -/// -/// ## Examples -/// -/// ```gleam -/// values([Ok(1), Error("a"), Ok(3)]) -/// // -> [1, 3] -/// ``` -/// -pub fn values(results: List(Result(a, e))) -> List(a) { - list.filter_map(results, fn(result) { result }) -} - -/// Updates a value held within the `Error` of a result by calling a given function -/// on it, where the given function also returns a result. The two results are -/// then merged together into one result. -/// -/// If the result is an `Ok` rather than `Error` the function is not called and the -/// result stays the same. -/// -/// This function is useful for chaining together computations that may fail -/// and trying to recover from possible errors. -/// -/// If you do not need access to the initial error value, use `result.lazy_or`. -/// -/// ## Examples -/// -/// ```gleam -/// Ok(1) |> try_recover(with: fn(_) { Error("failed to recover") }) -/// // -> Ok(1) -/// ``` -/// -/// ```gleam -/// Error(1) |> try_recover(with: fn(error) { Ok(error + 1) }) -/// // -> Ok(2) -/// ``` -/// -/// ```gleam -/// Error(1) |> try_recover(with: fn(error) { Error("failed to recover") }) -/// // -> Error("failed to recover") -/// ``` -/// -pub fn try_recover( - result: Result(a, e), - with fun: fn(e) -> Result(a, f), -) -> Result(a, f) { - case result { - Ok(value) -> Ok(value) - Error(error) -> fun(error) - } -} diff --git a/build/packages/gleam_stdlib/src/gleam/set.gleam b/build/packages/gleam_stdlib/src/gleam/set.gleam deleted file mode 100644 index 6ae5e9e..0000000 --- a/build/packages/gleam_stdlib/src/gleam/set.gleam +++ /dev/null @@ -1,407 +0,0 @@ -import gleam/dict.{type Dict} -import gleam/list -import gleam/result - -// A list is used as the dict value as an empty list has the smallest -// representation in Erlang's binary format -@target(erlang) -type Token = - List(Nil) - -@target(erlang) -const token = [] - -@target(javascript) -type Token = - Nil - -@target(javascript) -const token = Nil - -/// A set is a collection of unique members of the same type. -/// -/// It is implemented using the `gleam/dict` module, so inserts and lookups have -/// logarithmic time complexity. -/// -pub opaque type Set(member) { - Set(dict: Dict(member, Token)) -} - -/// Creates a new empty set. -/// -pub fn new() -> Set(member) { - Set(dict.new()) -} - -/// Gets the number of members in a set. -/// -/// This function runs in constant time. -/// -/// ## Examples -/// -/// ```gleam -/// new() -/// |> insert(1) -/// |> insert(2) -/// |> size -/// // -> 2 -/// ``` -/// -pub fn size(set: Set(member)) -> Int { - dict.size(set.dict) -} - -/// Determines whether or not the set is empty. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> is_empty -/// // -> True -/// ``` -/// -/// ```gleam -/// new() |> insert(1) |> is_empty -/// // -> False -/// ``` -/// -pub fn is_empty(set: Set(member)) -> Bool { - set == new() -} - -/// Inserts an member into the set. -/// -/// This function runs in logarithmic time. -/// -/// ## Examples -/// -/// ```gleam -/// new() -/// |> insert(1) -/// |> insert(2) -/// |> size -/// // -> 2 -/// ``` -/// -pub fn insert(into set: Set(member), this member: member) -> Set(member) { - Set(dict: dict.insert(set.dict, member, token)) -} - -/// Checks whether a set contains a given member. -/// -/// This function runs in logarithmic time. -/// -/// ## Examples -/// -/// ```gleam -/// new() -/// |> insert(2) -/// |> contains(2) -/// // -> True -/// ``` -/// -/// ```gleam -/// new() -/// |> insert(2) -/// |> contains(1) -/// // -> False -/// ``` -/// -pub fn contains(in set: Set(member), this member: member) -> Bool { - set.dict - |> dict.get(member) - |> result.is_ok -} - -/// Removes a member from a set. If the set does not contain the member then -/// the set is returned unchanged. -/// -/// This function runs in logarithmic time. -/// -/// ## Examples -/// -/// ```gleam -/// new() -/// |> insert(2) -/// |> delete(2) -/// |> contains(1) -/// // -> False -/// ``` -/// -pub fn delete(from set: Set(member), this member: member) -> Set(member) { - Set(dict: dict.delete(set.dict, member)) -} - -/// Converts the set into a list of the contained members. -/// -/// The list has no specific ordering, any unintentional ordering may change in -/// future versions of Gleam or Erlang. -/// -/// This function runs in linear time. -/// -/// ## Examples -/// -/// ```gleam -/// new() |> insert(2) |> to_list -/// // -> [2] -/// ``` -/// -pub fn to_list(set: Set(member)) -> List(member) { - dict.keys(set.dict) -} - -/// Creates a new set of the members in a given list. -/// -/// This function runs in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// import gleam/list -/// -/// [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort(by: int.compare) -/// // -> [1, 2, 3, 4] -/// ``` -/// -pub fn from_list(members: List(member)) -> Set(member) { - let dict = - list.fold(over: members, from: dict.new(), with: fn(m, k) { - dict.insert(m, k, token) - }) - Set(dict) -} - -/// Combines all entries into a single value by calling a given function on each -/// one. -/// -/// Sets are not ordered so the values are not returned in any specific order. -/// Do not write code that relies on the order entries are used by this -/// function as it may change in later versions of Gleam or Erlang. -/// -/// # Examples -/// -/// ```gleam -/// from_list([1, 3, 9]) -/// |> fold(0, fn(accumulator, member) { accumulator + member }) -/// // -> 13 -/// ``` -/// -pub fn fold( - over set: Set(member), - from initial: acc, - with reducer: fn(acc, member) -> acc, -) -> acc { - dict.fold(over: set.dict, from: initial, with: fn(a, k, _) { reducer(a, k) }) -} - -/// Creates a new set from an existing set, minus any members that a given -/// function returns `False` for. -/// -/// This function runs in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// import gleam/int -/// -/// from_list([1, 4, 6, 3, 675, 44, 67]) -/// |> filter(keeping: int.is_even) -/// |> to_list -/// // -> [4, 6, 44] -/// ``` -/// -pub fn filter( - in set: Set(member), - keeping predicate: fn(member) -> Bool, -) -> Set(member) { - Set(dict.filter(in: set.dict, keeping: fn(m, _) { predicate(m) })) -} - -/// Creates a new set from a given set with the result of applying the given -/// function to each member. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([1, 2, 3, 4]) -/// |> map(with: fn(x) { x * 2 }) -/// |> to_list -/// // -> [2, 4, 6, 8] -/// ``` -pub fn map(set: Set(member), with fun: fn(member) -> mapped) -> Set(mapped) { - fold(over: set, from: new(), with: fn(acc, member) { - insert(acc, fun(member)) - }) -} - -/// Creates a new set from a given set with all the same entries except any -/// entry found on the given list. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([1, 2, 3, 4]) -/// |> drop([1, 3]) -/// |> to_list -/// // -> [2, 4] -/// ``` -pub fn drop(from set: Set(member), drop disallowed: List(member)) -> Set(member) { - list.fold(over: disallowed, from: set, with: delete) -} - -/// Creates a new set from a given set, only including any members which are in -/// a given list. -/// -/// This function runs in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// from_list([1, 2, 3]) -/// |> take([1, 3, 5]) -/// |> to_list -/// // -> [1, 3] -/// ``` -/// -pub fn take(from set: Set(member), keeping desired: List(member)) -> Set(member) { - Set(dict.take(from: set.dict, keeping: desired)) -} - -/// Creates a new set that contains all members of both given sets. -/// -/// This function runs in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// union(from_list([1, 2]), from_list([2, 3])) |> to_list -/// // -> [1, 2, 3] -/// ``` -/// -pub fn union(of first: Set(member), and second: Set(member)) -> Set(member) { - let #(larger, smaller) = order(first, second) - fold(over: smaller, from: larger, with: insert) -} - -fn order(first: Set(member), second: Set(member)) -> #(Set(member), Set(member)) { - case dict.size(first.dict) > dict.size(second.dict) { - True -> #(first, second) - False -> #(second, first) - } -} - -/// Creates a new set that contains members that are present in both given sets. -/// -/// This function runs in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// intersection(from_list([1, 2]), from_list([2, 3])) |> to_list -/// // -> [2] -/// ``` -/// -pub fn intersection( - of first: Set(member), - and second: Set(member), -) -> Set(member) { - let #(larger, smaller) = order(first, second) - take(from: larger, keeping: to_list(smaller)) -} - -/// Creates a new set that contains members that are present in the first set -/// but not the second. -/// -/// ## Examples -/// -/// ```gleam -/// difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list -/// // -> [1] -/// ``` -/// -pub fn difference( - from first: Set(member), - minus second: Set(member), -) -> Set(member) { - drop(from: first, drop: to_list(second)) -} - -/// Determines if a set is fully contained by another. -/// -/// ## Examples -/// -/// ```gleam -/// is_subset(from_list([1]), from_list([1, 2])) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_subset(from_list([1, 2, 3]), from_list([3, 4, 5])) -/// // -> False -/// ``` -/// -pub fn is_subset(first: Set(member), of second: Set(member)) -> Bool { - intersection(of: first, and: second) == first -} - -/// Determines if two sets contain no common members -/// -/// ## Examples -/// -/// ```gleam -/// is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6])) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5])) -/// // -> False -/// ``` -/// -pub fn is_disjoint(first: Set(member), from second: Set(member)) -> Bool { - intersection(of: first, and: second) == new() -} - -/// Creates a new set that contains members that are present in either set, but -/// not both. -/// -/// ```gleam -/// symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) |> to_list -/// // -> [1, 2, 4] -/// ``` -/// -pub fn symmetric_difference( - of first: Set(member), - and second: Set(member), -) -> Set(member) { - difference( - from: union(of: first, and: second), - minus: intersection(of: first, and: second), - ) -} - -/// Calls a function for each member in a set, discarding the return -/// value. -/// -/// Useful for producing a side effect for every item of a set. -/// -/// ```gleam -/// let set = from_list(["apple", "banana", "cherry"]) -/// -/// each(set, io.println) -/// // -> Nil -/// // apple -/// // banana -/// // cherry -/// ``` -/// -/// The order of elements in the iteration is an implementation detail that -/// should not be relied upon. -/// -pub fn each(set: Set(member), fun: fn(member) -> a) -> Nil { - fold(set, Nil, fn(nil, member) { - fun(member) - nil - }) -} diff --git a/build/packages/gleam_stdlib/src/gleam/string.gleam b/build/packages/gleam_stdlib/src/gleam/string.gleam deleted file mode 100644 index c5945b5..0000000 --- a/build/packages/gleam_stdlib/src/gleam/string.gleam +++ /dev/null @@ -1,900 +0,0 @@ -//// Strings in Gleam are UTF-8 binaries. They can be written in your code as -//// text surrounded by `"double quotes"`. - -import gleam/list -import gleam/option.{type Option, None, Some} -import gleam/order -import gleam/string_tree.{type StringTree} - -/// Determines if a `String` is empty. -/// -/// ## Examples -/// -/// ```gleam -/// is_empty("") -/// // -> True -/// ``` -/// -/// ```gleam -/// is_empty("the world") -/// // -> False -/// ``` -/// -pub fn is_empty(str: String) -> Bool { - str == "" -} - -/// Gets the number of grapheme clusters in a given `String`. -/// -/// This function has to iterate across the whole string to count the number of -/// graphemes, so it runs in linear time. Avoid using this in a loop. -/// -/// ## Examples -/// -/// ```gleam -/// length("Gleam") -/// // -> 5 -/// ``` -/// -/// ```gleam -/// length("ß↑e̊") -/// // -> 3 -/// ``` -/// -/// ```gleam -/// length("") -/// // -> 0 -/// ``` -/// -@external(erlang, "string", "length") -@external(javascript, "../gleam_stdlib.mjs", "string_length") -pub fn length(string: String) -> Int - -/// Reverses a `String`. -/// -/// This function has to iterate across the whole `String` so it runs in linear -/// time. Avoid using this in a loop. -/// -/// ## Examples -/// -/// ```gleam -/// reverse("stressed") -/// // -> "desserts" -/// ``` -/// -pub fn reverse(string: String) -> String { - string - |> string_tree.from_string - |> string_tree.reverse - |> string_tree.to_string -} - -/// Creates a new `String` by replacing all occurrences of a given substring. -/// -/// ## Examples -/// -/// ```gleam -/// replace("www.example.com", each: ".", with: "-") -/// // -> "www-example-com" -/// ``` -/// -/// ```gleam -/// replace("a,b,c,d,e", each: ",", with: "/") -/// // -> "a/b/c/d/e" -/// ``` -/// -pub fn replace( - in string: String, - each pattern: String, - with substitute: String, -) -> String { - string - |> string_tree.from_string - |> string_tree.replace(each: pattern, with: substitute) - |> string_tree.to_string -} - -/// Creates a new `String` with all the graphemes in the input `String` converted to -/// lowercase. -/// -/// Useful for case-insensitive comparisons. -/// -/// ## Examples -/// -/// ```gleam -/// lowercase("X-FILES") -/// // -> "x-files" -/// ``` -/// -@external(erlang, "string", "lowercase") -@external(javascript, "../gleam_stdlib.mjs", "lowercase") -pub fn lowercase(string: String) -> String - -/// Creates a new `String` with all the graphemes in the input `String` converted to -/// uppercase. -/// -/// Useful for case-insensitive comparisons and VIRTUAL YELLING. -/// -/// ## Examples -/// -/// ```gleam -/// uppercase("skinner") -/// // -> "SKINNER" -/// ``` -/// -@external(erlang, "string", "uppercase") -@external(javascript, "../gleam_stdlib.mjs", "uppercase") -pub fn uppercase(string: String) -> String - -/// Compares two `String`s to see which is "larger" by comparing their graphemes. -/// -/// This does not compare the size or length of the given `String`s. -/// -/// ## Examples -/// -/// ```gleam -/// compare("Anthony", "Anthony") -/// // -> order.Eq -/// ``` -/// -/// ```gleam -/// compare("A", "B") -/// // -> order.Lt -/// ``` -/// -pub fn compare(a: String, b: String) -> order.Order { - case a == b { - True -> order.Eq - _ -> - case less_than(a, b) { - True -> order.Lt - False -> order.Gt - } - } -} - -@external(erlang, "gleam_stdlib", "less_than") -@external(javascript, "../gleam_stdlib.mjs", "less_than") -fn less_than(a: String, b: String) -> Bool - -/// Takes a substring given a start grapheme index and a length. Negative indexes -/// are taken starting from the *end* of the list. -/// -/// This function runs in linear time with the size of the index and the -/// length. Negative indexes are linear with the size of the input string in -/// addition to the other costs. -/// -/// ## Examples -/// -/// ```gleam -/// slice(from: "gleam", at_index: 1, length: 2) -/// // -> "le" -/// ``` -/// -/// ```gleam -/// slice(from: "gleam", at_index: 1, length: 10) -/// // -> "leam" -/// ``` -/// -/// ```gleam -/// slice(from: "gleam", at_index: 10, length: 3) -/// // -> "" -/// ``` -/// -/// ```gleam -/// slice(from: "gleam", at_index: -2, length: 2) -/// // -> "am" -/// ``` -/// -/// ```gleam -/// slice(from: "gleam", at_index: -12, length: 2) -/// // -> "" -/// ``` -/// -pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String { - case len <= 0 { - True -> "" - False -> - case idx < 0 { - True -> { - let translated_idx = length(string) + idx - case translated_idx < 0 { - True -> "" - False -> grapheme_slice(string, translated_idx, len) - } - } - False -> grapheme_slice(string, idx, len) - } - } -} - -@external(erlang, "gleam_stdlib", "slice") -@external(javascript, "../gleam_stdlib.mjs", "string_grapheme_slice") -fn grapheme_slice(string: String, index: Int, length: Int) -> String - -@external(erlang, "binary", "part") -@external(javascript, "../gleam_stdlib.mjs", "string_byte_slice") -fn unsafe_byte_slice(string: String, index: Int, length: Int) -> String - -/// Drops contents of the first `String` that occur before the second `String`. -/// If the `from` string does not contain the `before` string, `from` is -/// returned unchanged. -/// -/// ## Examples -/// -/// ```gleam -/// crop(from: "The Lone Gunmen", before: "Lone") -/// // -> "Lone Gunmen" -/// ``` -/// -@external(erlang, "gleam_stdlib", "crop_string") -@external(javascript, "../gleam_stdlib.mjs", "crop_string") -pub fn crop(from string: String, before substring: String) -> String - -/// Drops *n* graphemes from the start of a `String`. -/// -/// This function runs in linear time with the number of graphemes to drop. -/// -/// ## Examples -/// -/// ```gleam -/// drop_start(from: "The Lone Gunmen", up_to: 2) -/// // -> "e Lone Gunmen" -/// ``` -/// -pub fn drop_start(from string: String, up_to num_graphemes: Int) -> String { - case num_graphemes <= 0 { - True -> string - False -> { - let prefix = grapheme_slice(string, 0, num_graphemes) - let prefix_size = byte_size(prefix) - unsafe_byte_slice(string, prefix_size, byte_size(string) - prefix_size) - } - } -} - -/// Drops *n* graphemes from the end of a `String`. -/// -/// This function traverses the full string, so it runs in linear time with the -/// size of the string. Avoid using this in a loop. -/// -/// ## Examples -/// -/// ```gleam -/// drop_end(from: "Cigarette Smoking Man", up_to: 2) -/// // -> "Cigarette Smoking M" -/// ``` -/// -pub fn drop_end(from string: String, up_to num_graphemes: Int) -> String { - case num_graphemes <= 0 { - True -> string - False -> slice(string, 0, length(string) - num_graphemes) - } -} - -/// Checks if the first `String` contains the second. -/// -/// ## Examples -/// -/// ```gleam -/// contains(does: "theory", contain: "ory") -/// // -> True -/// ``` -/// -/// ```gleam -/// contains(does: "theory", contain: "the") -/// // -> True -/// ``` -/// -/// ```gleam -/// contains(does: "theory", contain: "THE") -/// // -> False -/// ``` -/// -@external(erlang, "gleam_stdlib", "contains_string") -@external(javascript, "../gleam_stdlib.mjs", "contains_string") -pub fn contains(does haystack: String, contain needle: String) -> Bool - -/// Checks whether the first `String` starts with the second one. -/// -/// ## Examples -/// -/// ```gleam -/// starts_with("theory", "ory") -/// // -> False -/// ``` -/// -@external(erlang, "gleam_stdlib", "string_starts_with") -@external(javascript, "../gleam_stdlib.mjs", "starts_with") -pub fn starts_with(string: String, prefix: String) -> Bool - -/// Checks whether the first `String` ends with the second one. -/// -/// ## Examples -/// -/// ```gleam -/// ends_with("theory", "ory") -/// // -> True -/// ``` -/// -@external(erlang, "gleam_stdlib", "string_ends_with") -@external(javascript, "../gleam_stdlib.mjs", "ends_with") -pub fn ends_with(string: String, suffix: String) -> Bool - -/// Creates a list of `String`s by splitting a given string on a given substring. -/// -/// ## Examples -/// -/// ```gleam -/// split("home/gleam/desktop/", on: "/") -/// // -> ["home", "gleam", "desktop", ""] -/// ``` -/// -pub fn split(x: String, on substring: String) -> List(String) { - case substring { - "" -> to_graphemes(x) - _ -> - x - |> string_tree.from_string - |> string_tree.split(on: substring) - |> list.map(with: string_tree.to_string) - } -} - -/// Splits a `String` a single time on the given substring. -/// -/// Returns an `Error` if substring not present. -/// -/// ## Examples -/// -/// ```gleam -/// split_once("home/gleam/desktop/", on: "/") -/// // -> Ok(#("home", "gleam/desktop/")) -/// ``` -/// -/// ```gleam -/// split_once("home/gleam/desktop/", on: "?") -/// // -> Error(Nil) -/// ``` -/// -@external(javascript, "../gleam_stdlib.mjs", "split_once") -pub fn split_once( - string: String, - on substring: String, -) -> Result(#(String, String), Nil) { - case erl_split(string, substring) { - [first, rest] -> Ok(#(first, rest)) - _ -> Error(Nil) - } -} - -@external(erlang, "string", "split") -fn erl_split(a: String, b: String) -> List(String) - -/// Creates a new `String` by joining two `String`s together. -/// -/// This function typically copies both `String`s and runs in linear time, but -/// the exact behaviour will depend on how the runtime you are using optimises -/// your code. Benchmark and profile your code if you need to understand its -/// performance better. -/// -/// If you are joining together large string and want to avoid copying any data -/// you may want to investigate using the [`string_tree`](../gleam/string_tree.html) -/// module. -/// -/// ## Examples -/// -/// ```gleam -/// append(to: "butter", suffix: "fly") -/// // -> "butterfly" -/// ``` -/// -pub fn append(to first: String, suffix second: String) -> String { - first <> second -} - -/// Creates a new `String` by joining many `String`s together. -/// -/// This function copies all the `String`s and runs in linear time. -/// -/// ## Examples -/// -/// ```gleam -/// concat(["never", "the", "less"]) -/// // -> "nevertheless" -/// ``` -/// -@external(erlang, "erlang", "list_to_binary") -pub fn concat(strings: List(String)) -> String { - concat_loop(strings, "") -} - -fn concat_loop(strings: List(String), accumulator: String) -> String { - case strings { - [string, ..strings] -> concat_loop(strings, accumulator <> string) - [] -> accumulator - } -} - -/// Creates a new `String` by repeating a `String` a given number of times. -/// -/// This function runs in loglinear time. -/// -/// ## Examples -/// -/// ```gleam -/// repeat("ha", times: 3) -/// // -> "hahaha" -/// ``` -/// -pub fn repeat(string: String, times times: Int) -> String { - case times <= 0 { - True -> "" - False -> repeat_loop(times, string, "") - } -} - -fn repeat_loop(times: Int, doubling_acc: String, acc: String) -> String { - let acc = case times % 2 { - 0 -> acc - _ -> acc <> doubling_acc - } - let times = times / 2 - case times <= 0 { - True -> acc - False -> repeat_loop(times, doubling_acc <> doubling_acc, acc) - } -} - -/// Joins many `String`s together with a given separator. -/// -/// This function runs in linear time. -/// -/// ## Examples -/// -/// ```gleam -/// join(["home","evan","Desktop"], with: "/") -/// // -> "home/evan/Desktop" -/// ``` -/// -pub fn join(strings: List(String), with separator: String) -> String { - case strings { - [] -> "" - [first, ..rest] -> join_loop(rest, separator, first) - } -} - -fn join_loop( - strings: List(String), - separator: String, - accumulator: String, -) -> String { - case strings { - [] -> accumulator - [string, ..strings] -> - join_loop(strings, separator, accumulator <> separator <> string) - } -} - -/// Pads the start of a `String` until it has a given length. -/// -/// ## Examples -/// -/// ```gleam -/// pad_start("121", to: 5, with: ".") -/// // -> "..121" -/// ``` -/// -/// ```gleam -/// pad_start("121", to: 3, with: ".") -/// // -> "121" -/// ``` -/// -/// ```gleam -/// pad_start("121", to: 2, with: ".") -/// // -> "121" -/// ``` -/// -pub fn pad_start( - string: String, - to desired_length: Int, - with pad_string: String, -) -> String { - let current_length = length(string) - let to_pad_length = desired_length - current_length - - case to_pad_length <= 0 { - True -> string - False -> padding(to_pad_length, pad_string) <> string - } -} - -/// Pads the end of a `String` until it has a given length. -/// -/// ## Examples -/// -/// ```gleam -/// pad_end("123", to: 5, with: ".") -/// // -> "123.." -/// ``` -/// -/// ```gleam -/// pad_end("123", to: 3, with: ".") -/// // -> "123" -/// ``` -/// -/// ```gleam -/// pad_end("123", to: 2, with: ".") -/// // -> "123" -/// ``` -/// -pub fn pad_end( - string: String, - to desired_length: Int, - with pad_string: String, -) -> String { - let current_length = length(string) - let to_pad_length = desired_length - current_length - - case to_pad_length <= 0 { - True -> string - False -> string <> padding(to_pad_length, pad_string) - } -} - -fn padding(size: Int, pad_string: String) -> String { - let pad_string_length = length(pad_string) - let num_pads = size / pad_string_length - let extra = size % pad_string_length - - repeat(pad_string, num_pads) <> slice(pad_string, 0, extra) -} - -/// Removes whitespace on both sides of a `String`. -/// -/// Whitespace in this function is the set of nonbreakable whitespace -/// codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1]. -/// -/// [1]: https://unicode.org/reports/tr31/ -/// -/// ## Examples -/// -/// ```gleam -/// trim(" hats \n") -/// // -> "hats" -/// ``` -/// -pub fn trim(string: String) -> String { - string |> trim_start |> trim_end -} - -@external(erlang, "string", "trim") -fn erl_trim(a: String, b: Direction) -> String - -type Direction { - Leading - Trailing -} - -/// Removes whitespace at the start of a `String`. -/// -/// ## Examples -/// -/// ```gleam -/// trim_start(" hats \n") -/// // -> "hats \n" -/// ``` -/// -@external(javascript, "../gleam_stdlib.mjs", "trim_start") -pub fn trim_start(string: String) -> String { - erl_trim(string, Leading) -} - -/// Removes whitespace at the end of a `String`. -/// -/// ## Examples -/// -/// ```gleam -/// trim_end(" hats \n") -/// // -> " hats" -/// ``` -/// -@external(javascript, "../gleam_stdlib.mjs", "trim_end") -pub fn trim_end(string: String) -> String { - erl_trim(string, Trailing) -} - -/// Splits a non-empty `String` into its first element (head) and rest (tail). -/// This lets you pattern match on `String`s exactly as you would with lists. -/// -/// ## Performance -/// -/// There is a notable overhead to using this function, so you may not want to -/// use it in a tight loop. If you wish to efficiently parse a string you may -/// want to use alternatives such as the [splitter package](https://hex.pm/packages/splitter). -/// -/// ## Examples -/// -/// ```gleam -/// pop_grapheme("gleam") -/// // -> Ok(#("g", "leam")) -/// ``` -/// -/// ```gleam -/// pop_grapheme("") -/// // -> Error(Nil) -/// ``` -/// -@external(erlang, "gleam_stdlib", "string_pop_grapheme") -@external(javascript, "../gleam_stdlib.mjs", "pop_grapheme") -pub fn pop_grapheme(string: String) -> Result(#(String, String), Nil) - -/// Converts a `String` to a list of -/// [graphemes](https://en.wikipedia.org/wiki/Grapheme). -/// -/// ```gleam -/// to_graphemes("abc") -/// // -> ["a", "b", "c"] -/// ``` -/// -@external(javascript, "../gleam_stdlib.mjs", "graphemes") -pub fn to_graphemes(string: String) -> List(String) { - string - |> to_graphemes_loop([]) - |> list.reverse -} - -fn to_graphemes_loop(string: String, acc: List(String)) -> List(String) { - case pop_grapheme(string) { - Ok(#(grapheme, rest)) -> to_graphemes_loop(rest, [grapheme, ..acc]) - Error(_) -> acc - } -} - -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "codepoint") -fn unsafe_int_to_utf_codepoint(a: Int) -> UtfCodepoint - -/// Converts a `String` to a `List` of `UtfCodepoint`. -/// -/// See and -/// for an -/// explanation on code points. -/// -/// ## Examples -/// -/// ```gleam -/// "a" |> to_utf_codepoints -/// // -> [UtfCodepoint(97)] -/// ``` -/// -/// ```gleam -/// // Semantically the same as: -/// // ["🏳", "️", "‍", "🌈"] or: -/// // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow] -/// "🏳️‍🌈" |> to_utf_codepoints -/// // -> [ -/// // UtfCodepoint(127987), -/// // UtfCodepoint(65039), -/// // UtfCodepoint(8205), -/// // UtfCodepoint(127752), -/// // ] -/// ``` -/// -pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) { - do_to_utf_codepoints(string) -} - -@target(erlang) -fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { - to_utf_codepoints_loop(<>, []) -} - -@target(erlang) -fn to_utf_codepoints_loop( - bit_array: BitArray, - acc: List(UtfCodepoint), -) -> List(UtfCodepoint) { - case bit_array { - <> -> - to_utf_codepoints_loop(rest, [first, ..acc]) - _ -> list.reverse(acc) - } -} - -@target(javascript) -fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { - string - |> string_to_codepoint_integer_list - |> list.map(unsafe_int_to_utf_codepoint) -} - -@target(javascript) -@external(javascript, "../gleam_stdlib.mjs", "string_to_codepoint_integer_list") -fn string_to_codepoint_integer_list(string: String) -> List(Int) - -/// Converts a `List` of `UtfCodepoint`s to a `String`. -/// -/// See and -/// for an -/// explanation on code points. -/// -/// ## Examples -/// -/// ```gleam -/// let assert Ok(a) = utf_codepoint(97) -/// let assert Ok(b) = utf_codepoint(98) -/// let assert Ok(c) = utf_codepoint(99) -/// from_utf_codepoints([a, b, c]) -/// // -> "abc" -/// ``` -/// -@external(erlang, "gleam_stdlib", "utf_codepoint_list_to_string") -@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_list_to_string") -pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String - -/// Converts an integer to a `UtfCodepoint`. -/// -/// Returns an `Error` if the integer does not represent a valid UTF codepoint. -/// -pub fn utf_codepoint(value: Int) -> Result(UtfCodepoint, Nil) { - case value { - i if i > 1_114_111 -> Error(Nil) - i if i >= 55_296 && i <= 57_343 -> Error(Nil) - i if i < 0 -> Error(Nil) - i -> Ok(unsafe_int_to_utf_codepoint(i)) - } -} - -/// Converts an UtfCodepoint to its ordinal code point value. -/// -/// ## Examples -/// -/// ```gleam -/// let assert [utf_codepoint, ..] = to_utf_codepoints("💜") -/// utf_codepoint_to_int(utf_codepoint) -/// // -> 128156 -/// ``` -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_to_int") -pub fn utf_codepoint_to_int(cp: UtfCodepoint) -> Int - -/// Converts a `String` into `Option(String)` where an empty `String` becomes -/// `None`. -/// -/// ## Examples -/// -/// ```gleam -/// to_option("") -/// // -> None -/// ``` -/// -/// ```gleam -/// to_option("hats") -/// // -> Some("hats") -/// ``` -/// -pub fn to_option(string: String) -> Option(String) { - case string { - "" -> None - _ -> Some(string) - } -} - -/// Returns the first grapheme cluster in a given `String` and wraps it in a -/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. -/// Otherwise, it returns `Ok(String)`. -/// -/// ## Examples -/// -/// ```gleam -/// first("") -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// first("icecream") -/// // -> Ok("i") -/// ``` -/// -pub fn first(string: String) -> Result(String, Nil) { - case pop_grapheme(string) { - Ok(#(first, _)) -> Ok(first) - Error(e) -> Error(e) - } -} - -/// Returns the last grapheme cluster in a given `String` and wraps it in a -/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. -/// Otherwise, it returns `Ok(String)`. -/// -/// This function traverses the full string, so it runs in linear time with the -/// length of the string. Avoid using this in a loop. -/// -/// ## Examples -/// -/// ```gleam -/// last("") -/// // -> Error(Nil) -/// ``` -/// -/// ```gleam -/// last("icecream") -/// // -> Ok("m") -/// ``` -/// -pub fn last(string: String) -> Result(String, Nil) { - case pop_grapheme(string) { - Ok(#(first, "")) -> Ok(first) - Ok(#(_, rest)) -> Ok(slice(rest, -1, 1)) - Error(e) -> Error(e) - } -} - -/// Creates a new `String` with the first grapheme in the input `String` -/// converted to uppercase and the remaining graphemes to lowercase. -/// -/// ## Examples -/// -/// ```gleam -/// capitalise("mamouna") -/// // -> "Mamouna" -/// ``` -/// -pub fn capitalise(string: String) -> String { - case pop_grapheme(string) { - Ok(#(first, rest)) -> append(to: uppercase(first), suffix: lowercase(rest)) - Error(_) -> "" - } -} - -/// Returns a `String` representation of a term in Gleam syntax. -/// -/// This may be occasionally useful for quick-and-dirty printing of values in -/// scripts. For error reporting and other uses prefer constructing strings by -/// pattern matching on the values. -/// -/// ## Limitations -/// -/// The output format of this function is not stable and could change at any -/// time. The output is not suitable for parsing. -/// -/// This function works using runtime reflection, so the output may not be -/// perfectly accurate for data structures where the runtime structure doesn't -/// hold enough information to determine the original syntax. For example, -/// tuples with an Erlang atom in the first position will be mistaken for Gleam -/// records. -/// -/// ## Security and safety -/// -/// There is no limit to how large the strings that this function can produce. -/// Be careful not to call this function with large data structures or you -/// could use very large amounts of memory, potentially causing runtime -/// problems. -/// -pub fn inspect(term: anything) -> String { - term - |> do_inspect - |> string_tree.to_string -} - -@external(erlang, "gleam_stdlib", "inspect") -@external(javascript, "../gleam_stdlib.mjs", "inspect") -fn do_inspect(term: anything) -> StringTree - -/// Returns the number of bytes in a `String`. -/// -/// This function runs in constant time on Erlang and in linear time on -/// JavaScript. -/// -/// ## Examples -/// -/// ```gleam -/// byte_size("🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻") -/// // -> 58 -/// ``` -/// -@external(erlang, "erlang", "byte_size") -@external(javascript, "../gleam_stdlib.mjs", "byte_size") -pub fn byte_size(string: String) -> Int diff --git a/build/packages/gleam_stdlib/src/gleam/string_tree.gleam b/build/packages/gleam_stdlib/src/gleam/string_tree.gleam deleted file mode 100644 index 22937e2..0000000 --- a/build/packages/gleam_stdlib/src/gleam/string_tree.gleam +++ /dev/null @@ -1,208 +0,0 @@ -import gleam/list - -/// `StringTree` is a type used for efficiently building text content to be -/// written to a file or a socket. Internally it is represented as tree so to -/// append or prepend to a string tree is a constant time operation that -/// allocates a new node in the tree without copying any of the content. When -/// writing to an output stream the tree is traversed and the content is sent -/// directly rather than copying it into a single buffer beforehand. -/// -/// On Erlang this type is compatible with Erlang's iodata. On JavaScript this -/// type is compatible with normal strings. -/// -/// The BEAM virtual machine has an optimisation for appending strings, where it -/// will mutate the string buffer when safe to do so, so if you are looking to -/// build a string through appending many small strings then you may get better -/// performance by not using a string tree. Always benchmark your performance -/// sensitive code. -/// -pub type StringTree - -/// Create an empty `StringTree`. Useful as the start of a pipe chaining many -/// trees together. -/// -pub fn new() -> StringTree { - from_strings([]) -} - -/// Prepends a `String` onto the start of some `StringTree`. -/// -/// Runs in constant time. -/// -pub fn prepend(to tree: StringTree, prefix prefix: String) -> StringTree { - append_tree(from_string(prefix), tree) -} - -/// Appends a `String` onto the end of some `StringTree`. -/// -/// Runs in constant time. -/// -pub fn append(to tree: StringTree, suffix second: String) -> StringTree { - append_tree(tree, from_string(second)) -} - -/// Prepends some `StringTree` onto the start of another. -/// -/// Runs in constant time. -/// -pub fn prepend_tree( - to tree: StringTree, - prefix prefix: StringTree, -) -> StringTree { - append_tree(prefix, tree) -} - -/// Appends some `StringTree` onto the end of another. -/// -/// Runs in constant time. -/// -@external(erlang, "gleam_stdlib", "iodata_append") -@external(javascript, "../gleam_stdlib.mjs", "add") -pub fn append_tree(to tree: StringTree, suffix suffix: StringTree) -> StringTree - -/// Converts a list of strings into a `StringTree`. -/// -/// Runs in constant time. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "concat") -pub fn from_strings(strings: List(String)) -> StringTree - -/// Joins a list of trees into a single tree. -/// -/// Runs in constant time. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "concat") -pub fn concat(trees: List(StringTree)) -> StringTree - -/// Converts a string into a `StringTree`. -/// -/// Runs in constant time. -/// -@external(erlang, "gleam_stdlib", "identity") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn from_string(string: String) -> StringTree - -/// Turns a `StringTree` into a `String` -/// -/// This function is implemented natively by the virtual machine and is highly -/// optimised. -/// -@external(erlang, "unicode", "characters_to_binary") -@external(javascript, "../gleam_stdlib.mjs", "identity") -pub fn to_string(tree: StringTree) -> String - -/// Returns the size of the `StringTree` in bytes. -/// -@external(erlang, "erlang", "iolist_size") -@external(javascript, "../gleam_stdlib.mjs", "length") -pub fn byte_size(tree: StringTree) -> Int - -/// Joins the given trees into a new tree separated with the given string. -/// -pub fn join(trees: List(StringTree), with sep: String) -> StringTree { - trees - |> list.intersperse(from_string(sep)) - |> concat -} - -/// Converts a `StringTree` to a new one where the contents have been -/// lowercased. -/// -@external(erlang, "string", "lowercase") -@external(javascript, "../gleam_stdlib.mjs", "lowercase") -pub fn lowercase(tree: StringTree) -> StringTree - -/// Converts a `StringTree` to a new one where the contents have been -/// uppercased. -/// -@external(erlang, "string", "uppercase") -@external(javascript, "../gleam_stdlib.mjs", "uppercase") -pub fn uppercase(tree: StringTree) -> StringTree - -/// Converts a `StringTree` to a new one with the contents reversed. -/// -@external(erlang, "string", "reverse") -pub fn reverse(tree: StringTree) -> StringTree { - tree - |> to_string - |> do_to_graphemes - |> list.reverse - |> from_strings -} - -@external(javascript, "../gleam_stdlib.mjs", "graphemes") -fn do_to_graphemes(string: String) -> List(String) - -type Direction { - All -} - -/// Splits a `StringTree` on a given pattern into a list of trees. -/// -@external(javascript, "../gleam_stdlib.mjs", "split") -pub fn split(tree: StringTree, on pattern: String) -> List(StringTree) { - erl_split(tree, pattern, All) -} - -@external(erlang, "string", "split") -fn erl_split(a: StringTree, b: String, c: Direction) -> List(StringTree) - -/// Replaces all instances of a pattern with a given string substitute. -/// -@external(erlang, "gleam_stdlib", "string_replace") -@external(javascript, "../gleam_stdlib.mjs", "string_replace") -pub fn replace( - in tree: StringTree, - each pattern: String, - with substitute: String, -) -> StringTree - -/// Compares two string trees to determine if they have the same textual -/// content. -/// -/// Comparing two string trees using the `==` operator may return `False` even -/// if they have the same content as they may have been build in different ways, -/// so using this function is often preferred. -/// -/// ## Examples -/// -/// ```gleam -/// from_strings(["a", "b"]) == from_string("ab") -/// // -> False -/// ``` -/// -/// ```gleam -/// is_equal(from_strings(["a", "b"]), from_string("ab")) -/// // -> True -/// ``` -/// -@external(erlang, "string", "equal") -pub fn is_equal(a: StringTree, b: StringTree) -> Bool { - a == b -} - -/// Inspects a `StringTree` to determine if it is equivalent to an empty string. -/// -/// ## Examples -/// -/// ```gleam -/// from_string("ok") |> is_empty -/// // -> False -/// ``` -/// -/// ```gleam -/// from_string("") |> is_empty -/// // -> True -/// ``` -/// -/// ```gleam -/// from_strings([]) |> is_empty -/// // -> True -/// ``` -/// -@external(erlang, "string", "is_empty") -pub fn is_empty(tree: StringTree) -> Bool { - from_string("") == tree -} diff --git a/build/packages/gleam_stdlib/src/gleam/uri.gleam b/build/packages/gleam_stdlib/src/gleam/uri.gleam deleted file mode 100644 index 9413b99..0000000 --- a/build/packages/gleam_stdlib/src/gleam/uri.gleam +++ /dev/null @@ -1,770 +0,0 @@ -//// Utilities for working with URIs -//// -//// This module provides functions for working with URIs (for example, parsing -//// URIs or encoding query strings). The functions in this module are implemented -//// according to [RFC 3986](https://tools.ietf.org/html/rfc3986). -//// -//// Query encoding (Form encoding) is defined in the -//// [W3C specification](https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data). - -import gleam/int -import gleam/list -import gleam/option.{type Option, None, Some} -import gleam/string -import gleam/string_tree.{type StringTree} - -/// Type representing holding the parsed components of an URI. -/// All components of a URI are optional, except the path. -/// -pub type Uri { - Uri( - scheme: Option(String), - userinfo: Option(String), - host: Option(String), - port: Option(Int), - path: String, - query: Option(String), - fragment: Option(String), - ) -} - -/// Constant representing an empty URI, equivalent to "". -/// -/// ## Examples -/// -/// ```gleam -/// let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com")) -/// // -> Uri( -/// // scheme: Some("https"), -/// // userinfo: None, -/// // host: Some("example.com"), -/// // port: None, -/// // path: "", -/// // query: None, -/// // fragment: None, -/// // ) -/// ``` -/// -pub const empty = Uri( - scheme: None, - userinfo: None, - host: None, - port: None, - path: "", - query: None, - fragment: None, -) - -/// Parses a compliant URI string into the `Uri` Type. -/// If the string is not a valid URI string then an error is returned. -/// -/// The opposite operation is `uri.to_string`. -/// -/// ## Examples -/// -/// ```gleam -/// parse("https://example.com:1234/a/b?query=true#fragment") -/// // -> Ok( -/// // Uri( -/// // scheme: Some("https"), -/// // userinfo: None, -/// // host: Some("example.com"), -/// // port: Some(1234), -/// // path: "/a/b", -/// // query: Some("query=true"), -/// // fragment: Some("fragment") -/// // ) -/// // ) -/// ``` -/// -@external(erlang, "gleam_stdlib", "uri_parse") -pub fn parse(uri_string: String) -> Result(Uri, Nil) { - // This parses a uri_string following the regex defined in - // https://tools.ietf.org/html/rfc3986#appendix-B - // - // TODO: This is not perfect and will be more permissive than its Erlang - // counterpart, ideally we want to replicate Erlang's implementation on the js - // target as well. - parse_scheme_loop(uri_string, uri_string, empty, 0) -} - -fn parse_scheme_loop( - original: String, - uri_string: String, - pieces: Uri, - size: Int, -) -> Result(Uri, Nil) { - case uri_string { - // `/` is not allowed to appear in a scheme so we know it's over and we can - // start parsing the authority with slashes. - "/" <> _ if size == 0 -> parse_authority_with_slashes(uri_string, pieces) - "/" <> _ -> { - let scheme = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, scheme: Some(string.lowercase(scheme))) - parse_authority_with_slashes(uri_string, pieces) - } - - // `?` is not allowed to appear in a schemem, in an authority, or in a path; - // so if we see it we know it marks the beginning of the query part. - "?" <> rest if size == 0 -> parse_query_with_question_mark(rest, pieces) - "?" <> rest -> { - let scheme = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, scheme: Some(string.lowercase(scheme))) - parse_query_with_question_mark(rest, pieces) - } - - // `#` is not allowed to appear in a scheme, in an authority, in a path or - // in a query; so if we see it we know it marks the beginning of the final - // fragment. - "#" <> rest if size == 0 -> parse_fragment(rest, pieces) - "#" <> rest -> { - let scheme = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, scheme: Some(string.lowercase(scheme))) - parse_fragment(rest, pieces) - } - - // A colon marks the end of a uri scheme, but if it is not preceded by any - // character then it's not a valid URI. - ":" <> _ if size == 0 -> Error(Nil) - ":" <> rest -> { - let scheme = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, scheme: Some(string.lowercase(scheme))) - parse_authority_with_slashes(rest, pieces) - } - - // If we could get to the end of the string and we've met no special - // chars whatsoever, that means the entire string is just a long path. - "" -> Ok(Uri(..pieces, path: original)) - - // In all other cases the first character is just a valid URI scheme - // character and we just keep munching characters until we reach the end of - // the uri scheme (or the end of the string and that would mean this is not - // a valid uri scheme since we found no `:`). - _ -> { - let #(_, rest) = pop_codeunit(uri_string) - parse_scheme_loop(original, rest, pieces, size + 1) - } - } -} - -fn parse_authority_with_slashes( - uri_string: String, - pieces: Uri, -) -> Result(Uri, Nil) { - case uri_string { - // To be a valid authority the string must start with a `//`, otherwise - // there's no authority and we just skip ahead to parsing the path. - "//" -> Ok(Uri(..pieces, host: Some(""))) - "//" <> rest -> parse_authority_pieces(rest, pieces) - _ -> parse_path(uri_string, pieces) - } -} - -fn parse_authority_pieces(string: String, pieces: Uri) -> Result(Uri, Nil) { - parse_userinfo_loop(string, string, pieces, 0) -} - -fn parse_userinfo_loop( - original: String, - uri_string: String, - pieces: Uri, - size: Int, -) -> Result(Uri, Nil) { - case uri_string { - // `@` marks the end of the userinfo and the start of the host part in the - // authority string. - "@" <> rest if size == 0 -> parse_host(rest, pieces) - "@" <> rest -> { - let userinfo = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, userinfo: Some(userinfo)) - parse_host(rest, pieces) - } - - // If we reach the end of the authority string without finding an `@` - // special character, then we know that the authority doesn't actually - // contain the userinfo part. - // The entire string we just went through was a host! So we parse it as - // such. - "" | "/" <> _ | "?" <> _ | "#" <> _ -> parse_host(original, pieces) - - // In all other cases we just keep munching characters increasing the size - // of the userinfo bit. - _ -> { - let #(_, rest) = pop_codeunit(uri_string) - parse_userinfo_loop(original, rest, pieces, size + 1) - } - } -} - -fn parse_host(uri_string: String, pieces: Uri) -> Result(Uri, Nil) { - // A host string can be in two formats: - // - \[[:.a-zA-Z0-9]*\] - // - [^:] - case uri_string { - // If we find an opening bracket we know it's the first format. - "[" <> _ -> parse_host_within_brackets(uri_string, pieces) - - // A `:` marks the beginning of the port part of the authority string. - ":" <> _ -> { - let pieces = Uri(..pieces, host: Some("")) - parse_port(uri_string, pieces) - } - - // If the string is empty then there's no need to keep going. The host is - // empty. - "" -> Ok(Uri(..pieces, host: Some(""))) - - // Otherwise it's the second format - _ -> parse_host_outside_of_brackets(uri_string, pieces) - } -} - -fn parse_host_within_brackets( - uri_string: String, - pieces: Uri, -) -> Result(Uri, Nil) { - parse_host_within_brackets_loop(uri_string, uri_string, pieces, 0) -} - -fn parse_host_within_brackets_loop( - original: String, - uri_string: String, - pieces: Uri, - size: Int, -) -> Result(Uri, Nil) { - case uri_string { - // If the string is over the entire string we were iterating through is the - // host part. - "" -> Ok(Uri(..pieces, host: Some(uri_string))) - - // A `]` marks the end of the host and the start of the port part. - "]" <> rest if size == 0 -> parse_port(rest, pieces) - "]" <> rest -> { - let host = codeunit_slice(original, at_index: 0, length: size + 1) - let pieces = Uri(..pieces, host: Some(host)) - parse_port(rest, pieces) - } - - // `/` marks the beginning of a path. - "/" <> _ if size == 0 -> parse_path(uri_string, pieces) - "/" <> _ -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_path(uri_string, pieces) - } - - // `?` marks the beginning of the query with question mark. - "?" <> rest if size == 0 -> parse_query_with_question_mark(rest, pieces) - "?" <> rest -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_query_with_question_mark(rest, pieces) - } - - // `#` marks the beginning of the fragment part. - "#" <> rest if size == 0 -> parse_fragment(rest, pieces) - "#" <> rest -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_fragment(rest, pieces) - } - - // In all other cases we just keep iterating. - _ -> { - let #(char, rest) = pop_codeunit(uri_string) - // Inside `[...]` there can only be some characters, if we find a special - // one then we know that we're actually parsing the other format for the - // host and we switch to that! - case is_valid_host_within_brackets_char(char) { - True -> - parse_host_within_brackets_loop(original, rest, pieces, size + 1) - - False -> - parse_host_outside_of_brackets_loop(original, original, pieces, 0) - } - } - } -} - -fn is_valid_host_within_brackets_char(char: Int) -> Bool { - // [0-9] - { 48 >= char && char <= 57 } - // [A-Z] - || { 65 >= char && char <= 90 } - // [a-z] - || { 97 >= char && char <= 122 } - // : - || char == 58 - // . - || char == 46 -} - -fn parse_host_outside_of_brackets( - uri_string: String, - pieces: Uri, -) -> Result(Uri, Nil) { - parse_host_outside_of_brackets_loop(uri_string, uri_string, pieces, 0) -} - -fn parse_host_outside_of_brackets_loop( - original: String, - uri_string: String, - pieces: Uri, - size: Int, -) -> Result(Uri, Nil) { - case uri_string { - "" -> Ok(Uri(..pieces, host: Some(original))) - - // `:` marks the beginning of the port. - ":" <> _ -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_port(uri_string, pieces) - } - - // `/` marks the beginning of a path. - "/" <> _ -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_path(uri_string, pieces) - } - - // `?` marks the beginning of the query with question mark. - "?" <> rest -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_query_with_question_mark(rest, pieces) - } - - // `#` marks the beginning of the fragment part. - "#" <> rest -> { - let host = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, host: Some(host)) - parse_fragment(rest, pieces) - } - - _ -> { - let #(_, rest) = pop_codeunit(uri_string) - parse_host_outside_of_brackets_loop(original, rest, pieces, size + 1) - } - } -} - -fn parse_port(uri_string: String, pieces: Uri) -> Result(Uri, Nil) { - case uri_string { - ":0" <> rest -> parse_port_loop(rest, pieces, 0) - ":1" <> rest -> parse_port_loop(rest, pieces, 1) - ":2" <> rest -> parse_port_loop(rest, pieces, 2) - ":3" <> rest -> parse_port_loop(rest, pieces, 3) - ":4" <> rest -> parse_port_loop(rest, pieces, 4) - ":5" <> rest -> parse_port_loop(rest, pieces, 5) - ":6" <> rest -> parse_port_loop(rest, pieces, 6) - ":7" <> rest -> parse_port_loop(rest, pieces, 7) - ":8" <> rest -> parse_port_loop(rest, pieces, 8) - ":9" <> rest -> parse_port_loop(rest, pieces, 9) - - // The port could be empty and be followed by any of the next delimiters. - // Like `:#`, `:?` or `:/` - ":" | "" -> Ok(pieces) - - // `?` marks the beginning of the query with question mark. - "?" <> rest | ":?" <> rest -> parse_query_with_question_mark(rest, pieces) - - // `#` marks the beginning of the fragment part. - "#" <> rest | ":#" <> rest -> parse_fragment(rest, pieces) - - // `/` marks the beginning of a path. - "/" <> _ -> parse_path(uri_string, pieces) - ":" <> rest -> - case rest { - "/" <> _ -> parse_path(rest, pieces) - _ -> Error(Nil) - } - - _ -> Error(Nil) - } -} - -fn parse_port_loop( - uri_string: String, - pieces: Uri, - port: Int, -) -> Result(Uri, Nil) { - case uri_string { - // As long as we find port numbers we keep accumulating those. - "0" <> rest -> parse_port_loop(rest, pieces, port * 10) - "1" <> rest -> parse_port_loop(rest, pieces, port * 10 + 1) - "2" <> rest -> parse_port_loop(rest, pieces, port * 10 + 2) - "3" <> rest -> parse_port_loop(rest, pieces, port * 10 + 3) - "4" <> rest -> parse_port_loop(rest, pieces, port * 10 + 4) - "5" <> rest -> parse_port_loop(rest, pieces, port * 10 + 5) - "6" <> rest -> parse_port_loop(rest, pieces, port * 10 + 6) - "7" <> rest -> parse_port_loop(rest, pieces, port * 10 + 7) - "8" <> rest -> parse_port_loop(rest, pieces, port * 10 + 8) - "9" <> rest -> parse_port_loop(rest, pieces, port * 10 + 9) - - // `?` marks the beginning of the query with question mark. - "?" <> rest -> { - let pieces = Uri(..pieces, port: Some(port)) - parse_query_with_question_mark(rest, pieces) - } - - // `#` marks the beginning of the fragment part. - "#" <> rest -> { - let pieces = Uri(..pieces, port: Some(port)) - parse_fragment(rest, pieces) - } - - // `/` marks the beginning of a path. - "/" <> _ -> { - let pieces = Uri(..pieces, port: Some(port)) - parse_path(uri_string, pieces) - } - - // The string (and so the port) is over, we return what we parsed so far. - "" -> Ok(Uri(..pieces, port: Some(port))) - - // In all other cases we've ran into some invalid character inside the port - // so the uri is invalid! - _ -> Error(Nil) - } -} - -fn parse_path(uri_string: String, pieces: Uri) -> Result(Uri, Nil) { - parse_path_loop(uri_string, uri_string, pieces, 0) -} - -fn parse_path_loop( - original: String, - uri_string: String, - pieces: Uri, - size: Int, -) -> Result(Uri, Nil) { - case uri_string { - // `?` marks the beginning of the query with question mark. - "?" <> rest -> { - let path = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, path: path) - parse_query_with_question_mark(rest, pieces) - } - - // `#` marks the beginning of the fragment part. - "#" <> rest -> { - let path = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, path: path) - parse_fragment(rest, pieces) - } - - // If the string is over that means the entirety of the string was the path - // and it has an empty query and fragment. - "" -> Ok(Uri(..pieces, path: original)) - - // In all other cases the character is allowed to be part of the path so we - // just keep munching until we reach to its end. - _ -> { - let #(_, rest) = pop_codeunit(uri_string) - parse_path_loop(original, rest, pieces, size + 1) - } - } -} - -fn parse_query_with_question_mark( - uri_string: String, - pieces: Uri, -) -> Result(Uri, Nil) { - parse_query_with_question_mark_loop(uri_string, uri_string, pieces, 0) -} - -fn parse_query_with_question_mark_loop( - original: String, - uri_string: String, - pieces: Uri, - size: Int, -) -> Result(Uri, Nil) { - case uri_string { - // `#` marks the beginning of the fragment part. - "#" <> rest if size == 0 -> parse_fragment(rest, pieces) - "#" <> rest -> { - let query = codeunit_slice(original, at_index: 0, length: size) - let pieces = Uri(..pieces, query: Some(query)) - parse_fragment(rest, pieces) - } - - // If the string is over that means the entirety of the string was the query - // and it has an empty fragment. - "" -> Ok(Uri(..pieces, query: Some(original))) - - // In all other cases the character is allowed to be part of the query so we - // just keep munching until we reach to its end. - _ -> { - let #(_, rest) = pop_codeunit(uri_string) - parse_query_with_question_mark_loop(original, rest, pieces, size + 1) - } - } -} - -fn parse_fragment(rest: String, pieces: Uri) -> Result(Uri, Nil) { - Ok(Uri(..pieces, fragment: Some(rest))) -} - -// WARN: this function returns invalid strings! -// We need to return a String anyways to have this as the representation on the -// JavaScript target. -// Alternatively, we could rewrite the entire code to use a single -// `fold_codeunits`-style loop and a state machine. -@external(erlang, "gleam_stdlib", "string_pop_codeunit") -@external(javascript, "../gleam_stdlib.mjs", "pop_codeunit") -fn pop_codeunit(str: String) -> #(Int, String) - -@external(erlang, "binary", "part") -@external(javascript, "../gleam_stdlib.mjs", "string_codeunit_slice") -fn codeunit_slice(str: String, at_index from: Int, length length: Int) -> String - -/// Parses an urlencoded query string into a list of key value pairs. -/// Returns an error for invalid encoding. -/// -/// The opposite operation is `uri.query_to_string`. -/// -/// ## Examples -/// -/// ```gleam -/// parse_query("a=1&b=2") -/// // -> Ok([#("a", "1"), #("b", "2")]) -/// ``` -/// -@external(erlang, "gleam_stdlib", "parse_query") -@external(javascript, "../gleam_stdlib.mjs", "parse_query") -pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) - -/// Encodes a list of key value pairs as a URI query string. -/// -/// The opposite operation is `uri.parse_query`. -/// -/// ## Examples -/// -/// ```gleam -/// query_to_string([#("a", "1"), #("b", "2")]) -/// // -> "a=1&b=2" -/// ``` -/// -pub fn query_to_string(query: List(#(String, String))) -> String { - query - |> list.map(query_pair) - |> list.intersperse(string_tree.from_string("&")) - |> string_tree.concat - |> string_tree.to_string -} - -fn query_pair(pair: #(String, String)) -> StringTree { - string_tree.from_strings([percent_encode(pair.0), "=", percent_encode(pair.1)]) -} - -/// Encodes a string into a percent encoded representation. -/// -/// ## Examples -/// -/// ```gleam -/// percent_encode("100% great") -/// // -> "100%25%20great" -/// ``` -/// -@external(erlang, "gleam_stdlib", "percent_encode") -@external(javascript, "../gleam_stdlib.mjs", "percent_encode") -pub fn percent_encode(value: String) -> String - -/// Decodes a percent encoded string. -/// -/// ## Examples -/// -/// ```gleam -/// percent_decode("100%25%20great+fun") -/// // -> Ok("100% great+fun") -/// ``` -/// -@external(erlang, "gleam_stdlib", "percent_decode") -@external(javascript, "../gleam_stdlib.mjs", "percent_decode") -pub fn percent_decode(value: String) -> Result(String, Nil) - -/// Splits the path section of a URI into it's constituent segments. -/// -/// Removes empty segments and resolves dot-segments as specified in -/// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC. -/// -/// ## Examples -/// -/// ```gleam -/// path_segments("/users/1") -/// // -> ["users" ,"1"] -/// ``` -/// -pub fn path_segments(path: String) -> List(String) { - remove_dot_segments(string.split(path, "/")) -} - -fn remove_dot_segments(input: List(String)) -> List(String) { - remove_dot_segments_loop(input, []) -} - -fn remove_dot_segments_loop( - input: List(String), - accumulator: List(String), -) -> List(String) { - case input { - [] -> list.reverse(accumulator) - [segment, ..rest] -> { - let accumulator = case segment, accumulator { - "", accumulator -> accumulator - ".", accumulator -> accumulator - "..", [] -> [] - "..", [_, ..accumulator] -> accumulator - segment, accumulator -> [segment, ..accumulator] - } - remove_dot_segments_loop(rest, accumulator) - } - } -} - -/// Encodes a `Uri` value as a URI string. -/// -/// The opposite operation is `uri.parse`. -/// -/// ## Examples -/// -/// ```gleam -/// let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com")) -/// to_string(uri) -/// // -> "https://example.com" -/// ``` -/// -pub fn to_string(uri: Uri) -> String { - let parts = case uri.fragment { - Some(fragment) -> ["#", fragment] - None -> [] - } - let parts = case uri.query { - Some(query) -> ["?", query, ..parts] - None -> parts - } - let parts = [uri.path, ..parts] - let parts = case uri.host, string.starts_with(uri.path, "/") { - Some(host), False if host != "" -> ["/", ..parts] - _, _ -> parts - } - let parts = case uri.host, uri.port { - Some(_), Some(port) -> [":", int.to_string(port), ..parts] - _, _ -> parts - } - let parts = case uri.scheme, uri.userinfo, uri.host { - Some(s), Some(u), Some(h) -> [s, "://", u, "@", h, ..parts] - Some(s), None, Some(h) -> [s, "://", h, ..parts] - Some(s), Some(_), None | Some(s), None, None -> [s, ":", ..parts] - None, None, Some(h) -> ["//", h, ..parts] - _, _, _ -> parts - } - string.concat(parts) -} - -/// Fetches the origin of a URI. -/// -/// Returns the origin of a uri as defined in -/// [RFC 6454](https://tools.ietf.org/html/rfc6454) -/// -/// The supported URI schemes are `http` and `https`. -/// URLs without a scheme will return `Error`. -/// -/// ## Examples -/// -/// ```gleam -/// let assert Ok(uri) = parse("https://example.com/path?foo#bar") -/// origin(uri) -/// // -> Ok("https://example.com") -/// ``` -/// -pub fn origin(uri: Uri) -> Result(String, Nil) { - let Uri(scheme: scheme, host: host, port: port, ..) = uri - case host, scheme { - Some(h), Some("https") if port == Some(443) -> - Ok(string.concat(["https://", h])) - Some(h), Some("http") if port == Some(80) -> - Ok(string.concat(["http://", h])) - Some(h), Some(s) if s == "http" || s == "https" -> { - case port { - Some(p) -> Ok(string.concat([s, "://", h, ":", int.to_string(p)])) - None -> Ok(string.concat([s, "://", h])) - } - } - _, _ -> Error(Nil) - } -} - -/// Resolves a URI with respect to the given base URI. -/// -/// The base URI must be an absolute URI or this function will return an error. -/// The algorithm for merging uris is described in -/// [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2). -/// -pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) { - case base { - Uri(scheme: Some(_), host: Some(_), ..) -> - case relative { - Uri(host: Some(_), ..) -> { - let path = - relative.path - |> string.split("/") - |> remove_dot_segments() - |> join_segments() - let resolved = - Uri( - option.or(relative.scheme, base.scheme), - None, - relative.host, - option.or(relative.port, base.port), - path, - relative.query, - relative.fragment, - ) - Ok(resolved) - } - _ -> { - let #(new_path, new_query) = case relative.path { - "" -> #(base.path, option.or(relative.query, base.query)) - _ -> { - let path_segments = case string.starts_with(relative.path, "/") { - True -> string.split(relative.path, "/") - False -> - base.path - |> string.split("/") - |> drop_last() - |> list.append(string.split(relative.path, "/")) - } - let path = - path_segments - |> remove_dot_segments() - |> join_segments() - #(path, relative.query) - } - } - let resolved = - Uri( - base.scheme, - None, - base.host, - base.port, - new_path, - new_query, - relative.fragment, - ) - Ok(resolved) - } - } - _ -> Error(Nil) - } -} - -fn drop_last(elements: List(a)) -> List(a) { - list.take(from: elements, up_to: list.length(elements) - 1) -} - -fn join_segments(segments: List(String)) -> String { - string.join(["", ..segments], "/") -} diff --git a/build/packages/gleam_stdlib/src/gleam@bit_array.erl b/build/packages/gleam_stdlib/src/gleam@bit_array.erl deleted file mode 100644 index 7df56ce..0000000 --- a/build/packages/gleam_stdlib/src/gleam@bit_array.erl +++ /dev/null @@ -1,347 +0,0 @@ --module(gleam@bit_array). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bit_array.gleam"). --export([from_string/1, bit_size/1, byte_size/1, pad_to_bytes/1, slice/3, is_utf8/1, to_string/1, concat/1, append/2, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1, inspect/1, compare/2, starts_with/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(" BitArrays are a sequence of binary data of any length.\n"). - --file("src/gleam/bit_array.gleam", 11). -?DOC(" Converts a UTF-8 `String` type into a `BitArray`.\n"). --spec from_string(binary()) -> bitstring(). -from_string(X) -> - gleam_stdlib:identity(X). - --file("src/gleam/bit_array.gleam", 17). -?DOC(" Returns an integer which is the number of bits in the bit array.\n"). --spec bit_size(bitstring()) -> integer(). -bit_size(X) -> - erlang:bit_size(X). - --file("src/gleam/bit_array.gleam", 23). -?DOC(" Returns an integer which is the number of bytes in the bit array.\n"). --spec byte_size(bitstring()) -> integer(). -byte_size(X) -> - erlang:byte_size(X). - --file("src/gleam/bit_array.gleam", 29). -?DOC(" Pads a bit array with zeros so that it is a whole number of bytes.\n"). --spec pad_to_bytes(bitstring()) -> bitstring(). -pad_to_bytes(X) -> - gleam_stdlib:bit_array_pad_to_bytes(X). - --file("src/gleam/bit_array.gleam", 54). -?DOC( - " Extracts a sub-section of a bit array.\n" - "\n" - " The slice will start at given position and continue up to specified\n" - " length.\n" - " A negative length can be used to extract bytes at the end of a bit array.\n" - "\n" - " This function runs in constant time.\n" -). --spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | - {error, nil}. -slice(String, Position, Length) -> - gleam_stdlib:bit_array_slice(String, Position, Length). - --file("src/gleam/bit_array.gleam", 67). --spec is_utf8_loop(bitstring()) -> boolean(). -is_utf8_loop(Bits) -> - case Bits of - <<>> -> - true; - - <<_/utf8, Rest/binary>> -> - is_utf8_loop(Rest); - - _ -> - false - end. - --file("src/gleam/bit_array.gleam", 62). -?DOC(" Tests to see whether a bit array is valid UTF-8.\n"). --spec is_utf8(bitstring()) -> boolean(). -is_utf8(Bits) -> - is_utf8_loop(Bits). - --file("src/gleam/bit_array.gleam", 88). -?DOC( - " Converts a bit array to a string.\n" - "\n" - " Returns an error if the bit array is invalid UTF-8 data.\n" -). --spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. -to_string(Bits) -> - case is_utf8(Bits) of - true -> - {ok, gleam_stdlib:identity(Bits)}; - - false -> - {error, nil} - end. - --file("src/gleam/bit_array.gleam", 109). -?DOC( - " Creates a new bit array by joining multiple binaries.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " concat([from_string(\"butter\"), from_string(\"fly\")])\n" - " // -> from_string(\"butterfly\")\n" - " ```\n" -). --spec concat(list(bitstring())) -> bitstring(). -concat(Bit_arrays) -> - gleam_stdlib:bit_array_concat(Bit_arrays). - --file("src/gleam/bit_array.gleam", 40). -?DOC( - " Creates a new bit array by joining two bit arrays.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " append(to: from_string(\"butter\"), suffix: from_string(\"fly\"))\n" - " // -> from_string(\"butterfly\")\n" - " ```\n" -). --spec append(bitstring(), bitstring()) -> bitstring(). -append(First, Second) -> - gleam_stdlib:bit_array_concat([First, Second]). - --file("src/gleam/bit_array.gleam", 118). -?DOC( - " Encodes a BitArray into a base 64 encoded string.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base64_encode(bitstring(), boolean()) -> binary(). -base64_encode(Input, Padding) -> - gleam_stdlib:base64_encode(Input, Padding). - --file("src/gleam/bit_array.gleam", 122). -?DOC(" Decodes a base 64 encoded string into a `BitArray`.\n"). --spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base64_decode(Encoded) -> - Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of - 0 -> - Encoded; - - N -> - gleam@string:append( - Encoded, - gleam@string:repeat(<<"="/utf8>>, 4 - N) - ) - end, - gleam_stdlib:base64_decode(Padded). - --file("src/gleam/bit_array.gleam", 140). -?DOC( - " Encodes a `BitArray` into a base 64 encoded string with URL and filename\n" - " safe alphabet.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base64_url_encode(bitstring(), boolean()) -> binary(). -base64_url_encode(Input, Padding) -> - _pipe = Input, - _pipe@1 = gleam_stdlib:base64_encode(_pipe, Padding), - _pipe@2 = gleam@string:replace(_pipe@1, <<"+"/utf8>>, <<"-"/utf8>>), - gleam@string:replace(_pipe@2, <<"/"/utf8>>, <<"_"/utf8>>). - --file("src/gleam/bit_array.gleam", 150). -?DOC( - " Decodes a base 64 encoded string with URL and filename safe alphabet into a\n" - " `BitArray`.\n" -). --spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base64_url_decode(Encoded) -> - _pipe = Encoded, - _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>), - _pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>), - base64_decode(_pipe@2). - --file("src/gleam/bit_array.gleam", 164). -?DOC( - " Encodes a `BitArray` into a base 16 encoded string.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base16_encode(bitstring()) -> binary(). -base16_encode(Input) -> - gleam_stdlib:base16_encode(Input). - --file("src/gleam/bit_array.gleam", 170). -?DOC(" Decodes a base 16 encoded string into a `BitArray`.\n"). --spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base16_decode(Input) -> - gleam_stdlib:base16_decode(Input). - --file("src/gleam/bit_array.gleam", 191). --spec inspect_loop(bitstring(), binary()) -> binary(). -inspect_loop(Input, Accumulator) -> - case Input of - <<>> -> - Accumulator; - - <> -> - <<<>/binary, - ":size(1)"/utf8>>; - - <> -> - <<<>/binary, - ":size(2)"/utf8>>; - - <> -> - <<<>/binary, - ":size(3)"/utf8>>; - - <> -> - <<<>/binary, - ":size(4)"/utf8>>; - - <> -> - <<<>/binary, - ":size(5)"/utf8>>; - - <> -> - <<<>/binary, - ":size(6)"/utf8>>; - - <> -> - <<<>/binary, - ":size(7)"/utf8>>; - - <> -> - Suffix = case Rest of - <<>> -> - <<""/utf8>>; - - _ -> - <<", "/utf8>> - end, - Accumulator@1 = <<<>/binary, - Suffix/binary>>, - inspect_loop(Rest, Accumulator@1); - - _ -> - Accumulator - end. - --file("src/gleam/bit_array.gleam", 187). -?DOC( - " Converts a bit array to a string containing the decimal value of each byte.\n" - "\n" - " Use this over `string.inspect` when you have a bit array you want printed\n" - " in the array syntax even if it is valid UTF-8.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " inspect(<<0, 20, 0x20, 255>>)\n" - " // -> \"<<0, 20, 32, 255>>\"\n" - "\n" - " inspect(<<100, 5:3>>)\n" - " // -> \"<<100, 5:size(3)>>\"\n" - " ```\n" -). --spec inspect(bitstring()) -> binary(). -inspect(Input) -> - <<(inspect_loop(Input, <<"<<"/utf8>>))/binary, ">>"/utf8>>. - --file("src/gleam/bit_array.gleam", 232). -?DOC( - " Compare two bit arrays as sequences of bytes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(<<1>>, <<2>>)\n" - " // -> Lt\n" - "\n" - " compare(<<\"AB\":utf8>>, <<\"AA\":utf8>>)\n" - " // -> Gt\n" - "\n" - " compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>)\n" - " // -> Eq\n" - " ```\n" -). --spec compare(bitstring(), bitstring()) -> gleam@order:order(). -compare(A, B) -> - case {A, B} of - {<>, - <>} -> - case {First_byte, Second_byte} of - {F, S} when F > S -> - gt; - - {F@1, S@1} when F@1 < S@1 -> - lt; - - {_, _} -> - compare(First_rest, Second_rest) - end; - - {<<>>, <<>>} -> - eq; - - {_, <<>>} -> - gt; - - {<<>>, _} -> - lt; - - {First, Second} -> - case {gleam_stdlib:bit_array_to_int_and_size(First), - gleam_stdlib:bit_array_to_int_and_size(Second)} of - {{A@1, _}, {B@1, _}} when A@1 > B@1 -> - gt; - - {{A@2, _}, {B@2, _}} when A@2 < B@2 -> - lt; - - {{_, Size_a}, {_, Size_b}} when Size_a > Size_b -> - gt; - - {{_, Size_a@1}, {_, Size_b@1}} when Size_a@1 < Size_b@1 -> - lt; - - {_, _} -> - eq - end - end. - --file("src/gleam/bit_array.gleam", 273). -?DOC( - " Checks whether the first `BitArray` starts with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " starts_with(<<1, 2, 3, 4>>, <<1, 2>>)\n" - " // -> True\n" - " ```\n" -). --spec starts_with(bitstring(), bitstring()) -> boolean(). -starts_with(Bits, Prefix) -> - Prefix_size = erlang:bit_size(Prefix), - case Bits of - <> when Pref =:= Prefix -> - true; - - _ -> - false - end. diff --git a/build/packages/gleam_stdlib/src/gleam@bool.erl b/build/packages/gleam_stdlib/src/gleam@bool.erl deleted file mode 100644 index 01307b3..0000000 --- a/build/packages/gleam_stdlib/src/gleam@bool.erl +++ /dev/null @@ -1,352 +0,0 @@ --module(gleam@bool). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bool.gleam"). --export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, to_string/1, guard/3, lazy_guard/3]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " A type with two possible values, `True` and `False`. Used to indicate whether\n" - " things are... true or false!\n" - "\n" - " Often is it clearer and offers more type safety to define a custom type\n" - " than to use `Bool`. For example, rather than having a `is_teacher: Bool`\n" - " field consider having a `role: SchoolRole` field where `SchoolRole` is a custom\n" - " type that can be either `Student` or `Teacher`.\n" -). - --file("src/gleam/bool.gleam", 31). -?DOC( - " Returns the and of two bools, but it evaluates both arguments.\n" - "\n" - " It's the function equivalent of the `&&` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " and(True, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " and(False, True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " False |> and(True)\n" - " // -> False\n" - " ```\n" -). --spec 'and'(boolean(), boolean()) -> boolean(). -'and'(A, B) -> - A andalso B. - --file("src/gleam/bool.gleam", 57). -?DOC( - " Returns the or of two bools, but it evaluates both arguments.\n" - "\n" - " It's the function equivalent of the `||` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " or(True, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " or(False, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " False |> or(True)\n" - " // -> True\n" - " ```\n" -). --spec 'or'(boolean(), boolean()) -> boolean(). -'or'(A, B) -> - A orelse B. - --file("src/gleam/bool.gleam", 77). -?DOC( - " Returns the opposite bool value.\n" - "\n" - " This is the same as the `!` or `not` operators in some other languages.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " negate(False)\n" - " // -> True\n" - " ```\n" -). --spec negate(boolean()) -> boolean(). -negate(Bool) -> - not Bool. - --file("src/gleam/bool.gleam", 105). -?DOC( - " Returns the nor of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " nor(False, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nor(False, True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " nor(True, False)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " nor(True, True)\n" - " // -> False\n" - " ```\n" -). --spec nor(boolean(), boolean()) -> boolean(). -nor(A, B) -> - not (A orelse B). - --file("src/gleam/bool.gleam", 133). -?DOC( - " Returns the nand of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " nand(False, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nand(False, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nand(True, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " nand(True, True)\n" - " // -> False\n" - " ```\n" -). --spec nand(boolean(), boolean()) -> boolean(). -nand(A, B) -> - not (A andalso B). - --file("src/gleam/bool.gleam", 161). -?DOC( - " Returns the exclusive or of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " exclusive_or(False, False)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_or(False, True)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_or(True, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_or(True, True)\n" - " // -> False\n" - " ```\n" -). --spec exclusive_or(boolean(), boolean()) -> boolean(). -exclusive_or(A, B) -> - A /= B. - --file("src/gleam/bool.gleam", 189). -?DOC( - " Returns the exclusive nor of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " exclusive_nor(False, False)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_nor(False, True)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_nor(True, False)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " exclusive_nor(True, True)\n" - " // -> True\n" - " ```\n" -). --spec exclusive_nor(boolean(), boolean()) -> boolean(). -exclusive_nor(A, B) -> - A =:= B. - --file("src/gleam/bool.gleam", 207). -?DOC( - " Returns a string representation of the given bool.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_string(True)\n" - " // -> \"True\"\n" - " ```\n" - "\n" - " ```gleam\n" - " to_string(False)\n" - " // -> \"False\"\n" - " ```\n" -). --spec to_string(boolean()) -> binary(). -to_string(Bool) -> - case Bool of - false -> - <<"False"/utf8>>; - - true -> - <<"True"/utf8>> - end. - --file("src/gleam/bool.gleam", 266). -?DOC( - " Run a callback function if the given bool is `False`, otherwise return a\n" - " default value.\n" - "\n" - " With a `use` expression this function can simulate the early-return pattern\n" - " found in some other programming languages.\n" - "\n" - " In a procedural language:\n" - "\n" - " ```js\n" - " if (predicate) return value;\n" - " // ...\n" - " ```\n" - "\n" - " In Gleam with a `use` expression:\n" - "\n" - " ```gleam\n" - " use <- guard(when: predicate, return: value)\n" - " // ...\n" - " ```\n" - "\n" - " Like everything in Gleam `use` is an expression, so it short circuits the\n" - " current block, not the entire function. As a result you can assign the value\n" - " to a variable:\n" - "\n" - " ```gleam\n" - " let x = {\n" - " use <- guard(when: predicate, return: value)\n" - " // ...\n" - " }\n" - " ```\n" - "\n" - " Note that unlike in procedural languages the `return` value is evaluated\n" - " even when the predicate is `False`, so it is advisable not to perform\n" - " expensive computation nor side-effects there.\n" - "\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let name = \"\"\n" - " use <- guard(when: name == \"\", return: \"Welcome!\")\n" - " \"Hello, \" <> name\n" - " // -> \"Welcome!\"\n" - " ```\n" - "\n" - " ```gleam\n" - " let name = \"Kamaka\"\n" - " use <- guard(when: name == \"\", return: \"Welcome!\")\n" - " \"Hello, \" <> name\n" - " // -> \"Hello, Kamaka\"\n" - " ```\n" -). --spec guard(boolean(), BSY, fun(() -> BSY)) -> BSY. -guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence; - - false -> - Alternative() - end. - --file("src/gleam/bool.gleam", 307). -?DOC( - " Runs a callback function if the given bool is `True`, otherwise runs an\n" - " alternative callback function.\n" - "\n" - " Useful when further computation should be delayed regardless of the given\n" - " bool's value.\n" - "\n" - " See [`guard`](#guard) for more info.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let name = \"Kamaka\"\n" - " let inquiry = fn() { \"How may we address you?\" }\n" - " use <- lazy_guard(when: name == \"\", return: inquiry)\n" - " \"Hello, \" <> name\n" - " // -> \"Hello, Kamaka\"\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " let name = \"\"\n" - " let greeting = fn() { \"Hello, \" <> name }\n" - " use <- lazy_guard(when: name == \"\", otherwise: greeting)\n" - " let number = int.random(99)\n" - " let name = \"User \" <> int.to_string(number)\n" - " \"Welcome, \" <> name\n" - " // -> \"Welcome, User 54\"\n" - " ```\n" -). --spec lazy_guard(boolean(), fun(() -> BSZ), fun(() -> BSZ)) -> BSZ. -lazy_guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence(); - - false -> - Alternative() - end. diff --git a/build/packages/gleam_stdlib/src/gleam@bytes_tree.erl b/build/packages/gleam_stdlib/src/gleam@bytes_tree.erl deleted file mode 100644 index a96eaa2..0000000 --- a/build/packages/gleam_stdlib/src/gleam@bytes_tree.erl +++ /dev/null @@ -1,211 +0,0 @@ --module(gleam@bytes_tree). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bytes_tree.gleam"). --export([append_tree/2, prepend_tree/2, concat/1, new/0, from_string/1, prepend_string/2, append_string/2, from_string_tree/1, from_bit_array/1, prepend/2, append/2, concat_bit_arrays/1, to_bit_array/1, byte_size/1]). --export_type([bytes_tree/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " `BytesTree` is a type used for efficiently building binary content to be\n" - " written to a file or a socket. Internally it is represented as tree so to\n" - " append or prepend to a bytes tree is a constant time operation that\n" - " allocates a new node in the tree without copying any of the content. When\n" - " writing to an output stream the tree is traversed and the content is sent\n" - " directly rather than copying it into a single buffer beforehand.\n" - "\n" - " If we append one bit array to another the bit arrays must be copied to a\n" - " new location in memory so that they can sit together. This behaviour\n" - " enables efficient reading of the data but copying can be expensive,\n" - " especially if we want to join many bit arrays together.\n" - "\n" - " BytesTree is different in that it can be joined together in constant\n" - " time using minimal memory, and then can be efficiently converted to a\n" - " bit array using the `to_bit_array` function.\n" - "\n" - " Byte trees are always byte aligned, so that a number of bits that is not\n" - " divisible by 8 will be padded with 0s.\n" - "\n" - " On Erlang this type is compatible with Erlang's iolists.\n" -). - --opaque bytes_tree() :: {bytes, bitstring()} | - {text, gleam@string_tree:string_tree()} | - {many, list(bytes_tree())}. - --file("src/gleam/bytes_tree.gleam", 68). -?DOC( - " Appends a bytes tree onto the end of another.\n" - "\n" - " Runs in constant time.\n" -). --spec append_tree(bytes_tree(), bytes_tree()) -> bytes_tree(). -append_tree(First, Second) -> - gleam_stdlib:iodata_append(First, Second). - --file("src/gleam/bytes_tree.gleam", 59). -?DOC( - " Prepends a bytes tree onto the start of another.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend_tree(bytes_tree(), bytes_tree()) -> bytes_tree(). -prepend_tree(Second, First) -> - gleam_stdlib:iodata_append(First, Second). - --file("src/gleam/bytes_tree.gleam", 98). -?DOC( - " Joins a list of bytes trees into a single one.\n" - "\n" - " Runs in constant time.\n" -). --spec concat(list(bytes_tree())) -> bytes_tree(). -concat(Trees) -> - gleam_stdlib:identity(Trees). - --file("src/gleam/bytes_tree.gleam", 35). -?DOC( - " Create an empty `BytesTree`. Useful as the start of a pipe chaining many\n" - " trees together.\n" -). --spec new() -> bytes_tree(). -new() -> - gleam_stdlib:identity([]). - --file("src/gleam/bytes_tree.gleam", 118). -?DOC( - " Creates a new bytes tree from a string.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time otherwise.\n" -). --spec from_string(binary()) -> bytes_tree(). -from_string(String) -> - gleam_stdlib:wrap_list(String). - --file("src/gleam/bytes_tree.gleam", 80). -?DOC( - " Prepends a string onto the start of a bytes tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time with the length of the string otherwise.\n" -). --spec prepend_string(bytes_tree(), binary()) -> bytes_tree(). -prepend_string(Second, First) -> - gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). - --file("src/gleam/bytes_tree.gleam", 89). -?DOC( - " Appends a string onto the end of a bytes tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time with the length of the string otherwise.\n" -). --spec append_string(bytes_tree(), binary()) -> bytes_tree(). -append_string(First, Second) -> - gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). - --file("src/gleam/bytes_tree.gleam", 128). -?DOC( - " Creates a new bytes tree from a string tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time otherwise.\n" -). --spec from_string_tree(gleam@string_tree:string_tree()) -> bytes_tree(). -from_string_tree(Tree) -> - gleam_stdlib:wrap_list(Tree). - --file("src/gleam/bytes_tree.gleam", 136). -?DOC( - " Creates a new bytes tree from a bit array.\n" - "\n" - " Runs in constant time.\n" -). --spec from_bit_array(bitstring()) -> bytes_tree(). -from_bit_array(Bits) -> - _pipe = Bits, - _pipe@1 = gleam_stdlib:bit_array_pad_to_bytes(_pipe), - gleam_stdlib:wrap_list(_pipe@1). - --file("src/gleam/bytes_tree.gleam", 43). -?DOC( - " Prepends a bit array to the start of a bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend(bytes_tree(), bitstring()) -> bytes_tree(). -prepend(Second, First) -> - gleam_stdlib:iodata_append(from_bit_array(First), Second). - --file("src/gleam/bytes_tree.gleam", 51). -?DOC( - " Appends a bit array to the end of a bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec append(bytes_tree(), bitstring()) -> bytes_tree(). -append(First, Second) -> - gleam_stdlib:iodata_append(First, from_bit_array(Second)). - --file("src/gleam/bytes_tree.gleam", 106). -?DOC( - " Joins a list of bit arrays into a single bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec concat_bit_arrays(list(bitstring())) -> bytes_tree(). -concat_bit_arrays(Bits) -> - _pipe = Bits, - _pipe@1 = gleam@list:map(_pipe, fun from_bit_array/1), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/bytes_tree.gleam", 162). --spec to_list(list(list(bytes_tree())), list(bitstring())) -> list(bitstring()). -to_list(Stack, Acc) -> - case Stack of - [] -> - Acc; - - [[] | Remaining_stack] -> - to_list(Remaining_stack, Acc); - - [[{bytes, Bits} | Rest] | Remaining_stack@1] -> - to_list([Rest | Remaining_stack@1], [Bits | Acc]); - - [[{text, Tree} | Rest@1] | Remaining_stack@2] -> - Bits@1 = gleam_stdlib:identity(unicode:characters_to_binary(Tree)), - to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]); - - [[{many, Trees} | Rest@2] | Remaining_stack@3] -> - to_list([Trees, Rest@2 | Remaining_stack@3], Acc) - end. - --file("src/gleam/bytes_tree.gleam", 155). -?DOC( - " Turns a bytes tree into a bit array.\n" - "\n" - " Runs in linear time.\n" - "\n" - " When running on Erlang this function is implemented natively by the\n" - " virtual machine and is highly optimised.\n" -). --spec to_bit_array(bytes_tree()) -> bitstring(). -to_bit_array(Tree) -> - erlang:list_to_bitstring(Tree). - --file("src/gleam/bytes_tree.gleam", 186). -?DOC( - " Returns the size of the bytes tree's content in bytes.\n" - "\n" - " Runs in linear time.\n" -). --spec byte_size(bytes_tree()) -> integer(). -byte_size(Tree) -> - erlang:iolist_size(Tree). diff --git a/build/packages/gleam_stdlib/src/gleam@dict.erl b/build/packages/gleam_stdlib/src/gleam@dict.erl deleted file mode 100644 index d496afb..0000000 --- a/build/packages/gleam_stdlib/src/gleam@dict.erl +++ /dev/null @@ -1,561 +0,0 @@ --module(gleam@dict). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dict.gleam"). --export([size/1, is_empty/1, to_list/1, new/0, get/2, has_key/2, insert/3, from_list/1, keys/1, values/1, take/2, merge/2, delete/2, drop/2, upsert/3, fold/3, map_values/2, filter/2, each/2, combine/3]). --export_type([dict/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type dict(KG, KH) :: any() | {gleam_phantom, KG, KH}. - --file("src/gleam/dict.gleam", 36). -?DOC( - " Determines the number of key-value pairs in the dict.\n" - " This function runs in constant time and does not need to iterate the dict.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> size\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"key\", \"value\") |> size\n" - " // -> 1\n" - " ```\n" -). --spec size(dict(any(), any())) -> integer(). -size(Dict) -> - maps:size(Dict). - --file("src/gleam/dict.gleam", 52). -?DOC( - " Determines whether or not the dict is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> is_empty\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"b\", 1) |> is_empty\n" - " // -> False\n" - " ```\n" -). --spec is_empty(dict(any(), any())) -> boolean(). -is_empty(Dict) -> - maps:size(Dict) =:= 0. - --file("src/gleam/dict.gleam", 80). -?DOC( - " Converts the dict to a list of 2-element tuples `#(key, value)`, one for\n" - " each key-value pair in the dict.\n" - "\n" - " The tuples in the list have no specific order.\n" - "\n" - " ## Examples\n" - "\n" - " Calling `to_list` on an empty `dict` returns an empty list.\n" - "\n" - " ```gleam\n" - " new() |> to_list\n" - " // -> []\n" - " ```\n" - "\n" - " The ordering of elements in the resulting list is an implementation detail\n" - " that should not be relied upon.\n" - "\n" - " ```gleam\n" - " new() |> insert(\"b\", 1) |> insert(\"a\", 0) |> insert(\"c\", 2) |> to_list\n" - " // -> [#(\"a\", 0), #(\"b\", 1), #(\"c\", 2)]\n" - " ```\n" -). --spec to_list(dict(KQ, KR)) -> list({KQ, KR}). -to_list(Dict) -> - maps:to_list(Dict). - --file("src/gleam/dict.gleam", 129). -?DOC(" Creates a fresh dict that contains no values.\n"). --spec new() -> dict(any(), any()). -new() -> - maps:new(). - --file("src/gleam/dict.gleam", 150). -?DOC( - " Fetches a value from a dict for a given key.\n" - "\n" - " The dict may not have a value for the key, so the value is wrapped in a\n" - " `Result`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> get(\"a\")\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> get(\"b\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec get(dict(LT, LU), LT) -> {ok, LU} | {error, nil}. -get(From, Get) -> - gleam_stdlib:map_get(From, Get). - --file("src/gleam/dict.gleam", 116). -?DOC( - " Determines whether or not a value present in the dict for a given key.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> has_key(\"a\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> has_key(\"b\")\n" - " // -> False\n" - " ```\n" -). --spec has_key(dict(LH, any()), LH) -> boolean(). -has_key(Dict, Key) -> - maps:is_key(Key, Dict). - --file("src/gleam/dict.gleam", 169). -?DOC( - " Inserts a value into the dict with the given key.\n" - "\n" - " If the dict already has a value for the given key then the value is\n" - " replaced with the new value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0)\n" - " // -> from_list([#(\"a\", 0)])\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(\"a\", 0) |> insert(\"a\", 5)\n" - " // -> from_list([#(\"a\", 5)])\n" - " ```\n" -). --spec insert(dict(LZ, MA), LZ, MA) -> dict(LZ, MA). -insert(Dict, Key, Value) -> - maps:put(Key, Value, Dict). - --file("src/gleam/dict.gleam", 92). --spec from_list_loop(list({LA, LB}), dict(LA, LB)) -> dict(LA, LB). -from_list_loop(List, Initial) -> - case List of - [] -> - Initial; - - [{Key, Value} | Rest] -> - from_list_loop(Rest, insert(Initial, Key, Value)) - end. - --file("src/gleam/dict.gleam", 88). -?DOC( - " Converts a list of 2-element tuples `#(key, value)` to a dict.\n" - "\n" - " If two tuples have the same key the last one in the list will be the one\n" - " that is present in the dict.\n" -). --spec from_list(list({KV, KW})) -> dict(KV, KW). -from_list(List) -> - maps:from_list(List). - --file("src/gleam/dict.gleam", 223). --spec reverse_and_concat(list(NJ), list(NJ)) -> list(NJ). -reverse_and_concat(Remaining, Accumulator) -> - case Remaining of - [] -> - Accumulator; - - [First | Rest] -> - reverse_and_concat(Rest, [First | Accumulator]) - end. - --file("src/gleam/dict.gleam", 216). --spec do_keys_loop(list({NE, any()}), list(NE)) -> list(NE). -do_keys_loop(List, Acc) -> - case List of - [] -> - reverse_and_concat(Acc, []); - - [{Key, _} | Rest] -> - do_keys_loop(Rest, [Key | Acc]) - end. - --file("src/gleam/dict.gleam", 212). -?DOC( - " Gets a list of all keys in a given dict.\n" - "\n" - " Dicts are not ordered so the keys are not returned in any specific order. Do\n" - " not write code that relies on the order keys are returned by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> keys\n" - " // -> [\"a\", \"b\"]\n" - " ```\n" -). --spec keys(dict(MZ, any())) -> list(MZ). -keys(Dict) -> - maps:keys(Dict). - --file("src/gleam/dict.gleam", 249). --spec do_values_loop(list({any(), NT}), list(NT)) -> list(NT). -do_values_loop(List, Acc) -> - case List of - [] -> - reverse_and_concat(Acc, []); - - [{_, Value} | Rest] -> - do_values_loop(Rest, [Value | Acc]) - end. - --file("src/gleam/dict.gleam", 244). -?DOC( - " Gets a list of all values in a given dict.\n" - "\n" - " Dicts are not ordered so the values are not returned in any specific order. Do\n" - " not write code that relies on the order values are returned by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> values\n" - " // -> [0, 1]\n" - " ```\n" -). --spec values(dict(any(), NO)) -> list(NO). -values(Dict) -> - maps:values(Dict). - --file("src/gleam/dict.gleam", 318). --spec do_take_loop(dict(OX, OY), list(OX), dict(OX, OY)) -> dict(OX, OY). -do_take_loop(Dict, Desired_keys, Acc) -> - Insert = fun(Taken, Key) -> case gleam_stdlib:map_get(Dict, Key) of - {ok, Value} -> - insert(Taken, Key, Value); - - {error, _} -> - Taken - end end, - case Desired_keys of - [] -> - Acc; - - [First | Rest] -> - do_take_loop(Dict, Rest, Insert(Acc, First)) - end. - --file("src/gleam/dict.gleam", 309). -?DOC( - " Creates a new dict from a given dict, only including any entries for which the\n" - " keys are in a given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> take([\"b\"])\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> take([\"a\", \"b\", \"c\"])\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec take(dict(OJ, OK), list(OJ)) -> dict(OJ, OK). -take(Dict, Desired_keys) -> - maps:with(Desired_keys, Dict). - --file("src/gleam/dict.gleam", 363). --spec insert_pair(dict(PV, PW), {PV, PW}) -> dict(PV, PW). -insert_pair(Dict, Pair) -> - insert(Dict, erlang:element(1, Pair), erlang:element(2, Pair)). - --file("src/gleam/dict.gleam", 356). --spec fold_inserts(list({PO, PP}), dict(PO, PP)) -> dict(PO, PP). -fold_inserts(New_entries, Dict) -> - case New_entries of - [] -> - Dict; - - [First | Rest] -> - fold_inserts(Rest, insert_pair(Dict, First)) - end. - --file("src/gleam/dict.gleam", 350). -?DOC( - " Creates a new dict from a pair of given dicts by combining their entries.\n" - "\n" - " If there are entries with the same keys in both dicts the entry from the\n" - " second dict takes precedence.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " let b = from_list([#(\"b\", 2), #(\"c\", 3)])\n" - " merge(a, b)\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 2), #(\"c\", 3)])\n" - " ```\n" -). --spec merge(dict(PG, PH), dict(PG, PH)) -> dict(PG, PH). -merge(Dict, New_entries) -> - maps:merge(Dict, New_entries). - --file("src/gleam/dict.gleam", 382). -?DOC( - " Creates a new dict from a given dict with all the same entries except for the\n" - " one with a given key, if it exists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"a\")\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"c\")\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec delete(dict(QB, QC), QB) -> dict(QB, QC). -delete(Dict, Key) -> - maps:remove(Key, Dict). - --file("src/gleam/dict.gleam", 410). -?DOC( - " Creates a new dict from a given dict with all the same entries except any with\n" - " keys found in a given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\"])\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"c\"])\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\", \"b\", \"c\"])\n" - " // -> from_list([])\n" - " ```\n" -). --spec drop(dict(QN, QO), list(QN)) -> dict(QN, QO). -drop(Dict, Disallowed_keys) -> - case Disallowed_keys of - [] -> - Dict; - - [First | Rest] -> - drop(delete(Dict, First), Rest) - end. - --file("src/gleam/dict.gleam", 440). -?DOC( - " Creates a new dict with one entry inserted or updated using a given function.\n" - "\n" - " If there was not an entry in the dict for the given key then the function\n" - " gets `None` as its argument, otherwise it gets `Some(value)`.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " let dict = from_list([#(\"a\", 0)])\n" - " let increment = fn(x) {\n" - " case x {\n" - " Some(i) -> i + 1\n" - " None -> 0\n" - " }\n" - " }\n" - "\n" - " upsert(dict, \"a\", increment)\n" - " // -> from_list([#(\"a\", 1)])\n" - "\n" - " upsert(dict, \"b\", increment)\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 0)])\n" - " ```\n" -). --spec upsert(dict(QU, QV), QU, fun((gleam@option:option(QV)) -> QV)) -> dict(QU, QV). -upsert(Dict, Key, Fun) -> - case gleam_stdlib:map_get(Dict, Key) of - {ok, Value} -> - insert(Dict, Key, Fun({some, Value})); - - {error, _} -> - insert(Dict, Key, Fun(none)) - end. - --file("src/gleam/dict.gleam", 484). --spec fold_loop(list({RG, RH}), RJ, fun((RJ, RG, RH) -> RJ)) -> RJ. -fold_loop(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [{K, V} | Rest] -> - fold_loop(Rest, Fun(Initial, K, V), Fun) - end. - --file("src/gleam/dict.gleam", 476). -?DOC( - " Combines all entries into a single value by calling a given function on each\n" - " one.\n" - "\n" - " Dicts are not ordered so the values are not returned in any specific order. Do\n" - " not write code that relies on the order entries are used by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n" - " fold(dict, 0, fn(accumulator, key, value) { accumulator + value })\n" - " // -> 13\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/string\n" - "\n" - " let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n" - " fold(dict, \"\", fn(accumulator, key, value) {\n" - " string.append(accumulator, key)\n" - " })\n" - " // -> \"abc\"\n" - " ```\n" -). --spec fold(dict(RB, RC), RF, fun((RF, RB, RC) -> RF)) -> RF. -fold(Dict, Initial, Fun) -> - fold_loop(maps:to_list(Dict), Initial, Fun). - --file("src/gleam/dict.gleam", 188). -?DOC( - " Updates all values in a given dict by calling a given function on each key\n" - " and value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(3, 3), #(2, 4)])\n" - " |> map_values(fn(key, value) { key * value })\n" - " // -> from_list([#(3, 9), #(2, 8)])\n" - " ```\n" -). --spec map_values(dict(ML, MM), fun((ML, MM) -> MP)) -> dict(ML, MP). -map_values(Dict, Fun) -> - maps:map(Fun, Dict). - --file("src/gleam/dict.gleam", 273). -?DOC( - " Creates a new dict from a given dict, minus any entries that a given function\n" - " returns `False` for.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> filter(fn(key, value) { value != 0 })\n" - " // -> from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> filter(fn(key, value) { True })\n" - " // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec filter(dict(NX, NY), fun((NX, NY) -> boolean())) -> dict(NX, NY). -filter(Dict, Predicate) -> - maps:filter(Predicate, Dict). - --file("src/gleam/dict.gleam", 517). -?DOC( - " Calls a function for each key and value in a dict, discarding the return\n" - " value.\n" - "\n" - " Useful for producing a side effect for every item of a dict.\n" - "\n" - " ```gleam\n" - " import gleam/io\n" - "\n" - " let dict = from_list([#(\"a\", \"apple\"), #(\"b\", \"banana\"), #(\"c\", \"cherry\")])\n" - "\n" - " each(dict, fn(k, v) {\n" - " io.println(key <> \" => \" <> value)\n" - " })\n" - " // -> Nil\n" - " // a => apple\n" - " // b => banana\n" - " // c => cherry\n" - " ```\n" - "\n" - " The order of elements in the iteration is an implementation detail that\n" - " should not be relied upon.\n" -). --spec each(dict(RK, RL), fun((RK, RL) -> any())) -> nil. -each(Dict, Fun) -> - fold( - Dict, - nil, - fun(Nil, K, V) -> - Fun(K, V), - Nil - end - ). - --file("src/gleam/dict.gleam", 538). -?DOC( - " Creates a new dict from a pair of given dicts by combining their entries.\n" - "\n" - " If there are entries with the same keys in both dicts the given function is\n" - " used to determine the new value to use in the resulting dict.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " let b = from_list([#(\"a\", 2), #(\"c\", 3)])\n" - " combine(a, b, fn(one, other) { one + other })\n" - " // -> from_list([#(\"a\", 2), #(\"b\", 1), #(\"c\", 3)])\n" - " ```\n" -). --spec combine(dict(RP, RQ), dict(RP, RQ), fun((RQ, RQ) -> RQ)) -> dict(RP, RQ). -combine(Dict, Other, Fun) -> - fold( - Dict, - Other, - fun(Acc, Key, Value) -> case gleam_stdlib:map_get(Acc, Key) of - {ok, Other_value} -> - insert(Acc, Key, Fun(Value, Other_value)); - - {error, _} -> - insert(Acc, Key, Value) - end end - ). diff --git a/build/packages/gleam_stdlib/src/gleam@dynamic.erl b/build/packages/gleam_stdlib/src/gleam@dynamic.erl deleted file mode 100644 index f057ca2..0000000 --- a/build/packages/gleam_stdlib/src/gleam@dynamic.erl +++ /dev/null @@ -1,106 +0,0 @@ --module(gleam@dynamic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dynamic.gleam"). --export([classify/1, bool/1, string/1, float/1, int/1, bit_array/1, list/1, array/1, properties/1, nil/0]). --export_type([dynamic_/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type dynamic_() :: any(). - --file("src/gleam/dynamic.gleam", 30). -?DOC( - " Return a string indicating the type of the dynamic value.\n" - "\n" - " This function may be useful for constructing error messages or logs. If you\n" - " want to turn dynamic data into well typed data then you want the\n" - " `gleam/dynamic/decode` module.\n" - "\n" - " ```gleam\n" - " classify(string(\"Hello\"))\n" - " // -> \"String\"\n" - " ```\n" -). --spec classify(dynamic_()) -> binary(). -classify(Data) -> - gleam_stdlib:classify_dynamic(Data). - --file("src/gleam/dynamic.gleam", 36). -?DOC(" Create a dynamic value from a bool.\n"). --spec bool(boolean()) -> dynamic_(). -bool(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 44). -?DOC( - " Create a dynamic value from a string.\n" - "\n" - " On Erlang this will be a binary string rather than a character list.\n" -). --spec string(binary()) -> dynamic_(). -string(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 50). -?DOC(" Create a dynamic value from a float.\n"). --spec float(float()) -> dynamic_(). -float(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 56). -?DOC(" Create a dynamic value from an int.\n"). --spec int(integer()) -> dynamic_(). -int(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 62). -?DOC(" Create a dynamic value from a bit array.\n"). --spec bit_array(bitstring()) -> dynamic_(). -bit_array(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 68). -?DOC(" Create a dynamic value from a list.\n"). --spec list(list(dynamic_())) -> dynamic_(). -list(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 77). -?DOC( - " Create a dynamic value from a list, converting it to a sequential runtime\n" - " format rather than the regular list format.\n" - "\n" - " On Erlang this will be a tuple, on JavaScript this will be an array.\n" -). --spec array(list(dynamic_())) -> dynamic_(). -array(A) -> - erlang:list_to_tuple(A). - --file("src/gleam/dynamic.gleam", 85). -?DOC( - " Create a dynamic value made an unordered series of keys and values, where\n" - " the keys are unique.\n" - "\n" - " On Erlang this will be a map, on JavaScript this will be a Gleam dict\n" - " object.\n" -). --spec properties(list({dynamic_(), dynamic_()})) -> dynamic_(). -properties(Entries) -> - gleam_stdlib:identity(maps:from_list(Entries)). - --file("src/gleam/dynamic.gleam", 94). -?DOC( - " A dynamic value representing nothing.\n" - "\n" - " On Erlang this will be the atom `nil`, on JavaScript this will be\n" - " `undefined`.\n" -). --spec nil() -> dynamic_(). -nil() -> - gleam_stdlib:identity(nil). diff --git a/build/packages/gleam_stdlib/src/gleam@dynamic@decode.erl b/build/packages/gleam_stdlib/src/gleam@dynamic@decode.erl deleted file mode 100644 index bf4b951..0000000 --- a/build/packages/gleam_stdlib/src/gleam@dynamic@decode.erl +++ /dev/null @@ -1,1088 +0,0 @@ --module(gleam@dynamic@decode). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dynamic/decode.gleam"). --export([run/2, success/1, decode_dynamic/1, map/2, map_errors/2, then/2, one_of/2, recursive/1, optional/1, decode_error/2, decode_bool/1, decode_int/1, decode_float/1, decode_bit_array/1, collapse_errors/2, failure/2, new_primitive_decoder/2, decode_string/1, dict/2, list/1, subfield/3, at/2, field/3, optional_field/4, optionally_at/3]). --export_type([decode_error/0, decoder/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " The `Dynamic` type is used to represent dynamically typed data. That is, data\n" - " that we don't know the precise type of yet, so we need to introspect the data to\n" - " see if it is of the desired type before we can use it. Typically data like this\n" - " would come from user input or from untyped languages such as Erlang or JavaScript.\n" - "\n" - " This module provides the `Decoder` type and associated functions, which provides\n" - " a type-safe and composable way to convert dynamic data into some desired type,\n" - " or into errors if the data doesn't have the desired structure.\n" - "\n" - " The `Decoder` type is generic and has 1 type parameter, which is the type that\n" - " it attempts to decode. A `Decoder(String)` can be used to decode strings, and a\n" - " `Decoder(Option(Int))` can be used to decode `Option(Int)`s\n" - "\n" - " Decoders work using _runtime reflection_ and the data structures of the target\n" - " platform. Differences between Erlang and JavaScript data structures may impact\n" - " your decoders, so it is important to test your decoders on all supported\n" - " platforms.\n" - "\n" - " The decoding technique used by this module was inspired by Juraj Petráš'\n" - " [Toy](https://github.com/Hackder/toy), Go's `encoding/json`, and Elm's\n" - " `Json.Decode`. Thank you to them!\n" - "\n" - " # Examples\n" - "\n" - " Dynamic data may come from various sources and so many different syntaxes could\n" - " be used to describe or construct them. In these examples a pseudocode\n" - " syntax is used to describe the data.\n" - "\n" - " ## Simple types\n" - "\n" - " This module defines decoders for simple data types such as [`string`](#string),\n" - " [`int`](#int), [`float`](#float), [`bit_array`](#bit_array), and [`bool`](#bool).\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // \"Hello, Joe!\"\n" - "\n" - " let result = decode.run(data, decode.string)\n" - " assert result == Ok(\"Hello, Joe!\")\n" - " ```\n" - "\n" - " ## Lists\n" - "\n" - " The [`list`](#list) decoder decodes `List`s. To use it you must construct it by\n" - " passing in another decoder into the `list` function, which is the decoder that\n" - " is to be used for the elements of the list, type checking both the list and its\n" - " elements.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // [1, 2, 3, 4]\n" - "\n" - " let result = decode.run(data, decode.list(decode.int))\n" - " assert result == Ok([1, 2, 3, 4])\n" - " ```\n" - "\n" - " On Erlang this decoder can decode from lists, and on JavaScript it can\n" - " decode from lists as well as JavaScript arrays.\n" - "\n" - " ## Options\n" - "\n" - " The [`optional`](#optional) decoder is used to decode values that may or may not\n" - " be present. In other environment these might be called \"nullable\" values.\n" - "\n" - " Like the `list` decoder, the `optional` decoder takes another decoder,\n" - " which is used to decode the value if it is present.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // 12.45\n" - "\n" - " let result = decode.run(data, decode.optional(decode.float))\n" - " assert result == Ok(option.Some(12.45))\n" - " ```\n" - " ```gleam\n" - " // Data:\n" - " // null\n" - "\n" - " let result = decode.run(data, decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" - "\n" - " This decoder knows how to handle multiple different runtime representations of\n" - " absent values, including `Nil`, `None`, `null`, and `undefined`.\n" - "\n" - " ## Dicts\n" - "\n" - " The [`dict`](#dict) decoder decodes `Dicts` and contains two other decoders, one\n" - " for the keys, one for the values.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // { \"Lucy\" -> 10, \"Nubi\" -> 20 }\n" - "\n" - " let result = decode.run(data, decode.dict(decode.string, decode.int))\n" - " assert result == Ok(dict.from_list([\n" - " #(\"Lucy\", 10),\n" - " #(\"Nubi\", 20),\n" - " ]))\n" - " ```\n" - "\n" - " ## Indexing objects\n" - "\n" - " The [`at`](#at) decoder can be used to decode a value that is nested within\n" - " key-value containers such as Gleam dicts, Erlang maps, or JavaScript objects.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // { \"one\" -> { \"two\" -> 123 } }\n" - "\n" - " let result = decode.run(data, decode.at([\"one\", \"two\"], decode.int))\n" - " assert result == Ok(123)\n" - " ```\n" - "\n" - " ## Indexing arrays\n" - "\n" - " If you use ints as keys then the [`at`](#at) decoder can be used to index into\n" - " array-like containers such as Gleam or Erlang tuples, or JavaScript arrays.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // [\"one\", \"two\", \"three\"]\n" - "\n" - " let result = decode.run(data, decode.at([1], decode.string))\n" - " assert result == Ok(\"two\")\n" - " ```\n" - "\n" - " ## Records\n" - "\n" - " Decoding records from dynamic data is more complex and requires combining a\n" - " decoder for each field and a special constructor that builds your records with\n" - " the decoded field values.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // {\n" - " // \"score\" -> 180,\n" - " // \"name\" -> \"Mel Smith\",\n" - " // \"is-admin\" -> false,\n" - " // \"enrolled\" -> true,\n" - " // \"colour\" -> \"Red\",\n" - " // }\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use score <- decode.field(\"score\", decode.int)\n" - " use colour <- decode.field(\"colour\", decode.string)\n" - " use enrolled <- decode.field(\"enrolled\", decode.bool)\n" - " decode.success(Player(name:, score:, colour:, enrolled:))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(Player(\"Mel Smith\", 180, \"Red\", True))\n" - " ```\n" - "\n" - " ## Enum variants\n" - "\n" - " Imagine you have a custom type where all the variants do not contain any values.\n" - "\n" - " ```gleam\n" - " pub type PocketMonsterType {\n" - " Fire\n" - " Water\n" - " Grass\n" - " Electric\n" - " }\n" - " ```\n" - "\n" - " You might choose to encode these variants as strings, `\"fire\"` for `Fire`,\n" - " `\"water\"` for `Water`, and so on. To decode them you'll need to decode the dynamic\n" - " data as a string, but then you'll need to decode it further still as not all\n" - " strings are valid values for the enum. This can be done with the `then`\n" - " function, which enables running a second decoder after the first one\n" - " succeeds.\n" - "\n" - " ```gleam\n" - " let decoder = {\n" - " use decoded_string <- decode.then(decode.string)\n" - " case decoded_string {\n" - " // Return succeeding decoders for valid strings\n" - " \"fire\" -> decode.success(Fire)\n" - " \"water\" -> decode.success(Water)\n" - " \"grass\" -> decode.success(Grass)\n" - " \"electric\" -> decode.success(Electric)\n" - " // Return a failing decoder for any other strings\n" - " _ -> decode.failure(Fire, \"PocketMonsterType\")\n" - " }\n" - " }\n" - "\n" - " let result = decode.run(dynamic.string(\"water\"), decoder)\n" - " assert result == Ok(Water)\n" - "\n" - " let result = decode.run(dynamic.string(\"wobble\"), decoder)\n" - " assert result == Error([DecodeError(\"PocketMonsterType\", \"String\", [])])\n" - " ```\n" - "\n" - " ## Record variants\n" - "\n" - " Decoding type variants that contain other values is done by combining the\n" - " techniques from the \"enum variants\" and \"records\" examples. Imagine you have\n" - " this custom type that you want to decode:\n" - "\n" - " ```gleam\n" - " pub type PocketMonsterPerson {\n" - " Trainer(name: String, badge_count: Int)\n" - " GymLeader(name: String, speciality: PocketMonsterType)\n" - " }\n" - " ```\n" - " And you would like to be able to decode these from dynamic data like this:\n" - " ```erlang\n" - " {\n" - " \"type\" -> \"trainer\",\n" - " \"name\" -> \"Ash\",\n" - " \"badge-count\" -> 1,\n" - " }\n" - " ```\n" - " ```erlang\n" - " {\n" - " \"type\" -> \"gym-leader\",\n" - " \"name\" -> \"Misty\",\n" - " \"speciality\" -> \"water\",\n" - " }\n" - " ```\n" - "\n" - " Notice how both documents have a `\"type\"` field, which is used to indicate which\n" - " variant the data is for.\n" - "\n" - " First, define decoders for each of the variants:\n" - "\n" - " ```gleam\n" - " let trainer_decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use badge_count <- decode.field(\"badge-count\", decode.int)\n" - " decode.success(Trainer(name, badge_count))\n" - " }\n" - "\n" - " let gym_leader_decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use speciality <- decode.field(\"speciality\", pocket_monster_type_decoder)\n" - " decode.success(GymLeader(name, speciality))\n" - " }\n" - " ```\n" - "\n" - " A third decoder can be used to extract and decode the `\"type\"` field, and the\n" - " expression can evaluate to whichever decoder is suitable for the document.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // {\n" - " // \"type\" -> \"gym-leader\",\n" - " // \"name\" -> \"Misty\",\n" - " // \"speciality\" -> \"water\",\n" - " // }\n" - "\n" - " let decoder = {\n" - " use tag <- decode.field(\"type\", decode.string)\n" - " case tag {\n" - " \"gym-leader\" -> gym_leader_decoder\n" - " _ -> trainer_decoder\n" - " }\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(GymLeader(\"Misty\", Water))\n" - " ```\n" -). - --type decode_error() :: {decode_error, binary(), binary(), list(binary())}. - --opaque decoder(BUW) :: {decoder, - fun((gleam@dynamic:dynamic_()) -> {BUW, list(decode_error())})}. - --file("src/gleam/dynamic/decode.gleam", 356). -?DOC( - " Run a decoder on a `Dynamic` value, decoding the value if it is of the\n" - " desired type, or returning errors.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = {\n" - " use name <- decode.field(\"email\", decode.string)\n" - " use email <- decode.field(\"password\", decode.string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " decode.run(data, decoder)\n" - " ```\n" -). --spec run(gleam@dynamic:dynamic_(), decoder(BVE)) -> {ok, BVE} | - {error, list(decode_error())}. -run(Data, Decoder) -> - {Maybe_invalid_data, Errors} = (erlang:element(2, Decoder))(Data), - case Errors of - [] -> - {ok, Maybe_invalid_data}; - - [_ | _] -> - {error, Errors} - end. - --file("src/gleam/dynamic/decode.gleam", 479). -?DOC( - " Finalise a decoder having successfully extracted a value.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.field(\"email\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" -). --spec success(BWF) -> decoder(BWF). -success(Data) -> - {decoder, fun(_) -> {Data, []} end}. - --file("src/gleam/dynamic/decode.gleam", 718). --spec decode_dynamic(gleam@dynamic:dynamic_()) -> {gleam@dynamic:dynamic_(), - list(decode_error())}. -decode_dynamic(Data) -> - {Data, []}. - --file("src/gleam/dynamic/decode.gleam", 875). -?DOC( - " Apply a transformation function to any value decoded by the decoder.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.int |> decode.map(int.to_string)\n" - " let result = decode.run(dynamic.int(1000), decoder)\n" - " assert result == Ok(\"1000\")\n" - " ```\n" -). --spec map(decoder(BZC), fun((BZC) -> BZE)) -> decoder(BZE). -map(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Transformer(Data), Errors} - end}. - --file("src/gleam/dynamic/decode.gleam", 884). -?DOC(" Apply a transformation function to any errors returned by the decoder.\n"). --spec map_errors( - decoder(BZG), - fun((list(decode_error())) -> list(decode_error())) -) -> decoder(BZG). -map_errors(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Data, Transformer(Errors)} - end}. - --file("src/gleam/dynamic/decode.gleam", 922). -?DOC( - " Create a new decoder based upon the value of a previous decoder.\n" - "\n" - " This may be useful to run one previous decoder to use in further decoding.\n" -). --spec then(decoder(BZO), fun((BZO) -> decoder(BZQ))) -> decoder(BZQ). -then(Decoder, Next) -> - {decoder, - fun(Dynamic_data) -> - {Data, Errors} = (erlang:element(2, Decoder))(Dynamic_data), - Decoder@1 = Next(Data), - {Data@1, _} = Layer = (erlang:element(2, Decoder@1))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - {Data@1, Errors} - end - end}. - --file("src/gleam/dynamic/decode.gleam", 965). --spec run_decoders( - gleam@dynamic:dynamic_(), - {BZY, list(decode_error())}, - list(decoder(BZY)) -) -> {BZY, list(decode_error())}. -run_decoders(Data, Failure, Decoders) -> - case Decoders of - [] -> - Failure; - - [Decoder | Decoders@1] -> - {_, Errors} = Layer = (erlang:element(2, Decoder))(Data), - case Errors of - [] -> - Layer; - - [_ | _] -> - run_decoders(Data, Failure, Decoders@1) - end - end. - --file("src/gleam/dynamic/decode.gleam", 952). -?DOC( - " Create a new decoder from several other decoders. Each of the inner\n" - " decoders is run in turn, and the value from the first to succeed is used.\n" - "\n" - " If no decoder succeeds then the errors from the first decoder is used.\n" - " If you wish for different errors then you may wish to use the\n" - " `collapse_errors` or `map_errors` functions.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.one_of(decode.string, or: [\n" - " decode.int |> decode.map(int.to_string),\n" - " decode.float |> decode.map(float.to_string),\n" - " ])\n" - " decode.run(dynamic.int(1000), decoder)\n" - " // -> Ok(\"1000\")\n" - " ```\n" -). --spec one_of(decoder(BZT), list(decoder(BZT))) -> decoder(BZT). -one_of(First, Alternatives) -> - {decoder, - fun(Dynamic_data) -> - {_, Errors} = Layer = (erlang:element(2, First))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - run_decoders(Dynamic_data, Layer, Alternatives) - end - end}. - --file("src/gleam/dynamic/decode.gleam", 1048). -?DOC( - " Create a decoder that can refer to itself, useful for decoding deeply\n" - " nested data.\n" - "\n" - " Attempting to create a recursive decoder without this function could result\n" - " in an infinite loop. If you are using `field` or other `use`able functions\n" - " then you may not need to use this function.\n" - "\n" - " ```gleam\n" - " type Nested {\n" - " Nested(List(Nested))\n" - " Value(String)\n" - " }\n" - "\n" - " fn nested_decoder() -> decode.Decoder(Nested) {\n" - " use <- decode.recursive\n" - " decode.one_of(decode.string |> decode.map(Value), [\n" - " decode.list(nested_decoder()) |> decode.map(Nested),\n" - " ])\n" - " }\n" - " ```\n" -). --spec recursive(fun(() -> decoder(CAJ))) -> decoder(CAJ). -recursive(Inner) -> - {decoder, - fun(Data) -> - Decoder = Inner(), - (erlang:element(2, Decoder))(Data) - end}. - --file("src/gleam/dynamic/decode.gleam", 853). -?DOC( - " A decoder that decodes nullable values of a type decoded by with a given\n" - " decoder.\n" - "\n" - " This function can handle common representations of null on all runtimes, such as\n" - " `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on\n" - " JavaScript.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.int(100), decode.optional(decode.int))\n" - " assert result == Ok(option.Some(100))\n" - " ```\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.nil(), decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" -). --spec optional(decoder(BYY)) -> decoder(gleam@option:option(BYY)). -optional(Inner) -> - {decoder, fun(Data) -> case gleam_stdlib:is_null(Data) of - true -> - {none, []}; - - false -> - {Data@1, Errors} = (erlang:element(2, Inner))(Data), - {{some, Data@1}, Errors} - end end}. - --file("src/gleam/dynamic/decode.gleam", 485). -?DOC(" Construct a decode error for some unexpected dynamic data.\n"). --spec decode_error(binary(), gleam@dynamic:dynamic_()) -> list(decode_error()). -decode_error(Expected, Found) -> - [{decode_error, Expected, gleam_stdlib:classify_dynamic(Found), []}]. - --file("src/gleam/dynamic/decode.gleam", 609). --spec run_dynamic_function( - gleam@dynamic:dynamic_(), - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, BWZ} | {error, BWZ}) -) -> {BWZ, list(decode_error())}. -run_dynamic_function(Data, Name, F) -> - case F(Data) of - {ok, Data@1} -> - {Data@1, []}; - - {error, Zero} -> - {Zero, - [{decode_error, Name, gleam_stdlib:classify_dynamic(Data), []}]} - end. - --file("src/gleam/dynamic/decode.gleam", 658). --spec decode_bool(gleam@dynamic:dynamic_()) -> {boolean(), list(decode_error())}. -decode_bool(Data) -> - case gleam_stdlib:identity(true) =:= Data of - true -> - {true, []}; - - false -> - case gleam_stdlib:identity(false) =:= Data of - true -> - {false, []}; - - false -> - {false, decode_error(<<"Bool"/utf8>>, Data)} - end - end. - --file("src/gleam/dynamic/decode.gleam", 680). --spec decode_int(gleam@dynamic:dynamic_()) -> {integer(), list(decode_error())}. -decode_int(Data) -> - run_dynamic_function(Data, <<"Int"/utf8>>, fun gleam_stdlib:int/1). - --file("src/gleam/dynamic/decode.gleam", 699). --spec decode_float(gleam@dynamic:dynamic_()) -> {float(), list(decode_error())}. -decode_float(Data) -> - run_dynamic_function(Data, <<"Float"/utf8>>, fun gleam_stdlib:float/1). - --file("src/gleam/dynamic/decode.gleam", 733). --spec decode_bit_array(gleam@dynamic:dynamic_()) -> {bitstring(), - list(decode_error())}. -decode_bit_array(Data) -> - run_dynamic_function( - Data, - <<"BitArray"/utf8>>, - fun gleam_stdlib:bit_array/1 - ). - --file("src/gleam/dynamic/decode.gleam", 908). -?DOC( - " Replace all errors produced by a decoder with one single error for a named\n" - " expected type.\n" - "\n" - " This function may be useful if you wish to simplify errors before\n" - " presenting them to a user, particularly when using the `one_of` function.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.string |> decode.collapse_errors(\"MyThing\")\n" - " let result = decode.run(dynamic.int(1000), decoder)\n" - " assert result == Error([DecodeError(\"MyThing\", \"Int\", [])])\n" - " ```\n" -). --spec collapse_errors(decoder(BZL), binary()) -> decoder(BZL). -collapse_errors(Decoder, Name) -> - {decoder, - fun(Dynamic_data) -> - {Data, Errors} = Layer = (erlang:element(2, Decoder))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - {Data, decode_error(Name, Dynamic_data)} - end - end}. - --file("src/gleam/dynamic/decode.gleam", 986). -?DOC( - " Define a decoder that always fails. The parameter for this function is the\n" - " name of the type that has failed to decode.\n" -). --spec failure(CAD, binary()) -> decoder(CAD). -failure(Zero, Expected) -> - {decoder, fun(D) -> {Zero, decode_error(Expected, D)} end}. - --file("src/gleam/dynamic/decode.gleam", 1015). -?DOC( - " Create a decoder for a new data type from a decoding function.\n" - "\n" - " This function is used for new primitive types. For example, you might\n" - " define a decoder for Erlang's pid type.\n" - "\n" - " A default \"zero\" value is also required to make a decoder. When this\n" - " decoder is used as part of a larger decoder this zero value used as\n" - " a placeholder so that the rest of the decoder can continue to run and\n" - " collect all decoding errors.\n" - "\n" - " If you were to make a decoder for the `String` type (rather than using the\n" - " build-in `string` decoder) you would define it like so:\n" - "\n" - " ```gleam\n" - " pub fn string_decoder() -> decode.Decoder(String) {\n" - " let default = \"\"\n" - " decode.new_primitive_decoder(\"String\", fn(data) {\n" - " case dynamic.string(data) {\n" - " Ok(x) -> Ok(x)\n" - " Error(_) -> Error(default)\n" - " }\n" - " })\n" - " }\n" - " ```\n" -). --spec new_primitive_decoder( - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, CAF} | {error, CAF}) -) -> decoder(CAF). -new_primitive_decoder(Name, Decoding_function) -> - {decoder, fun(D) -> case Decoding_function(D) of - {ok, T} -> - {T, []}; - - {error, Zero} -> - {Zero, - [{decode_error, - Name, - gleam_stdlib:classify_dynamic(D), - []}]} - end end}. - --file("src/gleam/dynamic/decode.gleam", 636). --spec dynamic_string(gleam@dynamic:dynamic_()) -> {ok, binary()} | - {error, binary()}. -dynamic_string(Data) -> - case gleam_stdlib:bit_array(Data) of - {ok, Data@1} -> - case gleam@bit_array:to_string(Data@1) of - {ok, String} -> - {ok, String}; - - {error, _} -> - {error, <<""/utf8>>} - end; - - {error, _} -> - {error, <<""/utf8>>} - end. - --file("src/gleam/dynamic/decode.gleam", 631). --spec decode_string(gleam@dynamic:dynamic_()) -> {binary(), - list(decode_error())}. -decode_string(Data) -> - run_dynamic_function(Data, <<"String"/utf8>>, fun dynamic_string/1). - --file("src/gleam/dynamic/decode.gleam", 807). --spec fold_dict( - {gleam@dict:dict(BYK, BYL), list(decode_error())}, - gleam@dynamic:dynamic_(), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_()) -> {BYK, list(decode_error())}), - fun((gleam@dynamic:dynamic_()) -> {BYL, list(decode_error())}) -) -> {gleam@dict:dict(BYK, BYL), list(decode_error())}. -fold_dict(Acc, Key, Value, Key_decoder, Value_decoder) -> - case Key_decoder(Key) of - {Key@1, []} -> - case Value_decoder(Value) of - {Value@1, []} -> - Dict = gleam@dict:insert( - erlang:element(1, Acc), - Key@1, - Value@1 - ), - {Dict, erlang:element(2, Acc)}; - - {_, Errors} -> - push_path({maps:new(), Errors}, [<<"values"/utf8>>]) - end; - - {_, Errors@1} -> - push_path({maps:new(), Errors@1}, [<<"keys"/utf8>>]) - end. - --file("src/gleam/dynamic/decode.gleam", 787). -?DOC( - " A decoder that decodes dicts where all keys and vales are decoded with\n" - " given decoders.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let values = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.int(1)),\n" - " #(dynamic.string(\"two\"), dynamic.int(2)),\n" - " ])\n" - "\n" - " let result =\n" - " decode.run(values, decode.dict(decode.string, decode.int))\n" - " assert result == Ok(values)\n" - " ```\n" -). --spec dict(decoder(BYD), decoder(BYF)) -> decoder(gleam@dict:dict(BYD, BYF)). -dict(Key, Value) -> - {decoder, fun(Data) -> case gleam_stdlib:dict(Data) of - {error, _} -> - {maps:new(), decode_error(<<"Dict"/utf8>>, Data)}; - - {ok, Dict} -> - gleam@dict:fold( - Dict, - {maps:new(), []}, - fun(A, K, V) -> case erlang:element(2, A) of - [] -> - fold_dict( - A, - K, - V, - erlang:element(2, Key), - erlang:element(2, Value) - ); - - [_ | _] -> - A - end end - ) - end end}. - --file("src/gleam/dynamic/decode.gleam", 755). -?DOC( - " A decoder that decodes lists where all elements are decoded with a given\n" - " decoder.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let result =\n" - " [1, 2, 3]\n" - " |> list.map(dynamic.int)\n" - " |> dynamic.list\n" - " |> decode.run(decode.list(of: decode.int))\n" - " assert result == Ok([1, 2, 3])\n" - " ```\n" -). --spec list(decoder(BXR)) -> decoder(list(BXR)). -list(Inner) -> - {decoder, - fun(Data) -> - gleam_stdlib:list( - Data, - erlang:element(2, Inner), - fun(P, K) -> push_path(P, [K]) end, - 0, - [] - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 439). --spec push_path({BWA, list(decode_error())}, list(any())) -> {BWA, - list(decode_error())}. -push_path(Layer, Path) -> - Decoder = one_of( - {decoder, fun decode_string/1}, - [begin - _pipe = {decoder, fun decode_int/1}, - map(_pipe, fun erlang:integer_to_binary/1) - end] - ), - Path@1 = gleam@list:map( - Path, - fun(Key) -> - Key@1 = gleam_stdlib:identity(Key), - case run(Key@1, Decoder) of - {ok, Key@2} -> - Key@2; - - {error, _} -> - <<<<"<"/utf8, - (gleam_stdlib:classify_dynamic(Key@1))/binary>>/binary, - ">"/utf8>> - end - end - ), - Errors = gleam@list:map( - erlang:element(2, Layer), - fun(Error) -> - {decode_error, - erlang:element(2, Error), - erlang:element(3, Error), - lists:append(Path@1, erlang:element(4, Error))} - end - ), - {erlang:element(1, Layer), Errors}. - --file("src/gleam/dynamic/decode.gleam", 403). --spec index( - list(BVO), - list(BVO), - fun((gleam@dynamic:dynamic_()) -> {BVR, list(decode_error())}), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_(), list(BVO)) -> {BVR, list(decode_error())}) -) -> {BVR, list(decode_error())}. -index(Path, Position, Inner, Data, Handle_miss) -> - case Path of - [] -> - _pipe = Data, - _pipe@1 = Inner(_pipe), - push_path(_pipe@1, lists:reverse(Position)); - - [Key | Path@1] -> - case gleam_stdlib:index(Data, Key) of - {ok, {some, Data@1}} -> - index(Path@1, [Key | Position], Inner, Data@1, Handle_miss); - - {ok, none} -> - Handle_miss(Data, [Key | Position]); - - {error, Kind} -> - {Default, _} = Inner(Data), - _pipe@2 = {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]}, - push_path(_pipe@2, lists:reverse(Position)) - end - end. - --file("src/gleam/dynamic/decode.gleam", 324). -?DOC( - " The same as [`field`](#field), except taking a path to the value rather\n" - " than a field name.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"data\"), dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ])\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.subfield([\"data\", \"name\"], decode.string)\n" - " use email <- decode.subfield([\"data\", \"email\"], decode.string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" -). --spec subfield(list(any()), decoder(BUZ), fun((BUZ) -> decoder(BVB))) -> decoder(BVB). -subfield(Field_path, Field_decoder, Next) -> - {decoder, - fun(Data) -> - {Out, Errors1} = index( - Field_path, - [], - erlang:element(2, Field_decoder), - Data, - fun(Data@1, Position) -> - {Default, _} = (erlang:element(2, Field_decoder))(Data@1), - _pipe = {Default, - [{decode_error, - <<"Field"/utf8>>, - <<"Nothing"/utf8>>, - []}]}, - push_path(_pipe, lists:reverse(Position)) - end - ), - {Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data), - {Out@1, lists:append(Errors1, Errors2)} - end}. - --file("src/gleam/dynamic/decode.gleam", 393). -?DOC( - " A decoder that decodes a value that is nested within other values. For\n" - " example, decoding a value that is within some deeply nested JSON objects.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.at([\"one\", \"two\"], decode.int)\n" - "\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.properties([\n" - " #(dynamic.string(\"two\"), dynamic.int(1000)),\n" - " ])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(1000)\n" - " ```\n" - "\n" - " ```gleam\n" - " dynamic.nil()\n" - " |> decode.run(decode.optional(decode.int))\n" - " // -> Ok(option.None)\n" - " ```\n" -). --spec at(list(any()), decoder(BVL)) -> decoder(BVL). -at(Path, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(Data@1, Position) -> - {Default, _} = (erlang:element(2, Inner))(Data@1), - _pipe = {Default, - [{decode_error, - <<"Field"/utf8>>, - <<"Nothing"/utf8>>, - []}]}, - push_path(_pipe, lists:reverse(Position)) - end - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 524). -?DOC( - " Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n" - " of the desired type, or returning errors. An error is returned if there is\n" - " no field for the specified key.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.field(\"email\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" - "\n" - " If you wish to decode a value that is more deeply nested within the dynamic\n" - " data, see [`subfield`](#subfield) and [`at`](#at).\n" - "\n" - " If you wish to return a default in the event that a field is not present,\n" - " see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at).\n" -). --spec field(any(), decoder(BWJ), fun((BWJ) -> decoder(BWL))) -> decoder(BWL). -field(Field_name, Field_decoder, Next) -> - subfield([Field_name], Field_decoder, Next). - --file("src/gleam/dynamic/decode.gleam", 557). -?DOC( - " Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n" - " of the desired type, or returning errors. The given default value is\n" - " returned if there is no field for the specified key.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ]))\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.optional_field(\"email\", \"n/a\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"n/a\"))\n" - " ```\n" -). --spec optional_field(any(), BWP, decoder(BWP), fun((BWP) -> decoder(BWR))) -> decoder(BWR). -optional_field(Key, Default, Field_decoder, Next) -> - {decoder, - fun(Data) -> - {Out, Errors1} = begin - _pipe = case gleam_stdlib:index(Data, Key) of - {ok, {some, Data@1}} -> - (erlang:element(2, Field_decoder))(Data@1); - - {ok, none} -> - {Default, []}; - - {error, Kind} -> - {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]} - end, - push_path(_pipe, [Key]) - end, - {Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data), - {Out@1, lists:append(Errors1, Errors2)} - end}. - --file("src/gleam/dynamic/decode.gleam", 599). -?DOC( - " A decoder that decodes a value that is nested within other values. For\n" - " example, decoding a value that is within some deeply nested JSON objects.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.optionally_at([\"one\", \"two\"], 100, decode.int)\n" - "\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.properties([])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(100)\n" - " ```\n" -). --spec optionally_at(list(any()), BWW, decoder(BWW)) -> decoder(BWW). -optionally_at(Path, Default, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(_, _) -> {Default, []} end - ) - end}. diff --git a/build/packages/gleam_stdlib/src/gleam@float.erl b/build/packages/gleam_stdlib/src/gleam@float.erl deleted file mode 100644 index 6b55b47..0000000 --- a/build/packages/gleam_stdlib/src/gleam@float.erl +++ /dev/null @@ -1,744 +0,0 @@ --module(gleam@float). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/float.gleam"). --export([parse/1, to_string/1, compare/2, min/2, max/2, clamp/3, ceiling/1, floor/1, truncate/1, absolute_value/1, loosely_compare/3, loosely_equals/3, power/2, square_root/1, negate/1, round/1, to_precision/2, sum/1, product/1, random/0, modulo/2, divide/2, add/2, multiply/2, subtract/2, logarithm/1, exponential/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Functions for working with floats.\n" - "\n" - " ## Float representation\n" - "\n" - " Floats are represented as 64 bit floating point numbers on both the Erlang\n" - " and JavaScript runtimes. The floating point behaviour is native to their\n" - " respective runtimes, so their exact behaviour will be slightly different on\n" - " the two runtimes.\n" - "\n" - " ### Infinity and NaN\n" - "\n" - " Under the JavaScript runtime, exceeding the maximum (or minimum)\n" - " representable value for a floating point value will result in Infinity (or\n" - " -Infinity). Should you try to divide two infinities you will get NaN as a\n" - " result.\n" - "\n" - " When running on BEAM, exceeding the maximum (or minimum) representable\n" - " value for a floating point value will raise an error.\n" - "\n" - " ## Division by zero\n" - "\n" - " Gleam runs on the Erlang virtual machine, which does not follow the IEEE\n" - " 754 standard for floating point arithmetic and does not have an `Infinity`\n" - " value. In Erlang division by zero results in a crash, however Gleam does\n" - " not have partial functions and operators in core so instead division by zero\n" - " returns zero, a behaviour taken from Pony, Coq, and Lean.\n" - "\n" - " This may seem unexpected at first, but it is no less mathematically valid\n" - " than crashing or returning a special value. Division by zero is undefined\n" - " in mathematics.\n" -). - --file("src/gleam/float.gleam", 51). -?DOC( - " Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was\n" - " not possible.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse(\"2.3\")\n" - " // -> Ok(2.3)\n" - " ```\n" - "\n" - " ```gleam\n" - " parse(\"ABC\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec parse(binary()) -> {ok, float()} | {error, nil}. -parse(String) -> - gleam_stdlib:parse_float(String). - --file("src/gleam/float.gleam", 64). -?DOC( - " Returns the string representation of the provided `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_string(2.3)\n" - " // -> \"2.3\"\n" - " ```\n" -). --spec to_string(float()) -> binary(). -to_string(X) -> - gleam_stdlib:float_to_string(X). - --file("src/gleam/float.gleam", 95). -?DOC( - " Compares two `Float`s, returning an `Order`:\n" - " `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(2.0, 2.3)\n" - " // -> Lt\n" - " ```\n" - "\n" - " To handle\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems)\n" - " you may use [`loosely_compare`](#loosely_compare) instead.\n" -). --spec compare(float(), float()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - false -> - case A < B of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/float.gleam", 176). -?DOC( - " Compares two `Float`s, returning the smaller of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " min(2.0, 2.3)\n" - " // -> 2.0\n" - " ```\n" -). --spec min(float(), float()) -> float(). -min(A, B) -> - case A < B of - true -> - A; - - false -> - B - end. - --file("src/gleam/float.gleam", 192). -?DOC( - " Compares two `Float`s, returning the larger of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " max(2.0, 2.3)\n" - " // -> 2.3\n" - " ```\n" -). --spec max(float(), float()) -> float(). -max(A, B) -> - case A > B of - true -> - A; - - false -> - B - end. - --file("src/gleam/float.gleam", 75). -?DOC( - " Restricts a `Float` between a lower and upper bound.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " clamp(1.2, min: 1.4, max: 1.6)\n" - " // -> 1.4\n" - " ```\n" -). --spec clamp(float(), float(), float()) -> float(). -clamp(X, Min_bound, Max_bound) -> - _pipe = X, - _pipe@1 = min(_pipe, Max_bound), - max(_pipe@1, Min_bound). - --file("src/gleam/float.gleam", 210). -?DOC( - " Rounds the value to the next highest whole number as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " ceiling(2.3)\n" - " // -> 3.0\n" - " ```\n" -). --spec ceiling(float()) -> float(). -ceiling(X) -> - math:ceil(X). - --file("src/gleam/float.gleam", 223). -?DOC( - " Rounds the value to the next lowest whole number as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " floor(2.3)\n" - " // -> 2.0\n" - " ```\n" -). --spec floor(float()) -> float(). -floor(X) -> - math:floor(X). - --file("src/gleam/float.gleam", 261). -?DOC( - " Returns the value as an `Int`, truncating all decimal digits.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " truncate(2.4343434847383438)\n" - " // -> 2\n" - " ```\n" -). --spec truncate(float()) -> integer(). -truncate(X) -> - erlang:trunc(X). - --file("src/gleam/float.gleam", 311). -?DOC( - " Returns the absolute value of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " absolute_value(-12.5)\n" - " // -> 12.5\n" - " ```\n" - "\n" - " ```gleam\n" - " absolute_value(10.2)\n" - " // -> 10.2\n" - " ```\n" -). --spec absolute_value(float()) -> float(). -absolute_value(X) -> - case X >= +0.0 of - true -> - X; - - false -> - +0.0 - X - end. - --file("src/gleam/float.gleam", 125). -?DOC( - " Compares two `Float`s within a tolerance, returning an `Order`:\n" - " `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n" - "\n" - " This function allows Float comparison while handling\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n" - "\n" - " Notice: For `Float`s the tolerance won't be exact:\n" - " `5.3 - 5.0` is not exactly `0.3`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " loosely_compare(5.0, with: 5.3, tolerating: 0.5)\n" - " // -> Eq\n" - " ```\n" - "\n" - " If you want to check only for equality you may use\n" - " [`loosely_equals`](#loosely_equals) instead.\n" -). --spec loosely_compare(float(), float(), float()) -> gleam@order:order(). -loosely_compare(A, B, Tolerance) -> - Difference = absolute_value(A - B), - case Difference =< Tolerance of - true -> - eq; - - false -> - compare(A, B) - end. - --file("src/gleam/float.gleam", 158). -?DOC( - " Checks for equality of two `Float`s within a tolerance,\n" - " returning an `Bool`.\n" - "\n" - " This function allows Float comparison while handling\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n" - "\n" - " Notice: For `Float`s the tolerance won't be exact:\n" - " `5.3 - 5.0` is not exactly `0.3`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " loosely_equals(5.0, with: 5.3, tolerating: 0.5)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " loosely_equals(5.0, with: 5.1, tolerating: 0.1)\n" - " // -> False\n" - " ```\n" -). --spec loosely_equals(float(), float(), float()) -> boolean(). -loosely_equals(A, B, Tolerance) -> - Difference = absolute_value(A - B), - Difference =< Tolerance. - --file("src/gleam/float.gleam", 348). -?DOC( - " Returns the results of the base being raised to the power of the\n" - " exponent, as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " power(2.0, -1.0)\n" - " // -> Ok(0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(2.0, 2.0)\n" - " // -> Ok(4.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(8.0, 1.5)\n" - " // -> Ok(22.627416997969522)\n" - " ```\n" - "\n" - " ```gleam\n" - " 4.0 |> power(of: 2.0)\n" - " // -> Ok(16.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(-1.0, 0.5)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec power(float(), float()) -> {ok, float()} | {error, nil}. -power(Base, Exponent) -> - Fractional = (math:ceil(Exponent) - Exponent) > +0.0, - case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent - < +0.0)) of - true -> - {error, nil}; - - false -> - {ok, math:pow(Base, Exponent)} - end. - --file("src/gleam/float.gleam", 380). -?DOC( - " Returns the square root of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " square_root(4.0)\n" - " // -> Ok(2.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " square_root(-16.0)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec square_root(float()) -> {ok, float()} | {error, nil}. -square_root(X) -> - power(X, 0.5). - --file("src/gleam/float.gleam", 393). -?DOC( - " Returns the negative of the value provided.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(1.0)\n" - " // -> -1.0\n" - " ```\n" -). --spec negate(float()) -> float(). -negate(X) -> - -1.0 * X. - --file("src/gleam/float.gleam", 240). -?DOC( - " Rounds the value to the nearest whole number as an `Int`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " round(2.3)\n" - " // -> 2\n" - " ```\n" - "\n" - " ```gleam\n" - " round(2.5)\n" - " // -> 3\n" - " ```\n" -). --spec round(float()) -> integer(). -round(X) -> - erlang:round(X). - --file("src/gleam/float.gleam", 280). -?DOC( - " Converts the value to a given precision as a `Float`.\n" - " The precision is the number of allowed decimal places.\n" - " Negative precisions are allowed and force rounding\n" - " to the nearest tenth, hundredth, thousandth etc.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_precision(2.43434348473, precision: 2)\n" - " // -> 2.43\n" - " ```\n" - "\n" - " ```gleam\n" - " to_precision(547890.453444, precision: -3)\n" - " // -> 548000.0\n" - " ```\n" -). --spec to_precision(float(), integer()) -> float(). -to_precision(X, Precision) -> - case Precision =< 0 of - true -> - Factor = math:pow(10.0, erlang:float(- Precision)), - erlang:float(erlang:round(case Factor of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> X / Gleam@denominator - end)) * Factor; - - false -> - Factor@1 = math:pow(10.0, erlang:float(Precision)), - case Factor@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> erlang:float(erlang:round(X * Factor@1)) - / Gleam@denominator@1 - end - end. - --file("src/gleam/float.gleam", 410). --spec sum_loop(list(float()), float()) -> float(). -sum_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - sum_loop(Rest, First + Initial); - - [] -> - Initial - end. - --file("src/gleam/float.gleam", 406). -?DOC( - " Sums a list of `Float`s.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " sum([1.0, 2.2, 3.3])\n" - " // -> 6.5\n" - " ```\n" -). --spec sum(list(float())) -> float(). -sum(Numbers) -> - sum_loop(Numbers, +0.0). - --file("src/gleam/float.gleam", 430). --spec product_loop(list(float()), float()) -> float(). -product_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - product_loop(Rest, First * Initial); - - [] -> - Initial - end. - --file("src/gleam/float.gleam", 426). -?DOC( - " Multiplies a list of `Float`s and returns the product.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " product([2.5, 3.2, 4.2])\n" - " // -> 33.6\n" - " ```\n" -). --spec product(list(float())) -> float(). -product(Numbers) -> - product_loop(Numbers, 1.0). - --file("src/gleam/float.gleam", 452). -?DOC( - " Generates a random float between the given zero (inclusive) and one\n" - " (exclusive).\n" - "\n" - " On Erlang this updates the random state in the process dictionary.\n" - " See: \n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " random()\n" - " // -> 0.646355926896028\n" - " ```\n" -). --spec random() -> float(). -random() -> - rand:uniform(). - --file("src/gleam/float.gleam", 481). -?DOC( - " Computes the modulo of an float division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " modulo(13.3, by: 3.3)\n" - " // -> Ok(0.1)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(-13.3, by: 3.3)\n" - " // -> Ok(3.2)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(13.3, by: -3.3)\n" - " // -> Ok(-3.2)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(-13.3, by: -3.3)\n" - " // -> Ok(-0.1)\n" - " ```\n" -). --spec modulo(float(), float()) -> {ok, float()} | {error, nil}. -modulo(Dividend, Divisor) -> - case Divisor of - +0.0 -> - {error, nil}; - - _ -> - {ok, Dividend - (math:floor(case Divisor of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> Dividend / Gleam@denominator - end) * Divisor)} - end. - --file("src/gleam/float.gleam", 502). -?DOC( - " Returns division of the inputs as a `Result`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " divide(0.0, 1.0)\n" - " // -> Ok(0.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(1.0, 0.0)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec divide(float(), float()) -> {ok, float()} | {error, nil}. -divide(A, B) -> - case B of - +0.0 -> - {error, nil}; - - B@1 -> - {ok, case B@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> A / Gleam@denominator - end} - end. - --file("src/gleam/float.gleam", 533). -?DOC( - " Adds two floats together.\n" - "\n" - " It's the function equivalent of the `+.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " add(1.0, 2.0)\n" - " // -> 3.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([1.0, 2.0, 3.0], 0.0, add)\n" - " // -> 6.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> add(2.0)\n" - " // -> 5.0\n" - " ```\n" -). --spec add(float(), float()) -> float(). -add(A, B) -> - A + B. - --file("src/gleam/float.gleam", 561). -?DOC( - " Multiplies two floats together.\n" - "\n" - " It's the function equivalent of the `*.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " multiply(2.0, 4.0)\n" - " // -> 8.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([2.0, 3.0, 4.0], 1.0, multiply)\n" - " // -> 24.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> multiply(2.0)\n" - " // -> 6.0\n" - " ```\n" -). --spec multiply(float(), float()) -> float(). -multiply(A, B) -> - A * B. - --file("src/gleam/float.gleam", 594). -?DOC( - " Subtracts one float from another.\n" - "\n" - " It's the function equivalent of the `-.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " subtract(3.0, 1.0)\n" - " // -> 2.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([1.0, 2.0, 3.0], 10.0, subtract)\n" - " // -> 4.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> subtract(_, 2.0)\n" - " // -> 1.0\n" - " ```\n" - "\n" - " ```gleam\n" - " 3.0 |> subtract(2.0, _)\n" - " // -> -1.0\n" - " ```\n" -). --spec subtract(float(), float()) -> float(). -subtract(A, B) -> - A - B. - --file("src/gleam/float.gleam", 623). -?DOC( - " Returns the natural logarithm (base e) of the given as a `Result`. If the\n" - " input is less than or equal to 0, returns `Error(Nil)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " logarithm(1.0)\n" - " // -> Ok(0.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " logarithm(2.718281828459045) // e\n" - " // -> Ok(1.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " logarithm(0.0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " logarithm(-1.0)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec logarithm(float()) -> {ok, float()} | {error, nil}. -logarithm(X) -> - case X =< +0.0 of - true -> - {error, nil}; - - false -> - {ok, math:log(X)} - end. - --file("src/gleam/float.gleam", 661). -?DOC( - " Returns e (Euler's number) raised to the power of the given exponent, as\n" - " a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " exponential(0.0)\n" - " // -> Ok(1.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " exponential(1.0)\n" - " // -> Ok(2.718281828459045)\n" - " ```\n" - "\n" - " ```gleam\n" - " exponential(-1.0)\n" - " // -> Ok(0.36787944117144233)\n" - " ```\n" -). --spec exponential(float()) -> float(). -exponential(X) -> - math:exp(X). diff --git a/build/packages/gleam_stdlib/src/gleam@function.erl b/build/packages/gleam_stdlib/src/gleam@function.erl deleted file mode 100644 index a6dec81..0000000 --- a/build/packages/gleam_stdlib/src/gleam@function.erl +++ /dev/null @@ -1,30 +0,0 @@ --module(gleam@function). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/function.gleam"). --export([identity/1, tap/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/function.gleam", 3). -?DOC(" Takes a single argument and always returns its input value.\n"). --spec identity(CLA) -> CLA. -identity(X) -> - X. - --file("src/gleam/function.gleam", 12). -?DOC( - " Takes an argument and a single function, calls that function with that\n" - " argument and returns that argument instead of the function return value.\n" - "\n" - " Useful for running synchronous side effects in a pipeline.\n" -). --spec tap(CLB, fun((CLB) -> any())) -> CLB. -tap(Arg, Effect) -> - Effect(Arg), - Arg. diff --git a/build/packages/gleam_stdlib/src/gleam@int.erl b/build/packages/gleam_stdlib/src/gleam@int.erl deleted file mode 100644 index 5e298da..0000000 --- a/build/packages/gleam_stdlib/src/gleam@int.erl +++ /dev/null @@ -1,986 +0,0 @@ --module(gleam@int). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/int.gleam"). --export([absolute_value/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, to_float/1, power/2, square_root/1, compare/2, min/2, max/2, clamp/3, is_even/1, is_odd/1, negate/1, sum/1, product/1, digits/2, undigits/2, random/1, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Functions for working with integers.\n" - "\n" - " ## Division by zero\n" - "\n" - " In Erlang division by zero results in a crash, however Gleam does not have\n" - " partial functions and operators in core so instead division by zero returns\n" - " zero, a behaviour taken from Pony, Coq, and Lean.\n" - "\n" - " This may seem unexpected at first, but it is no less mathematically valid\n" - " than crashing or returning a special value. Division by zero is undefined\n" - " in mathematics.\n" -). - --file("src/gleam/int.gleam", 30). -?DOC( - " Returns the absolute value of the input.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " absolute_value(-12)\n" - " // -> 12\n" - " ```\n" - "\n" - " ```gleam\n" - " absolute_value(10)\n" - " // -> 10\n" - " ```\n" -). --spec absolute_value(integer()) -> integer(). -absolute_value(X) -> - case X >= 0 of - true -> - X; - - false -> - X * -1 - end. - --file("src/gleam/int.gleam", 109). -?DOC( - " Parses a given string as an int if possible.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse(\"2\")\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " parse(\"ABC\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec parse(binary()) -> {ok, integer()} | {error, nil}. -parse(String) -> - gleam_stdlib:parse_int(String). - --file("src/gleam/int.gleam", 141). -?DOC( - " Parses a given string as an int in a given base if possible.\n" - " Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " base_parse(\"10\", 2)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"30\", 16)\n" - " // -> Ok(48)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"1C\", 36)\n" - " // -> Ok(48)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"48\", 1)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " base_parse(\"48\", 37)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}. -base_parse(String, Base) -> - case (Base >= 2) andalso (Base =< 36) of - true -> - gleam_stdlib:int_from_base_string(String, Base); - - false -> - {error, nil} - end. - --file("src/gleam/int.gleam", 163). -?DOC( - " Prints a given int to a string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_string(2)\n" - " // -> \"2\"\n" - " ```\n" -). --spec to_string(integer()) -> binary(). -to_string(X) -> - erlang:integer_to_binary(X). - --file("src/gleam/int.gleam", 196). -?DOC( - " Prints a given int to a string using the base number provided.\n" - " Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n" - " For common bases (2, 8, 16, 36), use the `to_baseN` functions.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base_string(2, 2)\n" - " // -> Ok(\"10\")\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 16)\n" - " // -> Ok(\"30\")\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 36)\n" - " // -> Ok(\"1C\")\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 1)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " to_base_string(48, 37)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec to_base_string(integer(), integer()) -> {ok, binary()} | {error, nil}. -to_base_string(X, Base) -> - case (Base >= 2) andalso (Base =< 36) of - true -> - {ok, erlang:integer_to_binary(X, Base)}; - - false -> - {error, nil} - end. - --file("src/gleam/int.gleam", 216). -?DOC( - " Prints a given int to a string using base-2.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base2(2)\n" - " // -> \"10\"\n" - " ```\n" -). --spec to_base2(integer()) -> binary(). -to_base2(X) -> - erlang:integer_to_binary(X, 2). - --file("src/gleam/int.gleam", 229). -?DOC( - " Prints a given int to a string using base-8.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base8(15)\n" - " // -> \"17\"\n" - " ```\n" -). --spec to_base8(integer()) -> binary(). -to_base8(X) -> - erlang:integer_to_binary(X, 8). - --file("src/gleam/int.gleam", 242). -?DOC( - " Prints a given int to a string using base-16.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base16(48)\n" - " // -> \"30\"\n" - " ```\n" -). --spec to_base16(integer()) -> binary(). -to_base16(X) -> - erlang:integer_to_binary(X, 16). - --file("src/gleam/int.gleam", 255). -?DOC( - " Prints a given int to a string using base-36.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_base36(48)\n" - " // -> \"1C\"\n" - " ```\n" -). --spec to_base36(integer()) -> binary(). -to_base36(X) -> - erlang:integer_to_binary(X, 36). - --file("src/gleam/int.gleam", 280). -?DOC( - " Takes an int and returns its value as a float.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_float(5)\n" - " // -> 5.0\n" - " ```\n" - "\n" - " ```gleam\n" - " to_float(0)\n" - " // -> 0.0\n" - " ```\n" - "\n" - " ```gleam\n" - " to_float(-3)\n" - " // -> -3.0\n" - " ```\n" -). --spec to_float(integer()) -> float(). -to_float(X) -> - erlang:float(X). - --file("src/gleam/int.gleam", 67). -?DOC( - " Returns the results of the base being raised to the power of the\n" - " exponent, as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " power(2, -1.0)\n" - " // -> Ok(0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(2, 2.0)\n" - " // -> Ok(4.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(8, 1.5)\n" - " // -> Ok(22.627416997969522)\n" - " ```\n" - "\n" - " ```gleam\n" - " 4 |> power(of: 2.0)\n" - " // -> Ok(16.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " power(-1, 0.5)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec power(integer(), float()) -> {ok, float()} | {error, nil}. -power(Base, Exponent) -> - _pipe = Base, - _pipe@1 = erlang:float(_pipe), - gleam@float:power(_pipe@1, Exponent). - --file("src/gleam/int.gleam", 87). -?DOC( - " Returns the square root of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " square_root(4)\n" - " // -> Ok(2.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " square_root(-16)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec square_root(integer()) -> {ok, float()} | {error, nil}. -square_root(X) -> - _pipe = X, - _pipe@1 = erlang:float(_pipe), - gleam@float:square_root(_pipe@1). - --file("src/gleam/int.gleam", 316). -?DOC( - " Compares two ints, returning an order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(2, 3)\n" - " // -> Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " compare(4, 3)\n" - " // -> Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " compare(3, 3)\n" - " // -> Eq\n" - " ```\n" -). --spec compare(integer(), integer()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - false -> - case A < B of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/int.gleam", 336). -?DOC( - " Compares two ints, returning the smaller of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " min(2, 3)\n" - " // -> 2\n" - " ```\n" -). --spec min(integer(), integer()) -> integer(). -min(A, B) -> - case A < B of - true -> - A; - - false -> - B - end. - --file("src/gleam/int.gleam", 352). -?DOC( - " Compares two ints, returning the larger of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " max(2, 3)\n" - " // -> 3\n" - " ```\n" -). --spec max(integer(), integer()) -> integer(). -max(A, B) -> - case A > B of - true -> - A; - - false -> - B - end. - --file("src/gleam/int.gleam", 291). -?DOC( - " Restricts an int between a lower and upper bound.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " clamp(40, min: 50, max: 60)\n" - " // -> 50\n" - " ```\n" -). --spec clamp(integer(), integer(), integer()) -> integer(). -clamp(X, Min_bound, Max_bound) -> - _pipe = X, - _pipe@1 = min(_pipe, Max_bound), - max(_pipe@1, Min_bound). - --file("src/gleam/int.gleam", 373). -?DOC( - " Returns whether the value provided is even.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_even(2)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_even(3)\n" - " // -> False\n" - " ```\n" -). --spec is_even(integer()) -> boolean(). -is_even(X) -> - (X rem 2) =:= 0. - --file("src/gleam/int.gleam", 391). -?DOC( - " Returns whether the value provided is odd.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_odd(3)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_odd(2)\n" - " // -> False\n" - " ```\n" -). --spec is_odd(integer()) -> boolean(). -is_odd(X) -> - (X rem 2) /= 0. - --file("src/gleam/int.gleam", 404). -?DOC( - " Returns the negative of the value provided.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(1)\n" - " // -> -1\n" - " ```\n" -). --spec negate(integer()) -> integer(). -negate(X) -> - -1 * X. - --file("src/gleam/int.gleam", 421). --spec sum_loop(list(integer()), integer()) -> integer(). -sum_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - sum_loop(Rest, First + Initial); - - [] -> - Initial - end. - --file("src/gleam/int.gleam", 417). -?DOC( - " Sums a list of ints.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " sum([1, 2, 3])\n" - " // -> 6\n" - " ```\n" -). --spec sum(list(integer())) -> integer(). -sum(Numbers) -> - sum_loop(Numbers, 0). - --file("src/gleam/int.gleam", 441). --spec product_loop(list(integer()), integer()) -> integer(). -product_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - product_loop(Rest, First * Initial); - - [] -> - Initial - end. - --file("src/gleam/int.gleam", 437). -?DOC( - " Multiplies a list of ints and returns the product.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " product([2, 3, 4])\n" - " // -> 24\n" - " ```\n" -). --spec product(list(integer())) -> integer(). -product(Numbers) -> - product_loop(Numbers, 1). - --file("src/gleam/int.gleam", 456). --spec digits_loop(integer(), integer(), list(integer())) -> list(integer()). -digits_loop(X, Base, Acc) -> - case absolute_value(X) < Base of - true -> - [X | Acc]; - - false -> - digits_loop(case Base of - 0 -> 0; - Gleam@denominator -> X div Gleam@denominator - end, Base, [case Base of - 0 -> 0; - Gleam@denominator@1 -> X rem Gleam@denominator@1 - end | Acc]) - end. - --file("src/gleam/int.gleam", 449). --spec digits(integer(), integer()) -> {ok, list(integer())} | {error, nil}. -digits(X, Base) -> - case Base < 2 of - true -> - {error, nil}; - - false -> - {ok, digits_loop(X, Base, [])} - end. - --file("src/gleam/int.gleam", 471). --spec undigits_loop(list(integer()), integer(), integer()) -> {ok, integer()} | - {error, nil}. -undigits_loop(Numbers, Base, Acc) -> - case Numbers of - [] -> - {ok, Acc}; - - [Digit | _] when Digit >= Base -> - {error, nil}; - - [Digit@1 | Rest] -> - undigits_loop(Rest, Base, (Acc * Base) + Digit@1) - end. - --file("src/gleam/int.gleam", 464). --spec undigits(list(integer()), integer()) -> {ok, integer()} | {error, nil}. -undigits(Numbers, Base) -> - case Base < 2 of - true -> - {error, nil}; - - false -> - undigits_loop(Numbers, Base, 0) - end. - --file("src/gleam/int.gleam", 500). -?DOC( - " Generates a random int between zero and the given maximum.\n" - "\n" - " The lower number is inclusive, the upper number is exclusive.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " random(10)\n" - " // -> 4\n" - " ```\n" - "\n" - " ```gleam\n" - " random(1)\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " random(-1)\n" - " // -> -1\n" - " ```\n" -). --spec random(integer()) -> integer(). -random(Max) -> - _pipe = (rand:uniform() * erlang:float(Max)), - _pipe@1 = math:floor(_pipe), - erlang:round(_pipe@1). - --file("src/gleam/int.gleam", 533). -?DOC( - " Performs a truncated integer division.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " divide(0, 1)\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(5, 2)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " divide(-99, 2)\n" - " // -> Ok(-49)\n" - " ```\n" -). --spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}. -divide(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend div Gleam@denominator - end} - end. - --file("src/gleam/int.gleam", 585). -?DOC( - " Computes the remainder of an integer division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " Most the time you will want to use the `%` operator instead of this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " remainder(3, 2)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(10, -1)\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(13, by: 3)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(-13, by: 3)\n" - " // -> Ok(-1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(13, by: -3)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " remainder(-13, by: -3)\n" - " // -> Ok(-1)\n" - " ```\n" -). --spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}. -remainder(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end} - end. - --file("src/gleam/int.gleam", 627). -?DOC( - " Computes the modulo of an integer division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " Most the time you will want to use the `%` operator instead of this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " modulo(3, 2)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(10, -1)\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(13, by: 3)\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " modulo(-13, by: 3)\n" - " // -> Ok(2)\n" - " ```\n" -). --spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}. -modulo(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - _ -> - Remainder = case Divisor of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end, - case (Remainder * Divisor) < 0 of - true -> - {ok, Remainder + Divisor}; - - false -> - {ok, Remainder} - end - end. - --file("src/gleam/int.gleam", 671). -?DOC( - " Performs a *floored* integer division, which means that the result will\n" - " always be rounded towards negative infinity.\n" - "\n" - " If you want to perform truncated integer division (rounding towards zero),\n" - " use `int.divide()` or the `/` operator instead.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " floor_divide(1, 0)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " floor_divide(5, 2)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " floor_divide(6, -4)\n" - " // -> Ok(-2)\n" - " ```\n" - "\n" - " ```gleam\n" - " floor_divide(-99, 2)\n" - " // -> Ok(-50)\n" - " ```\n" -). --spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}. -floor_divide(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end) /= 0) of - true -> - {ok, (case Divisor@1 of - 0 -> 0; - Gleam@denominator@1 -> Dividend div Gleam@denominator@1 - end) - 1}; - - false -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator@2 -> Dividend div Gleam@denominator@2 - end} - end - end. - --file("src/gleam/int.gleam", 705). -?DOC( - " Adds two integers together.\n" - "\n" - " It's the function equivalent of the `+` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " add(1, 2)\n" - " // -> 3\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - " list.fold([1, 2, 3], 0, add)\n" - " // -> 6\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> add(2)\n" - " // -> 5\n" - " ```\n" -). --spec add(integer(), integer()) -> integer(). -add(A, B) -> - A + B. - --file("src/gleam/int.gleam", 733). -?DOC( - " Multiplies two integers together.\n" - "\n" - " It's the function equivalent of the `*` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " multiply(2, 4)\n" - " // -> 8\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([2, 3, 4], 1, multiply)\n" - " // -> 24\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> multiply(2)\n" - " // -> 6\n" - " ```\n" -). --spec multiply(integer(), integer()) -> integer(). -multiply(A, B) -> - A * B. - --file("src/gleam/int.gleam", 766). -?DOC( - " Subtracts one int from another.\n" - "\n" - " It's the function equivalent of the `-` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " subtract(3, 1)\n" - " // -> 2\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " list.fold([1, 2, 3], 10, subtract)\n" - " // -> 4\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> subtract(2)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " 3 |> subtract(2, _)\n" - " // -> -1\n" - " ```\n" -). --spec subtract(integer(), integer()) -> integer(). -subtract(A, B) -> - A - B. - --file("src/gleam/int.gleam", 778). -?DOC( - " Calculates the bitwise AND of its arguments.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_and(integer(), integer()) -> integer(). -bitwise_and(X, Y) -> - erlang:'band'(X, Y). - --file("src/gleam/int.gleam", 788). -?DOC( - " Calculates the bitwise NOT of its argument.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_not(integer()) -> integer(). -bitwise_not(X) -> - erlang:'bnot'(X). - --file("src/gleam/int.gleam", 798). -?DOC( - " Calculates the bitwise OR of its arguments.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_or(integer(), integer()) -> integer(). -bitwise_or(X, Y) -> - erlang:'bor'(X, Y). - --file("src/gleam/int.gleam", 808). -?DOC( - " Calculates the bitwise XOR of its arguments.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_exclusive_or(integer(), integer()) -> integer(). -bitwise_exclusive_or(X, Y) -> - erlang:'bxor'(X, Y). - --file("src/gleam/int.gleam", 818). -?DOC( - " Calculates the result of an arithmetic left bitshift.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_shift_left(integer(), integer()) -> integer(). -bitwise_shift_left(X, Y) -> - erlang:'bsl'(X, Y). - --file("src/gleam/int.gleam", 828). -?DOC( - " Calculates the result of an arithmetic right bitshift.\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints.\n" -). --spec bitwise_shift_right(integer(), integer()) -> integer(). -bitwise_shift_right(X, Y) -> - erlang:'bsr'(X, Y). diff --git a/build/packages/gleam_stdlib/src/gleam@io.erl b/build/packages/gleam_stdlib/src/gleam@io.erl deleted file mode 100644 index e60295e..0000000 --- a/build/packages/gleam_stdlib/src/gleam@io.erl +++ /dev/null @@ -1,80 +0,0 @@ --module(gleam@io). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/io.gleam"). --export([print/1, print_error/1, println/1, println_error/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/io.gleam", 15). -?DOC( - " Writes a string to standard output (stdout).\n" - "\n" - " If you want your output to be printed on its own line see `println`.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " io.print(\"Hi mum\")\n" - " // -> Nil\n" - " // Hi mum\n" - " ```\n" -). --spec print(binary()) -> nil. -print(String) -> - gleam_stdlib:print(String). - --file("src/gleam/io.gleam", 31). -?DOC( - " Writes a string to standard error (stderr).\n" - "\n" - " If you want your output to be printed on its own line see `println_error`.\n" - "\n" - " ## Example\n" - "\n" - " ```\n" - " io.print_error(\"Hi pop\")\n" - " // -> Nil\n" - " // Hi pop\n" - " ```\n" -). --spec print_error(binary()) -> nil. -print_error(String) -> - gleam_stdlib:print_error(String). - --file("src/gleam/io.gleam", 45). -?DOC( - " Writes a string to standard output (stdout), appending a newline to the end.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " io.println(\"Hi mum\")\n" - " // -> Nil\n" - " // Hi mum\n" - " ```\n" -). --spec println(binary()) -> nil. -println(String) -> - gleam_stdlib:println(String). - --file("src/gleam/io.gleam", 59). -?DOC( - " Writes a string to standard error (stderr), appending a newline to the end.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " io.println_error(\"Hi pop\")\n" - " // -> Nil\n" - " // Hi pop\n" - " ```\n" -). --spec println_error(binary()) -> nil. -println_error(String) -> - gleam_stdlib:println_error(String). diff --git a/build/packages/gleam_stdlib/src/gleam@list.erl b/build/packages/gleam_stdlib/src/gleam@list.erl deleted file mode 100644 index 0c96ecb..0000000 --- a/build/packages/gleam_stdlib/src/gleam@list.erl +++ /dev/null @@ -1,2873 +0,0 @@ --module(gleam@list). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/list.gleam"). --export([length/1, count/2, reverse/1, is_empty/1, contains/2, first/1, rest/1, group/2, filter/2, filter_map/2, map/2, map2/3, map_fold/3, index_map/2, try_map/2, drop/2, take/2, new/0, wrap/1, append/2, prepend/2, flatten/1, flat_map/2, fold/3, fold_right/3, index_fold/3, try_fold/3, fold_until/3, find/2, find_map/2, all/2, any/2, zip/2, strict_zip/2, unzip/1, intersperse/2, unique/1, sort/2, range/2, repeat/2, split/2, split_while/2, key_find/2, key_filter/2, key_pop/2, key_set/3, each/2, try_each/2, partition/2, window/2, window_by_2/1, drop_while/2, take_while/2, chunk/2, sized_chunk/2, reduce/2, scan/3, last/1, combinations/2, combination_pairs/1, transpose/1, interleave/1, shuffle/1, max/2, sample/2, permutations/1]). --export_type([continue_or_stop/1, sorting/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Lists are an ordered sequence of elements and are one of the most common\n" - " data types in Gleam.\n" - "\n" - " New elements can be added and removed from the front of a list in\n" - " constant time, while adding and removing from the end requires traversing\n" - " and copying the whole list, so keep this in mind when designing your\n" - " programs.\n" - "\n" - " There is a dedicated syntax for prefixing to a list:\n" - "\n" - " ```gleam\n" - " let new_list = [1, 2, ..existing_list]\n" - " ```\n" - "\n" - " And a matching syntax for getting the first elements of a list:\n" - "\n" - " ```gleam\n" - " case list {\n" - " [first_element, ..rest] -> first_element\n" - " _ -> \"this pattern matches when the list is empty\"\n" - " }\n" - " ```\n" - "\n" -). - --type continue_or_stop(XG) :: {continue, XG} | {stop, XG}. - --type sorting() :: ascending | descending. - --file("src/gleam/list.gleam", 60). --spec length_loop(list(any()), integer()) -> integer(). -length_loop(List, Count) -> - case List of - [_ | List@1] -> - length_loop(List@1, Count + 1); - - [] -> - Count - end. - --file("src/gleam/list.gleam", 56). -?DOC( - " Counts the number of elements in a given list.\n" - "\n" - " This function has to traverse the list to determine the number of elements,\n" - " so it runs in linear time.\n" - "\n" - " This function is natively implemented by the virtual machine and is highly\n" - " optimised.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " length([])\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " length([1])\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " length([1, 2])\n" - " // -> 2\n" - " ```\n" -). --spec length(list(any())) -> integer(). -length(List) -> - erlang:length(List). - --file("src/gleam/list.gleam", 93). --spec count_loop(list(XN), fun((XN) -> boolean()), integer()) -> integer(). -count_loop(List, Predicate, Acc) -> - case List of - [] -> - Acc; - - [First | Rest] -> - case Predicate(First) of - true -> - count_loop(Rest, Predicate, Acc + 1); - - false -> - count_loop(Rest, Predicate, Acc) - end - end. - --file("src/gleam/list.gleam", 89). -?DOC( - " Counts the number of elements in a given list satisfying a given predicate.\n" - "\n" - " This function has to traverse the list to determine the number of elements,\n" - " so it runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " count([], fn(a) { a > 0 })\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " count([1], fn(a) { a > 0 })\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " count([1, 2, 3], int.is_odd)\n" - " // -> 2\n" - " ```\n" -). --spec count(list(XL), fun((XL) -> boolean())) -> integer(). -count(List, Predicate) -> - count_loop(List, Predicate, 0). - --file("src/gleam/list.gleam", 131). -?DOC( - " Creates a new list from a given list containing the same elements but in the\n" - " opposite order.\n" - "\n" - " This function has to traverse the list to create the new reversed list, so\n" - " it runs in linear time.\n" - "\n" - " This function is natively implemented by the virtual machine and is highly\n" - " optimised.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " reverse([])\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " reverse([1])\n" - " // -> [1]\n" - " ```\n" - "\n" - " ```gleam\n" - " reverse([1, 2])\n" - " // -> [2, 1]\n" - " ```\n" -). --spec reverse(list(XP)) -> list(XP). -reverse(List) -> - lists:reverse(List). - --file("src/gleam/list.gleam", 168). -?DOC( - " Determines whether or not the list is empty.\n" - "\n" - " This function runs in constant time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_empty([])\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_empty([1])\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_empty([1, 1])\n" - " // -> False\n" - " ```\n" -). --spec is_empty(list(any())) -> boolean(). -is_empty(List) -> - List =:= []. - --file("src/gleam/list.gleam", 204). -?DOC( - " Determines whether or not a given element exists within a given list.\n" - "\n" - " This function traverses the list to find the element, so it runs in linear\n" - " time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [] |> contains(any: 0)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " [0] |> contains(any: 0)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " [1] |> contains(any: 0)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 1] |> contains(any: 0)\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 0] |> contains(any: 0)\n" - " // -> True\n" - " ```\n" -). --spec contains(list(XY), XY) -> boolean(). -contains(List, Elem) -> - case List of - [] -> - false; - - [First | _] when First =:= Elem -> - true; - - [_ | Rest] -> - contains(Rest, Elem) - end. - --file("src/gleam/list.gleam", 231). -?DOC( - " Gets the first element from the start of the list, if there is one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " first([])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " first([0])\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " first([1, 2])\n" - " // -> Ok(1)\n" - " ```\n" -). --spec first(list(YA)) -> {ok, YA} | {error, nil}. -first(List) -> - case List of - [] -> - {error, nil}; - - [First | _] -> - {ok, First} - end. - --file("src/gleam/list.gleam", 260). -?DOC( - " Returns the list minus the first element. If the list is empty, `Error(Nil)` is\n" - " returned.\n" - "\n" - " This function runs in constant time and does not make a copy of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " rest([])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " rest([0])\n" - " // -> Ok([])\n" - " ```\n" - "\n" - " ```gleam\n" - " rest([1, 2])\n" - " // -> Ok([2])\n" - " ```\n" -). --spec rest(list(YE)) -> {ok, list(YE)} | {error, nil}. -rest(List) -> - case List of - [] -> - {error, nil}; - - [_ | Rest] -> - {ok, Rest} - end. - --file("src/gleam/list.gleam", 302). --spec group_loop(list(YP), fun((YP) -> YR), gleam@dict:dict(YR, list(YP))) -> gleam@dict:dict(YR, list(YP)). -group_loop(List, To_key, Groups) -> - case List of - [] -> - Groups; - - [First | Rest] -> - Key = To_key(First), - Groups@1 = case gleam_stdlib:map_get(Groups, Key) of - {error, _} -> - gleam@dict:insert(Groups, Key, [First]); - - {ok, Existing} -> - gleam@dict:insert(Groups, Key, [First | Existing]) - end, - group_loop(Rest, To_key, Groups@1) - end. - --file("src/gleam/list.gleam", 298). -?DOC( - " Groups the elements from the given list by the given key function.\n" - "\n" - " Does not preserve the initial value order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/dict\n" - "\n" - " [Ok(3), Error(\"Wrong\"), Ok(200), Ok(73)]\n" - " |> group(by: fn(i) {\n" - " case i {\n" - " Ok(_) -> \"Successful\"\n" - " Error(_) -> \"Failed\"\n" - " }\n" - " })\n" - " |> dict.to_list\n" - " // -> [\n" - " // #(\"Failed\", [Error(\"Wrong\")]),\n" - " // #(\"Successful\", [Ok(73), Ok(200), Ok(3)])\n" - " // ]\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/dict\n" - "\n" - " group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 })\n" - " |> dict.to_list\n" - " // -> [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])]\n" - " ```\n" -). --spec group(list(YJ), fun((YJ) -> YL)) -> gleam@dict:dict(YL, list(YJ)). -group(List, Key) -> - group_loop(List, Key, maps:new()). - --file("src/gleam/list.gleam", 339). --spec filter_loop(list(AAB), fun((AAB) -> boolean()), list(AAB)) -> list(AAB). -filter_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - New_acc = case Fun(First) of - true -> - [First | Acc]; - - false -> - Acc - end, - filter_loop(Rest, Fun, New_acc) - end. - --file("src/gleam/list.gleam", 335). -?DOC( - " Returns a new list containing only the elements from the first list for\n" - " which the given functions returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " filter([2, 4, 6, 1], fn(x) { x > 2 })\n" - " // -> [4, 6]\n" - " ```\n" - "\n" - " ```gleam\n" - " filter([2, 4, 6, 1], fn(x) { x > 6 })\n" - " // -> []\n" - " ```\n" -). --spec filter(list(YY), fun((YY) -> boolean())) -> list(YY). -filter(List, Predicate) -> - filter_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 371). --spec filter_map_loop( - list(AAM), - fun((AAM) -> {ok, AAO} | {error, any()}), - list(AAO) -) -> list(AAO). -filter_map_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - New_acc = case Fun(First) of - {ok, First@1} -> - [First@1 | Acc]; - - {error, _} -> - Acc - end, - filter_map_loop(Rest, Fun, New_acc) - end. - --file("src/gleam/list.gleam", 367). -?DOC( - " Returns a new list containing only the elements from the first list for\n" - " which the given functions returns `Ok(_)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " filter_map([2, 4, 6, 1], Error)\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) })\n" - " // -> [3, 5, 7, 2]\n" - " ```\n" -). --spec filter_map(list(AAF), fun((AAF) -> {ok, AAH} | {error, any()})) -> list(AAH). -filter_map(List, Fun) -> - filter_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 402). --spec map_loop(list(AAY), fun((AAY) -> ABA), list(ABA)) -> list(ABA). -map_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - map_loop(Rest, Fun, [Fun(First) | Acc]) - end. - --file("src/gleam/list.gleam", 398). -?DOC( - " Returns a new list containing only the elements of the first list after the\n" - " function has been applied to each one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map([2, 4, 6], fn(x) { x * 2 })\n" - " // -> [4, 8, 12]\n" - " ```\n" -). --spec map(list(AAU), fun((AAU) -> AAW)) -> list(AAW). -map(List, Fun) -> - map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 429). --spec map2_loop(list(ABJ), list(ABL), fun((ABJ, ABL) -> ABN), list(ABN)) -> list(ABN). -map2_loop(List1, List2, Fun, Acc) -> - case {List1, List2} of - {[], _} -> - lists:reverse(Acc); - - {_, []} -> - lists:reverse(Acc); - - {[A | As_], [B | Bs]} -> - map2_loop(As_, Bs, Fun, [Fun(A, B) | Acc]) - end. - --file("src/gleam/list.gleam", 425). -?DOC( - " Combines two lists into a single list using the given function.\n" - "\n" - " If a list is longer than the other the extra elements are dropped.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y })\n" - " // -> [5, 7, 9]\n" - " ```\n" - "\n" - " ```gleam\n" - " map2([1, 2], [\"a\", \"b\", \"c\"], fn(i, x) { #(i, x) })\n" - " // -> [#(1, \"a\"), #(2, \"b\")]\n" - " ```\n" -). --spec map2(list(ABD), list(ABF), fun((ABD, ABF) -> ABH)) -> list(ABH). -map2(List1, List2, Fun) -> - map2_loop(List1, List2, Fun, []). - --file("src/gleam/list.gleam", 462). --spec map_fold_loop(list(ABV), fun((ABX, ABV) -> {ABX, ABY}), ABX, list(ABY)) -> {ABX, - list(ABY)}. -map_fold_loop(List, Fun, Acc, List_acc) -> - case List of - [] -> - {Acc, lists:reverse(List_acc)}; - - [First | Rest] -> - {Acc@1, First@1} = Fun(Acc, First), - map_fold_loop(Rest, Fun, Acc@1, [First@1 | List_acc]) - end. - --file("src/gleam/list.gleam", 454). -?DOC( - " Similar to `map` but also lets you pass around an accumulated value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map_fold(\n" - " over: [1, 2, 3],\n" - " from: 100,\n" - " with: fn(memo, i) { #(memo + i, i * 2) }\n" - " )\n" - " // -> #(106, [2, 4, 6])\n" - " ```\n" -). --spec map_fold(list(ABQ), ABS, fun((ABS, ABQ) -> {ABS, ABT})) -> {ABS, - list(ABT)}. -map_fold(List, Initial, Fun) -> - map_fold_loop(List, Fun, Initial, []). - --file("src/gleam/list.gleam", 494). --spec index_map_loop( - list(ACF), - fun((ACF, integer()) -> ACH), - integer(), - list(ACH) -) -> list(ACH). -index_map_loop(List, Fun, Index, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - Acc@1 = [Fun(First, Index) | Acc], - index_map_loop(Rest, Fun, Index + 1, Acc@1) - end. - --file("src/gleam/list.gleam", 490). -?DOC( - " Returns a new list containing only the elements of the first list after the\n" - " function has been applied to each one and their index.\n" - "\n" - " The index starts at 0, so the first element is 0, the second is 1, and so\n" - " on.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " index_map([\"a\", \"b\"], fn(x, i) { #(i, x) })\n" - " // -> [#(0, \"a\"), #(1, \"b\")]\n" - " ```\n" -). --spec index_map(list(ACB), fun((ACB, integer()) -> ACD)) -> list(ACD). -index_map(List, Fun) -> - index_map_loop(List, Fun, 0, []). - --file("src/gleam/list.gleam", 548). --spec try_map_loop(list(ACT), fun((ACT) -> {ok, ACV} | {error, ACW}), list(ACV)) -> {ok, - list(ACV)} | - {error, ACW}. -try_map_loop(List, Fun, Acc) -> - case List of - [] -> - {ok, lists:reverse(Acc)}; - - [First | Rest] -> - case Fun(First) of - {ok, First@1} -> - try_map_loop(Rest, Fun, [First@1 | Acc]); - - {error, Error} -> - {error, Error} - end - end. - --file("src/gleam/list.gleam", 541). -?DOC( - " Takes a function that returns a `Result` and applies it to each element in a\n" - " given list in turn.\n" - "\n" - " If the function returns `Ok(new_value)` for all elements in the list then a\n" - " list of the new values is returned.\n" - "\n" - " If the function returns `Error(reason)` for any of the elements then it is\n" - " returned immediately. None of the elements in the list are processed after\n" - " one returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " try_map([1, 2, 3], fn(x) { Ok(x + 2) })\n" - " // -> Ok([3, 4, 5])\n" - " ```\n" - "\n" - " ```gleam\n" - " try_map([1, 2, 3], fn(_) { Error(0) })\n" - " // -> Error(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " try_map([[1], [2, 3]], first)\n" - " // -> Ok([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " try_map([[1], [], [2]], first)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec try_map(list(ACK), fun((ACK) -> {ok, ACM} | {error, ACN})) -> {ok, - list(ACM)} | - {error, ACN}. -try_map(List, Fun) -> - try_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 583). -?DOC( - " Returns a list that is the given list with up to the given number of\n" - " elements removed from the front of the list.\n" - "\n" - " If the element has less than the number of elements an empty list is\n" - " returned.\n" - "\n" - " This function runs in linear time but does not copy the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop([1, 2, 3, 4], 2)\n" - " // -> [3, 4]\n" - " ```\n" - "\n" - " ```gleam\n" - " drop([1, 2, 3, 4], 9)\n" - " // -> []\n" - " ```\n" -). --spec drop(list(ADD), integer()) -> list(ADD). -drop(List, N) -> - case N =< 0 of - true -> - List; - - false -> - case List of - [] -> - []; - - [_ | Rest] -> - drop(Rest, N - 1) - end - end. - --file("src/gleam/list.gleam", 618). --spec take_loop(list(ADJ), integer(), list(ADJ)) -> list(ADJ). -take_loop(List, N, Acc) -> - case N =< 0 of - true -> - lists:reverse(Acc); - - false -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - take_loop(Rest, N - 1, [First | Acc]) - end - end. - --file("src/gleam/list.gleam", 614). -?DOC( - " Returns a list containing the first given number of elements from the given\n" - " list.\n" - "\n" - " If the element has less than the number of elements then the full list is\n" - " returned.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " take([1, 2, 3, 4], 2)\n" - " // -> [1, 2]\n" - " ```\n" - "\n" - " ```gleam\n" - " take([1, 2, 3, 4], 9)\n" - " // -> [1, 2, 3, 4]\n" - " ```\n" -). --spec take(list(ADG), integer()) -> list(ADG). -take(List, N) -> - take_loop(List, N, []). - --file("src/gleam/list.gleam", 638). -?DOC( - " Returns a new empty list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " // -> []\n" - " ```\n" -). --spec new() -> list(any()). -new() -> - []. - --file("src/gleam/list.gleam", 658). -?DOC( - " Returns the given item wrapped in a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " wrap(1)\n" - " // -> [1]\n" - "\n" - " wrap([\"a\", \"b\", \"c\"])\n" - " // -> [[\"a\", \"b\", \"c\"]]\n" - "\n" - " wrap([[]])\n" - " // -> [[[]]]\n" - " ```\n" -). --spec wrap(ADP) -> list(ADP). -wrap(Item) -> - [Item]. - --file("src/gleam/list.gleam", 679). --spec append_loop(list(ADV), list(ADV)) -> list(ADV). -append_loop(First, Second) -> - case First of - [] -> - Second; - - [First@1 | Rest] -> - append_loop(Rest, [First@1 | Second]) - end. - --file("src/gleam/list.gleam", 675). -?DOC( - " Joins one list onto the end of another.\n" - "\n" - " This function runs in linear time, and it traverses and copies the first\n" - " list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " append([1, 2], [3])\n" - " // -> [1, 2, 3]\n" - " ```\n" -). --spec append(list(ADR), list(ADR)) -> list(ADR). -append(First, Second) -> - lists:append(First, Second). - --file("src/gleam/list.gleam", 699). -?DOC( - " Prefixes an item to a list. This can also be done using the dedicated\n" - " syntax instead\n" - "\n" - " ```gleam\n" - " let existing_list = [2, 3, 4]\n" - "\n" - " [1, ..existing_list]\n" - " // -> [1, 2, 3, 4]\n" - "\n" - " prepend(to: existing_list, this: 1)\n" - " // -> [1, 2, 3, 4]\n" - " ```\n" -). --spec prepend(list(ADZ), ADZ) -> list(ADZ). -prepend(List, Item) -> - [Item | List]. - --file("src/gleam/list.gleam", 720). --spec flatten_loop(list(list(AEG)), list(AEG)) -> list(AEG). -flatten_loop(Lists, Acc) -> - case Lists of - [] -> - lists:reverse(Acc); - - [List | Further_lists] -> - flatten_loop(Further_lists, lists:reverse(List, Acc)) - end. - --file("src/gleam/list.gleam", 716). -?DOC( - " Joins a list of lists into a single list.\n" - "\n" - " This function traverses all elements twice on the JavaScript target.\n" - " This function traverses all elements once on the Erlang target.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flatten([[1], [2, 3], []])\n" - " // -> [1, 2, 3]\n" - " ```\n" -). --spec flatten(list(list(AEC))) -> list(AEC). -flatten(Lists) -> - lists:append(Lists). - --file("src/gleam/list.gleam", 737). -?DOC( - " Maps the list with the given function into a list of lists, and then flattens it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flat_map([2, 4, 6], fn(x) { [x, x + 1] })\n" - " // -> [2, 3, 4, 5, 6, 7]\n" - " ```\n" -). --spec flat_map(list(AEL), fun((AEL) -> list(AEN))) -> list(AEN). -flat_map(List, Fun) -> - lists:append(map(List, Fun)). - --file("src/gleam/list.gleam", 749). -?DOC( - " Reduces a list of elements into a single value by calling a given function\n" - " on each element, going from left to right.\n" - "\n" - " `fold([1, 2, 3], 0, add)` is the equivalent of\n" - " `add(add(add(0, 1), 2), 3)`.\n" - "\n" - " This function runs in linear time.\n" -). --spec fold(list(AEQ), AES, fun((AES, AEQ) -> AES)) -> AES. -fold(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - fold(Rest, Fun(Initial, First), Fun) - end. - --file("src/gleam/list.gleam", 771). -?DOC( - " Reduces a list of elements into a single value by calling a given function\n" - " on each element, going from right to left.\n" - "\n" - " `fold_right([1, 2, 3], 0, add)` is the equivalent of\n" - " `add(add(add(0, 3), 2), 1)`.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " Unlike `fold` this function is not tail recursive. Where possible use\n" - " `fold` instead as it will use less memory.\n" -). --spec fold_right(list(AET), AEV, fun((AEV, AET) -> AEV)) -> AEV. -fold_right(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - Fun(fold_right(Rest, Initial, Fun), First) - end. - --file("src/gleam/list.gleam", 808). --spec index_fold_loop( - list(AEZ), - AFB, - fun((AFB, AEZ, integer()) -> AFB), - integer() -) -> AFB. -index_fold_loop(Over, Acc, With, Index) -> - case Over of - [] -> - Acc; - - [First | Rest] -> - index_fold_loop(Rest, With(Acc, First, Index), With, Index + 1) - end. - --file("src/gleam/list.gleam", 800). -?DOC( - " Like fold but the folding function also receives the index of the current element.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [\"a\", \"b\", \"c\"]\n" - " |> index_fold(\"\", fn(acc, item, index) {\n" - " acc <> int.to_string(index) <> \":\" <> item <> \" \"\n" - " })\n" - " // -> \"0:a 1:b 2:c\"\n" - " ```\n" - "\n" - " ```gleam\n" - " [10, 20, 30]\n" - " |> index_fold(0, fn(acc, item, index) { acc + item * index })\n" - " // -> 80\n" - " ```\n" -). --spec index_fold(list(AEW), AEY, fun((AEY, AEW, integer()) -> AEY)) -> AEY. -index_fold(List, Initial, Fun) -> - index_fold_loop(List, Initial, Fun, 0). - --file("src/gleam/list.gleam", 840). -?DOC( - " A variant of fold that might fail.\n" - "\n" - " The folding function should return `Result(accumulator, error)`.\n" - " If the returned value is `Ok(accumulator)` try_fold will try the next value in the list.\n" - " If the returned value is `Error(error)` try_fold will stop and return that error.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4]\n" - " |> try_fold(0, fn(acc, i) {\n" - " case i < 3 {\n" - " True -> Ok(acc + i)\n" - " False -> Error(Nil)\n" - " }\n" - " })\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec try_fold(list(AFC), AFE, fun((AFE, AFC) -> {ok, AFE} | {error, AFF})) -> {ok, - AFE} | - {error, AFF}. -try_fold(List, Initial, Fun) -> - case List of - [] -> - {ok, Initial}; - - [First | Rest] -> - case Fun(Initial, First) of - {ok, Result} -> - try_fold(Rest, Result, Fun); - - {error, _} = Error -> - Error - end - end. - --file("src/gleam/list.gleam", 879). -?DOC( - " A variant of fold that allows to stop folding earlier.\n" - "\n" - " The folding function should return `ContinueOrStop(accumulator)`.\n" - " If the returned value is `Continue(accumulator)` fold_until will try the next value in the list.\n" - " If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4]\n" - " |> fold_until(0, fn(acc, i) {\n" - " case i < 3 {\n" - " True -> Continue(acc + i)\n" - " False -> Stop(acc)\n" - " }\n" - " })\n" - " // -> 3\n" - " ```\n" -). --spec fold_until(list(AFK), AFM, fun((AFM, AFK) -> continue_or_stop(AFM))) -> AFM. -fold_until(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - case Fun(Initial, First) of - {continue, Next_accumulator} -> - fold_until(Rest, Next_accumulator, Fun); - - {stop, B} -> - B - end - end. - --file("src/gleam/list.gleam", 916). -?DOC( - " Finds the first element in a given list for which the given function returns\n" - " `True`.\n" - "\n" - " Returns `Error(Nil)` if no such element is found.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " find([1, 2, 3], fn(x) { x > 2 })\n" - " // -> Ok(3)\n" - " ```\n" - "\n" - " ```gleam\n" - " find([1, 2, 3], fn(x) { x > 4 })\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " find([], fn(_) { True })\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec find(list(AFO), fun((AFO) -> boolean())) -> {ok, AFO} | {error, nil}. -find(List, Is_desired) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - case Is_desired(First) of - true -> - {ok, First}; - - false -> - find(Rest, Is_desired) - end - end. - --file("src/gleam/list.gleam", 952). -?DOC( - " Finds the first element in a given list for which the given function returns\n" - " `Ok(new_value)`, then returns the wrapped `new_value`.\n" - "\n" - " Returns `Error(Nil)` if no such element is found.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " find_map([[], [2], [3]], first)\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " find_map([[], []], first)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " find_map([], first)\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec find_map(list(AFS), fun((AFS) -> {ok, AFU} | {error, any()})) -> {ok, AFU} | - {error, nil}. -find_map(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - case Fun(First) of - {ok, First@1} -> - {ok, First@1}; - - {error, _} -> - find_map(Rest, Fun) - end - end. - --file("src/gleam/list.gleam", 987). -?DOC( - " Returns `True` if the given function returns `True` for all the elements in\n" - " the given list. If the function returns `False` for any of the elements it\n" - " immediately returns `False` without checking the rest of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " all([], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " all([4, 5], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " all([4, 3], fn(x) { x > 3 })\n" - " // -> False\n" - " ```\n" -). --spec all(list(AGA), fun((AGA) -> boolean())) -> boolean(). -all(List, Predicate) -> - case List of - [] -> - true; - - [First | Rest] -> - case Predicate(First) of - true -> - all(Rest, Predicate); - - false -> - false - end - end. - --file("src/gleam/list.gleam", 1024). -?DOC( - " Returns `True` if the given function returns `True` for any the elements in\n" - " the given list. If the function returns `True` for any of the elements it\n" - " immediately returns `True` without checking the rest of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " any([], fn(x) { x > 3 })\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " any([4, 5], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " any([4, 3], fn(x) { x > 4 })\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " any([3, 4], fn(x) { x > 3 })\n" - " // -> True\n" - " ```\n" -). --spec any(list(AGC), fun((AGC) -> boolean())) -> boolean(). -any(List, Predicate) -> - case List of - [] -> - false; - - [First | Rest] -> - case Predicate(First) of - true -> - true; - - false -> - any(Rest, Predicate) - end - end. - --file("src/gleam/list.gleam", 1066). --spec zip_loop(list(AGJ), list(AGL), list({AGJ, AGL})) -> list({AGJ, AGL}). -zip_loop(One, Other, Acc) -> - case {One, Other} of - {[First_one | Rest_one], [First_other | Rest_other]} -> - zip_loop(Rest_one, Rest_other, [{First_one, First_other} | Acc]); - - {_, _} -> - lists:reverse(Acc) - end. - --file("src/gleam/list.gleam", 1062). -?DOC( - " Takes two lists and returns a single list of 2-element tuples.\n" - "\n" - " If one of the lists is longer than the other, the remaining elements from\n" - " the longer list are not used.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " zip([], [])\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " zip([1, 2], [3])\n" - " // -> [#(1, 3)]\n" - " ```\n" - "\n" - " ```gleam\n" - " zip([1], [3, 4])\n" - " // -> [#(1, 3)]\n" - " ```\n" - "\n" - " ```gleam\n" - " zip([1, 2], [3, 4])\n" - " // -> [#(1, 3), #(2, 4)]\n" - " ```\n" -). --spec zip(list(AGE), list(AGG)) -> list({AGE, AGG}). -zip(List, Other) -> - zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1107). --spec strict_zip_loop(list(AGW), list(AGY), list({AGW, AGY})) -> {ok, - list({AGW, AGY})} | - {error, nil}. -strict_zip_loop(One, Other, Acc) -> - case {One, Other} of - {[], []} -> - {ok, lists:reverse(Acc)}; - - {[], _} -> - {error, nil}; - - {_, []} -> - {error, nil}; - - {[First_one | Rest_one], [First_other | Rest_other]} -> - strict_zip_loop( - Rest_one, - Rest_other, - [{First_one, First_other} | Acc] - ) - end. - --file("src/gleam/list.gleam", 1100). -?DOC( - " Takes two lists and returns a single list of 2-element tuples.\n" - "\n" - " If one of the lists is longer than the other, an `Error` is returned.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " strict_zip([], [])\n" - " // -> Ok([])\n" - " ```\n" - "\n" - " ```gleam\n" - " strict_zip([1, 2], [3])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " strict_zip([1], [3, 4])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " strict_zip([1, 2], [3, 4])\n" - " // -> Ok([#(1, 3), #(2, 4)])\n" - " ```\n" -). --spec strict_zip(list(AGP), list(AGR)) -> {ok, list({AGP, AGR})} | {error, nil}. -strict_zip(List, Other) -> - strict_zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1138). --spec unzip_loop(list({AHJ, AHK}), list(AHJ), list(AHK)) -> {list(AHJ), - list(AHK)}. -unzip_loop(Input, One, Other) -> - case Input of - [] -> - {lists:reverse(One), lists:reverse(Other)}; - - [{First_one, First_other} | Rest] -> - unzip_loop(Rest, [First_one | One], [First_other | Other]) - end. - --file("src/gleam/list.gleam", 1134). -?DOC( - " Takes a single list of 2-element tuples and returns two lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unzip([#(1, 2), #(3, 4)])\n" - " // -> #([1, 3], [2, 4])\n" - " ```\n" - "\n" - " ```gleam\n" - " unzip([])\n" - " // -> #([], [])\n" - " ```\n" -). --spec unzip(list({AHE, AHF})) -> {list(AHE), list(AHF)}. -unzip(Input) -> - unzip_loop(Input, [], []). - --file("src/gleam/list.gleam", 1173). --spec intersperse_loop(list(AHT), AHT, list(AHT)) -> list(AHT). -intersperse_loop(List, Separator, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - intersperse_loop(Rest, Separator, [First, Separator | Acc]) - end. - --file("src/gleam/list.gleam", 1166). -?DOC( - " Inserts a given value between each existing element in a given list.\n" - "\n" - " This function runs in linear time and copies the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " intersperse([1, 1, 1], 2)\n" - " // -> [1, 2, 1, 2, 1]\n" - " ```\n" - "\n" - " ```gleam\n" - " intersperse([], 2)\n" - " // -> []\n" - " ```\n" -). --spec intersperse(list(AHQ), AHQ) -> list(AHQ). -intersperse(List, Elem) -> - case List of - [] -> - List; - - [_] -> - List; - - [First | Rest] -> - intersperse_loop(Rest, Elem, [First]) - end. - --file("src/gleam/list.gleam", 1196). --spec unique_loop(list(AIA), gleam@dict:dict(AIA, nil), list(AIA)) -> list(AIA). -unique_loop(List, Seen, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - case gleam@dict:has_key(Seen, First) of - true -> - unique_loop(Rest, Seen, Acc); - - false -> - unique_loop( - Rest, - gleam@dict:insert(Seen, First, nil), - [First | Acc] - ) - end - end. - --file("src/gleam/list.gleam", 1192). -?DOC( - " Removes any duplicate elements from a given list.\n" - "\n" - " This function returns in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unique([1, 1, 1, 4, 7, 3, 3, 4])\n" - " // -> [1, 4, 7, 3]\n" - " ```\n" -). --spec unique(list(AHX)) -> list(AHX). -unique(List) -> - unique_loop(List, maps:new(), []). - --file("src/gleam/list.gleam", 1282). -?DOC( - " Given a list it returns slices of it that are locally sorted in ascending\n" - " order.\n" - "\n" - " Imagine you have this list:\n" - "\n" - " ```\n" - " [1, 2, 3, 2, 1, 0]\n" - " ^^^^^^^ ^^^^^^^ This is a slice in descending order\n" - " |\n" - " | This is a slice that is sorted in ascending order\n" - " ```\n" - "\n" - " So the produced result will contain these two slices, each one sorted in\n" - " ascending order: `[[1, 2, 3], [0, 1, 2]]`.\n" - "\n" - " - `growing` is an accumulator with the current slice being grown\n" - " - `direction` is the growing direction of the slice being grown, it could\n" - " either be ascending or strictly descending\n" - " - `prev` is the previous element that needs to be added to the growing slice\n" - " it is carried around to check whether we have to keep growing the current\n" - " slice or not\n" - " - `acc` is the accumulator containing the slices sorted in ascending order\n" -). --spec sequences( - list(AIJ), - fun((AIJ, AIJ) -> gleam@order:order()), - list(AIJ), - sorting(), - AIJ, - list(list(AIJ)) -) -> list(list(AIJ)). -sequences(List, Compare, Growing, Direction, Prev, Acc) -> - Growing@1 = [Prev | Growing], - case List of - [] -> - case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end; - - [New | Rest] -> - case {Compare(Prev, New), Direction} of - {gt, descending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {lt, ascending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {eq, ascending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {gt, ascending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end; - - {lt, descending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end; - - {eq, descending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end - end - end. - --file("src/gleam/list.gleam", 1430). -?DOC( - " Merges two lists sorted in ascending order into a single list sorted in\n" - " descending order according to the given comparator function.\n" - "\n" - " This reversing of the sort order is not avoidable if we want to implement\n" - " merge as a tail recursive function. We could reverse the accumulator before\n" - " returning it but that would end up being less efficient; so the merging\n" - " algorithm has to play around this.\n" -). --spec merge_ascendings( - list(AJG), - list(AJG), - fun((AJG, AJG) -> gleam@order:order()), - list(AJG) -) -> list(AJG). -merge_ascendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - lists:reverse(List, Acc); - - {List, []} -> - lists:reverse(List, Acc); - - {[First1 | Rest1], [First2 | Rest2]} -> - case Compare(First1, First2) of - lt -> - merge_ascendings(Rest1, List2, Compare, [First1 | Acc]); - - gt -> - merge_ascendings(List1, Rest2, Compare, [First2 | Acc]); - - eq -> - merge_ascendings(List1, Rest2, Compare, [First2 | Acc]) - end - end. - --file("src/gleam/list.gleam", 1383). -?DOC( - " Given a list of ascending lists, it merges adjacent pairs into a single\n" - " descending list, halving their number.\n" - " It returns a list of the remaining descending lists.\n" -). --spec merge_ascending_pairs( - list(list(AIU)), - fun((AIU, AIU) -> gleam@order:order()), - list(list(AIU)) -) -> list(list(AIU)). -merge_ascending_pairs(Sequences, Compare, Acc) -> - case Sequences of - [] -> - lists:reverse(Acc); - - [Sequence] -> - lists:reverse([lists:reverse(Sequence) | Acc]); - - [Ascending1, Ascending2 | Rest] -> - Descending = merge_ascendings(Ascending1, Ascending2, Compare, []), - merge_ascending_pairs(Rest, Compare, [Descending | Acc]) - end. - --file("src/gleam/list.gleam", 1457). -?DOC( - " This is exactly the same as merge_ascendings but mirrored: it merges two\n" - " lists sorted in descending order into a single list sorted in ascending\n" - " order according to the given comparator function.\n" - "\n" - " This reversing of the sort order is not avoidable if we want to implement\n" - " merge as a tail recursive function. We could reverse the accumulator before\n" - " returning it but that would end up being less efficient; so the merging\n" - " algorithm has to play around this.\n" -). --spec merge_descendings( - list(AJL), - list(AJL), - fun((AJL, AJL) -> gleam@order:order()), - list(AJL) -) -> list(AJL). -merge_descendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - lists:reverse(List, Acc); - - {List, []} -> - lists:reverse(List, Acc); - - {[First1 | Rest1], [First2 | Rest2]} -> - case Compare(First1, First2) of - lt -> - merge_descendings(List1, Rest2, Compare, [First2 | Acc]); - - gt -> - merge_descendings(Rest1, List2, Compare, [First1 | Acc]); - - eq -> - merge_descendings(Rest1, List2, Compare, [First1 | Acc]) - end - end. - --file("src/gleam/list.gleam", 1405). -?DOC(" This is the same as merge_ascending_pairs but flipped for descending lists.\n"). --spec merge_descending_pairs( - list(list(AJA)), - fun((AJA, AJA) -> gleam@order:order()), - list(list(AJA)) -) -> list(list(AJA)). -merge_descending_pairs(Sequences, Compare, Acc) -> - case Sequences of - [] -> - lists:reverse(Acc); - - [Sequence] -> - lists:reverse([lists:reverse(Sequence) | Acc]); - - [Descending1, Descending2 | Rest] -> - Ascending = merge_descendings(Descending1, Descending2, Compare, []), - merge_descending_pairs(Rest, Compare, [Ascending | Acc]) - end. - --file("src/gleam/list.gleam", 1349). -?DOC( - " Given some some sorted sequences (assumed to be sorted in `direction`) it\n" - " merges them all together until we're left with just a list sorted in\n" - " ascending order.\n" -). --spec merge_all( - list(list(AIQ)), - sorting(), - fun((AIQ, AIQ) -> gleam@order:order()) -) -> list(AIQ). -merge_all(Sequences, Direction, Compare) -> - case {Sequences, Direction} of - {[], _} -> - []; - - {[Sequence], ascending} -> - Sequence; - - {[Sequence@1], descending} -> - lists:reverse(Sequence@1); - - {_, ascending} -> - Sequences@1 = merge_ascending_pairs(Sequences, Compare, []), - merge_all(Sequences@1, descending, Compare); - - {_, descending} -> - Sequences@2 = merge_descending_pairs(Sequences, Compare, []), - merge_all(Sequences@2, ascending, Compare) - end. - --file("src/gleam/list.gleam", 1220). -?DOC( - " Sorts from smallest to largest based upon the ordering specified by a given\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " sort([4, 3, 6, 5, 4, 1, 2], by: int.compare)\n" - " // -> [1, 2, 3, 4, 4, 5, 6]\n" - " ```\n" -). --spec sort(list(AIG), fun((AIG, AIG) -> gleam@order:order())) -> list(AIG). -sort(List, Compare) -> - case List of - [] -> - []; - - [X] -> - [X]; - - [X@1, Y | Rest] -> - Direction = case Compare(X@1, Y) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - Sequences = sequences(Rest, Compare, [X@1], Direction, Y, []), - merge_all(Sequences, ascending, Compare) - end. - --file("src/gleam/list.gleam", 1497). --spec range_loop(integer(), integer(), list(integer())) -> list(integer()). -range_loop(Start, Stop, Acc) -> - case gleam@int:compare(Start, Stop) of - eq -> - [Stop | Acc]; - - gt -> - range_loop(Start, Stop + 1, [Stop | Acc]); - - lt -> - range_loop(Start, Stop - 1, [Stop | Acc]) - end. - --file("src/gleam/list.gleam", 1493). -?DOC( - " Creates a list of ints ranging from a given start and finish.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " range(0, 0)\n" - " // -> [0]\n" - " ```\n" - "\n" - " ```gleam\n" - " range(0, 5)\n" - " // -> [0, 1, 2, 3, 4, 5]\n" - " ```\n" - "\n" - " ```gleam\n" - " range(1, -5)\n" - " // -> [1, 0, -1, -2, -3, -4, -5]\n" - " ```\n" -). --spec range(integer(), integer()) -> list(integer()). -range(Start, Stop) -> - range_loop(Start, Stop, []). - --file("src/gleam/list.gleam", 1523). --spec repeat_loop(AJV, integer(), list(AJV)) -> list(AJV). -repeat_loop(Item, Times, Acc) -> - case Times =< 0 of - true -> - Acc; - - false -> - repeat_loop(Item, Times - 1, [Item | Acc]) - end. - --file("src/gleam/list.gleam", 1519). -?DOC( - " Builds a list of a given value a given number of times.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " repeat(\"a\", times: 0)\n" - " // -> []\n" - " ```\n" - "\n" - " ```gleam\n" - " repeat(\"a\", times: 5)\n" - " // -> [\"a\", \"a\", \"a\", \"a\", \"a\"]\n" - " ```\n" -). --spec repeat(AJT, integer()) -> list(AJT). -repeat(A, Times) -> - repeat_loop(A, Times, []). - --file("src/gleam/list.gleam", 1556). --spec split_loop(list(AKC), integer(), list(AKC)) -> {list(AKC), list(AKC)}. -split_loop(List, N, Taken) -> - case N =< 0 of - true -> - {lists:reverse(Taken), List}; - - false -> - case List of - [] -> - {lists:reverse(Taken), []}; - - [First | Rest] -> - split_loop(Rest, N - 1, [First | Taken]) - end - end. - --file("src/gleam/list.gleam", 1552). -?DOC( - " Splits a list in two before the given index.\n" - "\n" - " If the list is not long enough to have the given index the before list will\n" - " be the input list, and the after list will be empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split([6, 7, 8, 9], 0)\n" - " // -> #([], [6, 7, 8, 9])\n" - " ```\n" - "\n" - " ```gleam\n" - " split([6, 7, 8, 9], 2)\n" - " // -> #([6, 7], [8, 9])\n" - " ```\n" - "\n" - " ```gleam\n" - " split([6, 7, 8, 9], 4)\n" - " // -> #([6, 7, 8, 9], [])\n" - " ```\n" -). --spec split(list(AJY), integer()) -> {list(AJY), list(AJY)}. -split(List, Index) -> - split_loop(List, Index, []). - --file("src/gleam/list.gleam", 1592). --spec split_while_loop(list(AKL), fun((AKL) -> boolean()), list(AKL)) -> {list(AKL), - list(AKL)}. -split_while_loop(List, F, Acc) -> - case List of - [] -> - {lists:reverse(Acc), []}; - - [First | Rest] -> - case F(First) of - true -> - split_while_loop(Rest, F, [First | Acc]); - - false -> - {lists:reverse(Acc), List} - end - end. - --file("src/gleam/list.gleam", 1585). -?DOC( - " Splits a list in two before the first element that a given function returns\n" - " `False` for.\n" - "\n" - " If the function returns `True` for all elements the first list will be the\n" - " input list, and the second list will be empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 })\n" - " // -> #([1, 2, 3], [4, 5])\n" - " ```\n" - "\n" - " ```gleam\n" - " split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 })\n" - " // -> #([1, 2, 3, 4, 5], [])\n" - " ```\n" -). --spec split_while(list(AKH), fun((AKH) -> boolean())) -> {list(AKH), list(AKH)}. -split_while(List, Predicate) -> - split_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1632). -?DOC( - " Given a list of 2-element tuples, finds the first tuple that has a given\n" - " key as the first element and returns the second element.\n" - "\n" - " If no tuple is found with the given key then `Error(Nil)` is returned.\n" - "\n" - " This function may be useful for interacting with Erlang code where lists of\n" - " tuples are common.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_find([#(\"a\", 0), #(\"b\", 1)], \"a\")\n" - " // -> Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " key_find([#(\"a\", 0), #(\"b\", 1)], \"b\")\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " key_find([#(\"a\", 0), #(\"b\", 1)], \"c\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec key_find(list({AKQ, AKR}), AKQ) -> {ok, AKR} | {error, nil}. -key_find(Keyword_list, Desired_key) -> - find_map( - Keyword_list, - fun(Keyword) -> - {Key, Value} = Keyword, - case Key =:= Desired_key of - true -> - {ok, Value}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/list.gleam", 1663). -?DOC( - " Given a list of 2-element tuples, finds all tuples that have a given\n" - " key as the first element and returns the second element.\n" - "\n" - " This function may be useful for interacting with Erlang code where lists of\n" - " tuples are common.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_filter([#(\"a\", 0), #(\"b\", 1), #(\"a\", 2)], \"a\")\n" - " // -> [0, 2]\n" - " ```\n" - "\n" - " ```gleam\n" - " key_filter([#(\"a\", 0), #(\"b\", 1)], \"c\")\n" - " // -> []\n" - " ```\n" -). --spec key_filter(list({AKV, AKW}), AKV) -> list(AKW). -key_filter(Keyword_list, Desired_key) -> - filter_map( - Keyword_list, - fun(Keyword) -> - {Key, Value} = Keyword, - case Key =:= Desired_key of - true -> - {ok, Value}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/list.gleam", 1703). --spec key_pop_loop(list({ALF, ALG}), ALF, list({ALF, ALG})) -> {ok, - {ALG, list({ALF, ALG})}} | - {error, nil}. -key_pop_loop(List, Key, Checked) -> - case List of - [] -> - {error, nil}; - - [{K, V} | Rest] when K =:= Key -> - {ok, {V, lists:reverse(Checked, Rest)}}; - - [First | Rest@1] -> - key_pop_loop(Rest@1, Key, [First | Checked]) - end. - --file("src/gleam/list.gleam", 1699). -?DOC( - " Given a list of 2-element tuples, finds the first tuple that has a given\n" - " key as the first element. This function will return the second element\n" - " of the found tuple and list with tuple removed.\n" - "\n" - " If no tuple is found with the given key then `Error(Nil)` is returned.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_pop([#(\"a\", 0), #(\"b\", 1)], \"a\")\n" - " // -> Ok(#(0, [#(\"b\", 1)]))\n" - " ```\n" - "\n" - " ```gleam\n" - " key_pop([#(\"a\", 0), #(\"b\", 1)], \"b\")\n" - " // -> Ok(#(1, [#(\"a\", 0)]))\n" - " ```\n" - "\n" - " ```gleam\n" - " key_pop([#(\"a\", 0), #(\"b\", 1)], \"c\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec key_pop(list({AKZ, ALA}), AKZ) -> {ok, {ALA, list({AKZ, ALA})}} | - {error, nil}. -key_pop(List, Key) -> - key_pop_loop(List, Key, []). - --file("src/gleam/list.gleam", 1737). --spec key_set_loop(list({ALQ, ALR}), ALQ, ALR, list({ALQ, ALR})) -> list({ALQ, - ALR}). -key_set_loop(List, Key, Value, Inspected) -> - case List of - [{K, _} | Rest] when K =:= Key -> - lists:reverse(Inspected, [{K, Value} | Rest]); - - [First | Rest@1] -> - key_set_loop(Rest@1, Key, Value, [First | Inspected]); - - [] -> - lists:reverse([{Key, Value} | Inspected]) - end. - --file("src/gleam/list.gleam", 1733). -?DOC( - " Given a list of 2-element tuples, inserts a key and value into the list.\n" - "\n" - " If there was already a tuple with the key then it is replaced, otherwise it\n" - " is added to the end of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " key_set([#(5, 0), #(4, 1)], 4, 100)\n" - " // -> [#(5, 0), #(4, 100)]\n" - " ```\n" - "\n" - " ```gleam\n" - " key_set([#(5, 0), #(4, 1)], 1, 100)\n" - " // -> [#(5, 0), #(4, 1), #(1, 100)]\n" - " ```\n" -). --spec key_set(list({ALM, ALN}), ALM, ALN) -> list({ALM, ALN}). -key_set(List, Key, Value) -> - key_set_loop(List, Key, Value, []). - --file("src/gleam/list.gleam", 1765). -?DOC( - " Calls a function for each element in a list, discarding the return value.\n" - "\n" - " Useful for calling a side effect for every item of a list.\n" - "\n" - " ```gleam\n" - " import gleam/io\n" - "\n" - " each([\"1\", \"2\", \"3\"], io.println)\n" - " // -> Nil\n" - " // 1\n" - " // 2\n" - " // 3\n" - " ```\n" -). --spec each(list(ALV), fun((ALV) -> any())) -> nil. -each(List, F) -> - case List of - [] -> - nil; - - [First | Rest] -> - F(First), - each(Rest, F) - end. - --file("src/gleam/list.gleam", 1791). -?DOC( - " Calls a `Result` returning function for each element in a list, discarding\n" - " the return value. If the function returns `Error` then the iteration is\n" - " stopped and the error is returned.\n" - "\n" - " Useful for calling a side effect for every item of a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " try_each(\n" - " over: [1, 2, 3],\n" - " with: function_that_might_fail,\n" - " )\n" - " // -> Ok(Nil)\n" - " ```\n" -). --spec try_each(list(ALY), fun((ALY) -> {ok, any()} | {error, AMB})) -> {ok, nil} | - {error, AMB}. -try_each(List, Fun) -> - case List of - [] -> - {ok, nil}; - - [First | Rest] -> - case Fun(First) of - {ok, _} -> - try_each(Rest, Fun); - - {error, E} -> - {error, E} - end - end. - --file("src/gleam/list.gleam", 1824). --spec partition_loop(list(BFR), fun((BFR) -> boolean()), list(BFR), list(BFR)) -> {list(BFR), - list(BFR)}. -partition_loop(List, Categorise, Trues, Falses) -> - case List of - [] -> - {lists:reverse(Trues), lists:reverse(Falses)}; - - [First | Rest] -> - case Categorise(First) of - true -> - partition_loop(Rest, Categorise, [First | Trues], Falses); - - false -> - partition_loop(Rest, Categorise, Trues, [First | Falses]) - end - end. - --file("src/gleam/list.gleam", 1817). -?DOC( - " Partitions a list into a tuple/pair of lists\n" - " by a given categorisation function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " [1, 2, 3, 4, 5] |> partition(int.is_odd)\n" - " // -> #([1, 3, 5], [2, 4])\n" - " ```\n" -). --spec partition(list(AMG), fun((AMG) -> boolean())) -> {list(AMG), list(AMG)}. -partition(List, Categorise) -> - partition_loop(List, Categorise, [], []). - --file("src/gleam/list.gleam", 1904). --spec window_loop(list(list(ANN)), list(ANN), integer()) -> list(list(ANN)). -window_loop(Acc, List, N) -> - Window = take(List, N), - case erlang:length(Window) =:= N of - true -> - window_loop([Window | Acc], drop(List, 1), N); - - false -> - lists:reverse(Acc) - end. - --file("src/gleam/list.gleam", 1897). -?DOC( - " Returns a list of sliding windows.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " window([1,2,3,4,5], 3)\n" - " // -> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]\n" - " ```\n" - "\n" - " ```gleam\n" - " window([1, 2], 4)\n" - " // -> []\n" - " ```\n" -). --spec window(list(ANJ), integer()) -> list(list(ANJ)). -window(List, N) -> - case N =< 0 of - true -> - []; - - false -> - window_loop([], List, N) - end. - --file("src/gleam/list.gleam", 1927). -?DOC( - " Returns a list of tuples containing two contiguous elements.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " window_by_2([1,2,3,4])\n" - " // -> [#(1, 2), #(2, 3), #(3, 4)]\n" - " ```\n" - "\n" - " ```gleam\n" - " window_by_2([1])\n" - " // -> []\n" - " ```\n" -). --spec window_by_2(list(ANT)) -> list({ANT, ANT}). -window_by_2(List) -> - zip(List, drop(List, 1)). - --file("src/gleam/list.gleam", 1940). -?DOC( - " Drops the first elements in a given list for which the predicate function returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop_while([1, 2, 3, 4], fn (x) { x < 3 })\n" - " // -> [3, 4]\n" - " ```\n" -). --spec drop_while(list(ANW), fun((ANW) -> boolean())) -> list(ANW). -drop_while(List, Predicate) -> - case List of - [] -> - []; - - [First | Rest] -> - case Predicate(First) of - true -> - drop_while(Rest, Predicate); - - false -> - [First | Rest] - end - end. - --file("src/gleam/list.gleam", 1970). --spec take_while_loop(list(AOC), fun((AOC) -> boolean()), list(AOC)) -> list(AOC). -take_while_loop(List, Predicate, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - case Predicate(First) of - true -> - take_while_loop(Rest, Predicate, [First | Acc]); - - false -> - lists:reverse(Acc) - end - end. - --file("src/gleam/list.gleam", 1963). -?DOC( - " Takes the first elements in a given list for which the predicate function returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " take_while([1, 2, 3, 2, 4], fn (x) { x < 3 })\n" - " // -> [1, 2]\n" - " ```\n" -). --spec take_while(list(ANZ), fun((ANZ) -> boolean())) -> list(ANZ). -take_while(List, Predicate) -> - take_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 2002). --spec chunk_loop(list(AOL), fun((AOL) -> AON), AON, list(AOL), list(list(AOL))) -> list(list(AOL)). -chunk_loop(List, F, Previous_key, Current_chunk, Acc) -> - case List of - [First | Rest] -> - Key = F(First), - case Key =:= Previous_key of - true -> - chunk_loop(Rest, F, Key, [First | Current_chunk], Acc); - - false -> - New_acc = [lists:reverse(Current_chunk) | Acc], - chunk_loop(Rest, F, Key, [First], New_acc) - end; - - [] -> - lists:reverse([lists:reverse(Current_chunk) | Acc]) - end. - --file("src/gleam/list.gleam", 1995). -?DOC( - " Returns a list of chunks in which\n" - " the return value of calling `f` on each element is the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 })\n" - " // -> [[1], [2, 2], [3], [4, 4, 6], [7, 7]]\n" - " ```\n" -). --spec chunk(list(AOG), fun((AOG) -> any())) -> list(list(AOG)). -chunk(List, F) -> - case List of - [] -> - []; - - [First | Rest] -> - chunk_loop(Rest, F, F(First), [First], []) - end. - --file("src/gleam/list.gleam", 2047). --spec sized_chunk_loop( - list(AOX), - integer(), - integer(), - list(AOX), - list(list(AOX)) -) -> list(list(AOX)). -sized_chunk_loop(List, Count, Left, Current_chunk, Acc) -> - case List of - [] -> - case Current_chunk of - [] -> - lists:reverse(Acc); - - Remaining -> - lists:reverse([lists:reverse(Remaining) | Acc]) - end; - - [First | Rest] -> - Chunk = [First | Current_chunk], - case Left > 1 of - true -> - sized_chunk_loop(Rest, Count, Left - 1, Chunk, Acc); - - false -> - sized_chunk_loop( - Rest, - Count, - Count, - [], - [lists:reverse(Chunk) | Acc] - ) - end - end. - --file("src/gleam/list.gleam", 2043). -?DOC( - " Returns a list of chunks containing `count` elements each.\n" - "\n" - " If the last chunk does not have `count` elements, it is instead\n" - " a partial chunk, with less than `count` elements.\n" - "\n" - " For any `count` less than 1 this function behaves as if it was set to 1.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2)\n" - " // -> [[1, 2], [3, 4], [5, 6]]\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3)\n" - " // -> [[1, 2, 3], [4, 5, 6], [7, 8]]\n" - " ```\n" -). --spec sized_chunk(list(AOT), integer()) -> list(list(AOT)). -sized_chunk(List, Count) -> - sized_chunk_loop(List, Count, Count, [], []). - --file("src/gleam/list.gleam", 2091). -?DOC( - " This function acts similar to fold, but does not take an initial state.\n" - " Instead, it starts from the first element in the list\n" - " and combines it with each subsequent element in turn using the given\n" - " function. The function is called as `fun(accumulator, current_element)`.\n" - "\n" - " Returns `Ok` to indicate a successful run, and `Error` if called on an\n" - " empty list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " [] |> reduce(fn(acc, x) { acc + x })\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x })\n" - " // -> Ok(15)\n" - " ```\n" -). --spec reduce(list(APE), fun((APE, APE) -> APE)) -> {ok, APE} | {error, nil}. -reduce(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, fold(Rest, First, Fun)} - end. - --file("src/gleam/list.gleam", 2115). --spec scan_loop(list(APM), APO, list(APO), fun((APO, APM) -> APO)) -> list(APO). -scan_loop(List, Accumulator, Accumulated, Fun) -> - case List of - [] -> - lists:reverse(Accumulated); - - [First | Rest] -> - Next = Fun(Accumulator, First), - scan_loop(Rest, Next, [Next | Accumulated], Fun) - end. - --file("src/gleam/list.gleam", 2107). -?DOC( - " Similar to `fold`, but yields the state of the accumulator at each stage.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i })\n" - " // -> [101, 103, 106]\n" - " ```\n" -). --spec scan(list(API), APK, fun((APK, API) -> APK)) -> list(APK). -scan(List, Initial, Fun) -> - scan_loop(List, Initial, [], Fun). - --file("src/gleam/list.gleam", 2148). -?DOC( - " Returns the last element in the given list.\n" - "\n" - " Returns `Error(Nil)` if the list is empty.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " last([])\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " last([1, 2, 3, 4, 5])\n" - " // -> Ok(5)\n" - " ```\n" -). --spec last(list(APR)) -> {ok, APR} | {error, nil}. -last(List) -> - case List of - [] -> - {error, nil}; - - [Last] -> - {ok, Last}; - - [_ | Rest] -> - last(Rest) - end. - --file("src/gleam/list.gleam", 2170). -?DOC( - " Return unique combinations of elements in the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " combinations([1, 2, 3], 2)\n" - " // -> [[1, 2], [1, 3], [2, 3]]\n" - " ```\n" - "\n" - " ```gleam\n" - " combinations([1, 2, 3, 4], 3)\n" - " // -> [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]\n" - " ```\n" -). --spec combinations(list(APV), integer()) -> list(list(APV)). -combinations(Items, N) -> - case {N, Items} of - {0, _} -> - [[]]; - - {_, []} -> - []; - - {_, [First | Rest]} -> - _pipe = Rest, - _pipe@1 = combinations(_pipe, N - 1), - _pipe@2 = map( - _pipe@1, - fun(Combination) -> [First | Combination] end - ), - _pipe@3 = lists:reverse(_pipe@2), - fold(_pipe@3, combinations(Rest, N), fun(Acc, C) -> [C | Acc] end) - end. - --file("src/gleam/list.gleam", 2196). --spec combination_pairs_loop(list(AQC), list({AQC, AQC})) -> list({AQC, AQC}). -combination_pairs_loop(Items, Acc) -> - case Items of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - First_combinations = map(Rest, fun(Other) -> {First, Other} end), - Acc@1 = lists:reverse(First_combinations, Acc), - combination_pairs_loop(Rest, Acc@1) - end. - --file("src/gleam/list.gleam", 2192). -?DOC( - " Return unique pair combinations of elements in the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " combination_pairs([1, 2, 3])\n" - " // -> [#(1, 2), #(1, 3), #(2, 3)]\n" - " ```\n" -). --spec combination_pairs(list(APZ)) -> list({APZ, APZ}). -combination_pairs(Items) -> - combination_pairs_loop(Items, []). - --file("src/gleam/list.gleam", 2252). --spec take_firsts(list(list(AQW)), list(AQW), list(list(AQW))) -> {list(AQW), - list(list(AQW))}. -take_firsts(Rows, Column, Remaining_rows) -> - case Rows of - [] -> - {lists:reverse(Column), lists:reverse(Remaining_rows)}; - - [[] | Rest] -> - take_firsts(Rest, Column, Remaining_rows); - - [[First | Remaining_row] | Rest_rows] -> - Remaining_rows@1 = [Remaining_row | Remaining_rows], - take_firsts(Rest_rows, [First | Column], Remaining_rows@1) - end. - --file("src/gleam/list.gleam", 2239). --spec transpose_loop(list(list(AQP)), list(list(AQP))) -> list(list(AQP)). -transpose_loop(Rows, Columns) -> - case Rows of - [] -> - lists:reverse(Columns); - - _ -> - {Column, Rest} = take_firsts(Rows, [], []), - case Column of - [_ | _] -> - transpose_loop(Rest, [Column | Columns]); - - [] -> - transpose_loop(Rest, Columns) - end - end. - --file("src/gleam/list.gleam", 2235). -?DOC( - " Transpose rows and columns of the list of lists.\n" - "\n" - " Notice: This function is not tail recursive,\n" - " and thus may exceed stack size if called,\n" - " with large lists (on the JavaScript target).\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " transpose([[1, 2, 3], [101, 102, 103]])\n" - " // -> [[1, 101], [2, 102], [3, 103]]\n" - " ```\n" -). --spec transpose(list(list(AQK))) -> list(list(AQK)). -transpose(List_of_lists) -> - transpose_loop(List_of_lists, []). - --file("src/gleam/list.gleam", 2216). -?DOC( - " Make a list alternating the elements from the given lists\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " interleave([[1, 2], [101, 102], [201, 202]])\n" - " // -> [1, 101, 201, 2, 102, 202]\n" - " ```\n" -). --spec interleave(list(list(AQG))) -> list(AQG). -interleave(List) -> - _pipe = List, - _pipe@1 = transpose(_pipe), - lists:append(_pipe@1). - --file("src/gleam/list.gleam", 2285). --spec shuffle_pair_unwrap_loop(list({float(), ARI}), list(ARI)) -> list(ARI). -shuffle_pair_unwrap_loop(List, Acc) -> - case List of - [] -> - Acc; - - [Elem_pair | Enumerable] -> - shuffle_pair_unwrap_loop( - Enumerable, - [erlang:element(2, Elem_pair) | Acc] - ) - end. - --file("src/gleam/list.gleam", 2293). --spec do_shuffle_by_pair_indexes(list({float(), ARM})) -> list({float(), ARM}). -do_shuffle_by_pair_indexes(List_of_pairs) -> - sort( - List_of_pairs, - fun(A_pair, B_pair) -> - gleam@float:compare( - erlang:element(1, A_pair), - erlang:element(1, B_pair) - ) - end - ). - --file("src/gleam/list.gleam", 2278). -?DOC( - " Takes a list, randomly sorts all items and returns the shuffled list.\n" - "\n" - " This function uses `float.random` to decide the order of the elements.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " range(1, 10) |> shuffle()\n" - " // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5]\n" - " ```\n" -). --spec shuffle(list(ARF)) -> list(ARF). -shuffle(List) -> - _pipe = List, - _pipe@1 = fold(_pipe, [], fun(Acc, A) -> [{rand:uniform(), A} | Acc] end), - _pipe@2 = do_shuffle_by_pair_indexes(_pipe@1), - shuffle_pair_unwrap_loop(_pipe@2, []). - --file("src/gleam/list.gleam", 2325). --spec max_loop(list(ARW), fun((ARW, ARW) -> gleam@order:order()), ARW) -> ARW. -max_loop(List, Compare, Max) -> - case List of - [] -> - Max; - - [First | Rest] -> - case Compare(First, Max) of - gt -> - max_loop(Rest, Compare, First); - - lt -> - max_loop(Rest, Compare, Max); - - eq -> - max_loop(Rest, Compare, Max) - end - end. - --file("src/gleam/list.gleam", 2315). -?DOC( - " Takes a list and a comparator, and returns the maximum element in the list\n" - "\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " range(1, 10) |> list.max(int.compare)\n" - " // -> Ok(10)\n" - " ```\n" - "\n" - " ```gleam\n" - " [\"a\", \"c\", \"b\"] |> list.max(string.compare)\n" - " // -> Ok(\"c\")\n" - " ```\n" -). --spec max(list(ARP), fun((ARP, ARP) -> gleam@order:order())) -> {ok, ARP} | - {error, nil}. -max(List, Compare) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, max_loop(Rest, Compare, First)} - end. - --file("src/gleam/list.gleam", 2406). --spec build_reservoir_loop( - list(ASL), - integer(), - gleam@dict:dict(integer(), ASL) -) -> {gleam@dict:dict(integer(), ASL), list(ASL)}. -build_reservoir_loop(List, Size, Reservoir) -> - Reservoir_size = maps:size(Reservoir), - case Reservoir_size >= Size of - true -> - {Reservoir, List}; - - false -> - case List of - [] -> - {Reservoir, []}; - - [First | Rest] -> - Reservoir@1 = gleam@dict:insert( - Reservoir, - Reservoir_size, - First - ), - build_reservoir_loop(Rest, Size, Reservoir@1) - end - end. - --file("src/gleam/list.gleam", 2402). -?DOC( - " Builds the initial reservoir used by Algorithm L.\n" - " This is a dictionary with keys ranging from `0` up to `n - 1` where each\n" - " value is the corresponding element at that position in `list`.\n" - "\n" - " This also returns the remaining elements of `list` that didn't end up in\n" - " the reservoir.\n" -). --spec build_reservoir(list(ASG), integer()) -> {gleam@dict:dict(integer(), ASG), - list(ASG)}. -build_reservoir(List, N) -> - build_reservoir_loop(List, N, maps:new()). - --file("src/gleam/list.gleam", 2390). --spec log_random() -> float(). -log_random() -> - Random@1 = case gleam@float:logarithm( - rand:uniform() + 2.2250738585072014e-308 - ) of - {ok, Random} -> Random; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam/list"/utf8>>, - function => <<"log_random"/utf8>>, - line => 2391, - value => _assert_fail, - start => 56078, - 'end' => 56149, - pattern_start => 56089, - pattern_end => 56099}) - end, - Random@1. - --file("src/gleam/list.gleam", 2367). --spec sample_loop( - list(ASA), - gleam@dict:dict(integer(), ASA), - integer(), - float() -) -> gleam@dict:dict(integer(), ASA). -sample_loop(List, Reservoir, N, W) -> - Skip = begin - Log@1 = case gleam@float:logarithm(1.0 - W) of - {ok, Log} -> Log; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam/list"/utf8>>, - function => <<"sample_loop"/utf8>>, - line => 2374, - value => _assert_fail, - start => 55639, - 'end' => 55685, - pattern_start => 55650, - pattern_end => 55657}) - end, - erlang:round(math:floor(case Log@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> log_random() / Gleam@denominator - end)) - end, - case drop(List, Skip) of - [] -> - Reservoir; - - [First | Rest] -> - Reservoir@1 = gleam@dict:insert( - Reservoir, - gleam@int:random(N), - First - ), - W@1 = W * math:exp(case erlang:float(N) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> log_random() / Gleam@denominator@1 - end), - sample_loop(Rest, Reservoir@1, N, W@1) - end. - --file("src/gleam/list.gleam", 2349). -?DOC( - " Returns a random sample of up to n elements from a list using reservoir\n" - " sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L).\n" - " Returns an empty list if the sample size is less than or equal to 0.\n" - "\n" - " Order is not random, only selection is.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " reservoir_sample([1, 2, 3, 4, 5], 3)\n" - " // -> [2, 4, 5] // A random sample of 3 items\n" - " ```\n" -). --spec sample(list(ARX), integer()) -> list(ARX). -sample(List, N) -> - {Reservoir, Rest} = build_reservoir(List, N), - case gleam@dict:is_empty(Reservoir) of - true -> - []; - - false -> - W = math:exp(case erlang:float(N) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> log_random() / Gleam@denominator - end), - maps:values(sample_loop(Rest, Reservoir, N, W)) - end. - --file("src/gleam/list.gleam", 1851). --spec permutation_zip(list(AMT), list(AMT), list(list(AMT))) -> list(list(AMT)). -permutation_zip(List, Rest, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [Head | Tail] -> - permutation_prepend( - Head, - permutations(lists:reverse(Rest, Tail)), - Tail, - [Head | Rest], - Acc - ) - end. - --file("src/gleam/list.gleam", 1869). --spec permutation_prepend( - ANA, - list(list(ANA)), - list(ANA), - list(ANA), - list(list(ANA)) -) -> list(list(ANA)). -permutation_prepend(El, Permutations, List_1, List_2, Acc) -> - case Permutations of - [] -> - permutation_zip(List_1, List_2, Acc); - - [Head | Tail] -> - permutation_prepend(El, Tail, List_1, List_2, [[El | Head] | Acc]) - end. - --file("src/gleam/list.gleam", 1844). -?DOC( - " Returns all the permutations of a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " permutations([1, 2])\n" - " // -> [[1, 2], [2, 1]]\n" - " ```\n" -). --spec permutations(list(AMP)) -> list(list(AMP)). -permutations(List) -> - case List of - [] -> - [[]]; - - L -> - permutation_zip(L, [], []) - end. diff --git a/build/packages/gleam_stdlib/src/gleam@option.erl b/build/packages/gleam_stdlib/src/gleam@option.erl deleted file mode 100644 index 8e86a8e..0000000 --- a/build/packages/gleam_stdlib/src/gleam@option.erl +++ /dev/null @@ -1,413 +0,0 @@ --module(gleam@option). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/option.gleam"). --export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]). --export_type([option/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type option(FG) :: {some, FG} | none. - --file("src/gleam/option.gleam", 59). --spec reverse_and_prepend(list(FV), list(FV)) -> list(FV). -reverse_and_prepend(Prefix, Suffix) -> - case Prefix of - [] -> - Suffix; - - [First | Rest] -> - reverse_and_prepend(Rest, [First | Suffix]) - end. - --file("src/gleam/option.gleam", 44). --spec all_loop(list(option(FM)), list(FM)) -> option(list(FM)). -all_loop(List, Acc) -> - case List of - [] -> - {some, lists:reverse(Acc)}; - - [none | _] -> - none; - - [{some, First} | Rest] -> - all_loop(Rest, [First | Acc]) - end. - --file("src/gleam/option.gleam", 40). -?DOC( - " Combines a list of `Option`s into a single `Option`.\n" - " If all elements in the list are `Some` then returns a `Some` holding the list of values.\n" - " If any element is `None` then returns`None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " all([Some(1), Some(2)])\n" - " // -> Some([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " all([Some(1), None])\n" - " // -> None\n" - " ```\n" -). --spec all(list(option(FH))) -> option(list(FH)). -all(List) -> - all_loop(List, []). - --file("src/gleam/option.gleam", 80). -?DOC( - " Checks whether the `Option` is a `Some` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_some(Some(1))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_some(None)\n" - " // -> False\n" - " ```\n" -). --spec is_some(option(any())) -> boolean(). -is_some(Option) -> - Option /= none. - --file("src/gleam/option.gleam", 98). -?DOC( - " Checks whether the `Option` is a `None` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_none(Some(1))\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_none(None)\n" - " // -> True\n" - " ```\n" -). --spec is_none(option(any())) -> boolean(). -is_none(Option) -> - Option =:= none. - --file("src/gleam/option.gleam", 116). -?DOC( - " Converts an `Option` type to a `Result` type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_result(Some(1), \"some_error\")\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " to_result(None, \"some_error\")\n" - " // -> Error(\"some_error\")\n" - " ```\n" -). --spec to_result(option(GD), GG) -> {ok, GD} | {error, GG}. -to_result(Option, E) -> - case Option of - {some, A} -> - {ok, A}; - - none -> - {error, E} - end. - --file("src/gleam/option.gleam", 137). -?DOC( - " Converts a `Result` type to an `Option` type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_result(Ok(1))\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " from_result(Error(\"some_error\"))\n" - " // -> None\n" - " ```\n" -). --spec from_result({ok, GJ} | {error, any()}) -> option(GJ). -from_result(Result) -> - case Result of - {ok, A} -> - {some, A}; - - {error, _} -> - none - end. - --file("src/gleam/option.gleam", 158). -?DOC( - " Extracts the value from an `Option`, returning a default value if there is none.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap(Some(1), 0)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap(None, 0)\n" - " // -> 0\n" - " ```\n" -). --spec unwrap(option(GO), GO) -> GO. -unwrap(Option, Default) -> - case Option of - {some, X} -> - X; - - none -> - Default - end. - --file("src/gleam/option.gleam", 179). -?DOC( - " Extracts the value from an `Option`, evaluating the default function if the option is `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_unwrap(Some(1), fn() { 0 })\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_unwrap(None, fn() { 0 })\n" - " // -> 0\n" - " ```\n" -). --spec lazy_unwrap(option(GQ), fun(() -> GQ)) -> GQ. -lazy_unwrap(Option, Default) -> - case Option of - {some, X} -> - X; - - none -> - Default() - end. - --file("src/gleam/option.gleam", 204). -?DOC( - " Updates a value held within the `Some` of an `Option` by calling a given function\n" - " on it.\n" - "\n" - " If the `Option` is a `None` rather than `Some`, the function is not called and the\n" - " `Option` stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map(over: Some(1), with: fn(x) { x + 1 })\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " map(over: None, with: fn(x) { x + 1 })\n" - " // -> None\n" - " ```\n" -). --spec map(option(GS), fun((GS) -> GU)) -> option(GU). -map(Option, Fun) -> - case Option of - {some, X} -> - {some, Fun(X)}; - - none -> - none - end. - --file("src/gleam/option.gleam", 230). -?DOC( - " Merges a nested `Option` into a single layer.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flatten(Some(Some(1)))\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(Some(None))\n" - " // -> None\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(None)\n" - " // -> None\n" - " ```\n" -). --spec flatten(option(option(GW))) -> option(GW). -flatten(Option) -> - case Option of - {some, X} -> - X; - - none -> - none - end. - --file("src/gleam/option.gleam", 269). -?DOC( - " Updates a value held within the `Some` of an `Option` by calling a given function\n" - " on it, where the given function also returns an `Option`. The two options are\n" - " then merged together into one `Option`.\n" - "\n" - " If the `Option` is a `None` rather than `Some` the function is not called and the\n" - " option stays the same.\n" - "\n" - " This function is the equivalent of calling `map` followed by `flatten`, and\n" - " it is useful for chaining together multiple functions that return `Option`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " then(Some(1), fn(x) { Some(x + 1) })\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " then(Some(1), fn(x) { Some(#(\"a\", x)) })\n" - " // -> Some(#(\"a\", 1))\n" - " ```\n" - "\n" - " ```gleam\n" - " then(Some(1), fn(_) { None })\n" - " // -> None\n" - " ```\n" - "\n" - " ```gleam\n" - " then(None, fn(x) { Some(x + 1) })\n" - " // -> None\n" - " ```\n" -). --spec then(option(HA), fun((HA) -> option(HC))) -> option(HC). -then(Option, Fun) -> - case Option of - {some, X} -> - Fun(X); - - none -> - none - end. - --file("src/gleam/option.gleam", 300). -?DOC( - " Returns the first value if it is `Some`, otherwise returns the second value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " or(Some(1), Some(2))\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Some(1), None)\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(None, Some(2))\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(None, None)\n" - " // -> None\n" - " ```\n" -). --spec 'or'(option(HF), option(HF)) -> option(HF). -'or'(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second - end. - --file("src/gleam/option.gleam", 331). -?DOC( - " Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_or(Some(1), fn() { Some(2) })\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Some(1), fn() { None })\n" - " // -> Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(None, fn() { Some(2) })\n" - " // -> Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(None, fn() { None })\n" - " // -> None\n" - " ```\n" -). --spec lazy_or(option(HJ), fun(() -> option(HJ))) -> option(HJ). -lazy_or(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second() - end. - --file("src/gleam/option.gleam", 352). --spec values_loop(list(option(HR)), list(HR)) -> list(HR). -values_loop(List, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [none | Rest] -> - values_loop(Rest, Acc); - - [{some, First} | Rest@1] -> - values_loop(Rest@1, [First | Acc]) - end. - --file("src/gleam/option.gleam", 348). -?DOC( - " Given a list of `Option`s,\n" - " returns only the values inside `Some`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " values([Some(1), None, Some(3)])\n" - " // -> [1, 3]\n" - " ```\n" -). --spec values(list(option(HN))) -> list(HN). -values(Options) -> - values_loop(Options, []). diff --git a/build/packages/gleam_stdlib/src/gleam@order.erl b/build/packages/gleam_stdlib/src/gleam@order.erl deleted file mode 100644 index ec2bb84..0000000 --- a/build/packages/gleam_stdlib/src/gleam@order.erl +++ /dev/null @@ -1,200 +0,0 @@ --module(gleam@order). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/order.gleam"). --export([negate/1, to_int/1, compare/2, reverse/1, break_tie/2, lazy_break_tie/2]). --export_type([order/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type order() :: lt | eq | gt. - --file("src/gleam/order.gleam", 35). -?DOC( - " Inverts an order, so less-than becomes greater-than and greater-than\n" - " becomes less-than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " negate(Lt)\n" - " // -> Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " negate(Eq)\n" - " // -> Eq\n" - " ```\n" - "\n" - " ```gleam\n" - " negate(Gt)\n" - " // -> Lt\n" - " ```\n" -). --spec negate(order()) -> order(). -negate(Order) -> - case Order of - lt -> - gt; - - eq -> - eq; - - gt -> - lt - end. - --file("src/gleam/order.gleam", 62). -?DOC( - " Produces a numeric representation of the order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_int(Lt)\n" - " // -> -1\n" - " ```\n" - "\n" - " ```gleam\n" - " to_int(Eq)\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " to_int(Gt)\n" - " // -> 1\n" - " ```\n" -). --spec to_int(order()) -> integer(). -to_int(Order) -> - case Order of - lt -> - -1; - - eq -> - 0; - - gt -> - 1 - end. - --file("src/gleam/order.gleam", 79). -?DOC( - " Compares two `Order` values to one another, producing a new `Order`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(Eq, with: Lt)\n" - " // -> Gt\n" - " ```\n" -). --spec compare(order(), order()) -> order(). -compare(A, B) -> - case {A, B} of - {X, Y} when X =:= Y -> - eq; - - {lt, _} -> - lt; - - {eq, gt} -> - lt; - - {_, _} -> - gt - end. - --file("src/gleam/order.gleam", 100). -?DOC( - " Inverts an ordering function, so less-than becomes greater-than and greater-than\n" - " becomes less-than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - " import gleam/list\n" - "\n" - " list.sort([1, 5, 4], by: reverse(int.compare))\n" - " // -> [5, 4, 1]\n" - " ```\n" -). --spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()). -reverse(Orderer) -> - fun(A, B) -> Orderer(B, A) end. - --file("src/gleam/order.gleam", 122). -?DOC( - " Return a fallback `Order` in case the first argument is `Eq`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " break_tie(in: int.compare(1, 1), with: Lt)\n" - " // -> Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " break_tie(in: int.compare(1, 0), with: Eq)\n" - " // -> Gt\n" - " ```\n" -). --spec break_tie(order(), order()) -> order(). -break_tie(Order, Other) -> - case Order of - lt -> - Order; - - gt -> - Order; - - eq -> - Other - end. - --file("src/gleam/order.gleam", 151). -?DOC( - " Invokes a fallback function returning an `Order` in case the first argument\n" - " is `Eq`.\n" - "\n" - " This can be useful when the fallback comparison might be expensive and it\n" - " needs to be delayed until strictly necessary.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt })\n" - " // -> Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq })\n" - " // -> Gt\n" - " ```\n" -). --spec lazy_break_tie(order(), fun(() -> order())) -> order(). -lazy_break_tie(Order, Comparison) -> - case Order of - lt -> - Order; - - gt -> - Order; - - eq -> - Comparison() - end. diff --git a/build/packages/gleam_stdlib/src/gleam@pair.erl b/build/packages/gleam_stdlib/src/gleam@pair.erl deleted file mode 100644 index cb18264..0000000 --- a/build/packages/gleam_stdlib/src/gleam@pair.erl +++ /dev/null @@ -1,110 +0,0 @@ --module(gleam@pair). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/pair.gleam"). --export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/pair.gleam", 10). -?DOC( - " Returns the first element in a pair.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " first(#(1, 2))\n" - " // -> 1\n" - " ```\n" -). --spec first({CLF, any()}) -> CLF. -first(Pair) -> - {A, _} = Pair, - A. - --file("src/gleam/pair.gleam", 24). -?DOC( - " Returns the second element in a pair.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " second(#(1, 2))\n" - " // -> 2\n" - " ```\n" -). --spec second({any(), CLI}) -> CLI. -second(Pair) -> - {_, A} = Pair, - A. - --file("src/gleam/pair.gleam", 38). -?DOC( - " Returns a new pair with the elements swapped.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " swap(#(1, 2))\n" - " // -> #(2, 1)\n" - " ```\n" -). --spec swap({CLJ, CLK}) -> {CLK, CLJ}. -swap(Pair) -> - {A, B} = Pair, - {B, A}. - --file("src/gleam/pair.gleam", 53). -?DOC( - " Returns a new pair with the first element having had `with` applied to\n" - " it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " #(1, 2) |> map_first(fn(n) { n * 2 })\n" - " // -> #(2, 2)\n" - " ```\n" -). --spec map_first({CLL, CLM}, fun((CLL) -> CLN)) -> {CLN, CLM}. -map_first(Pair, Fun) -> - {A, B} = Pair, - {Fun(A), B}. - --file("src/gleam/pair.gleam", 68). -?DOC( - " Returns a new pair with the second element having had `with` applied to\n" - " it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " #(1, 2) |> map_second(fn(n) { n * 2 })\n" - " // -> #(1, 4)\n" - " ```\n" -). --spec map_second({CLO, CLP}, fun((CLP) -> CLQ)) -> {CLO, CLQ}. -map_second(Pair, Fun) -> - {A, B} = Pair, - {A, Fun(B)}. - --file("src/gleam/pair.gleam", 83). -?DOC( - " Returns a new pair with the given elements. This can also be done using the dedicated\n" - " syntax instead: `new(1, 2) == #(1, 2)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new(1, 2)\n" - " // -> #(1, 2)\n" - " ```\n" -). --spec new(CLR, CLS) -> {CLR, CLS}. -new(First, Second) -> - {First, Second}. diff --git a/build/packages/gleam_stdlib/src/gleam@result.erl b/build/packages/gleam_stdlib/src/gleam@result.erl deleted file mode 100644 index 9d89ff7..0000000 --- a/build/packages/gleam_stdlib/src/gleam@result.erl +++ /dev/null @@ -1,550 +0,0 @@ --module(gleam@result). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/result.gleam"). --export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, then/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, unwrap_both/1, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Result represents the result of something that may succeed or not.\n" - " `Ok` means it was successful, `Error` means it was not successful.\n" -). - --file("src/gleam/result.gleam", 20). -?DOC( - " Checks whether the result is an `Ok` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_ok(Ok(1))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_ok(Error(Nil))\n" - " // -> False\n" - " ```\n" -). --spec is_ok({ok, any()} | {error, any()}) -> boolean(). -is_ok(Result) -> - case Result of - {error, _} -> - false; - - {ok, _} -> - true - end. - --file("src/gleam/result.gleam", 41). -?DOC( - " Checks whether the result is an `Error` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_error(Ok(1))\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_error(Error(Nil))\n" - " // -> True\n" - " ```\n" -). --spec is_error({ok, any()} | {error, any()}) -> boolean(). -is_error(Result) -> - case Result of - {ok, _} -> - false; - - {error, _} -> - true - end. - --file("src/gleam/result.gleam", 66). -?DOC( - " Updates a value held within the `Ok` of a result by calling a given function\n" - " on it.\n" - "\n" - " If the result is an `Error` rather than `Ok` the function is not called and the\n" - " result stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map(over: Ok(1), with: fn(x) { x + 1 })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " map(over: Error(1), with: fn(x) { x + 1 })\n" - " // -> Error(1)\n" - " ```\n" -). --spec map({ok, CMC} | {error, CMD}, fun((CMC) -> CMG)) -> {ok, CMG} | - {error, CMD}. -map(Result, Fun) -> - case Result of - {ok, X} -> - {ok, Fun(X)}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 91). -?DOC( - " Updates a value held within the `Error` of a result by calling a given function\n" - " on it.\n" - "\n" - " If the result is `Ok` rather than `Error` the function is not called and the\n" - " result stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " map_error(over: Error(1), with: fn(x) { x + 1 })\n" - " // -> Error(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " map_error(over: Ok(1), with: fn(x) { x + 1 })\n" - " // -> Ok(1)\n" - " ```\n" -). --spec map_error({ok, CMJ} | {error, CMK}, fun((CMK) -> CMN)) -> {ok, CMJ} | - {error, CMN}. -map_error(Result, Fun) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, Error} -> - {error, Fun(Error)} - end. - --file("src/gleam/result.gleam", 120). -?DOC( - " Merges a nested `Result` into a single layer.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " flatten(Ok(Ok(1)))\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(Ok(Error(\"\")))\n" - " // -> Error(\"\")\n" - " ```\n" - "\n" - " ```gleam\n" - " flatten(Error(Nil))\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec flatten({ok, {ok, CMQ} | {error, CMR}} | {error, CMR}) -> {ok, CMQ} | - {error, CMR}. -flatten(Result) -> - case Result of - {ok, X} -> - X; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 158). -?DOC( - " \"Updates\" an `Ok` result by passing its value to a function that yields a result,\n" - " and returning the yielded result. (This may \"replace\" the `Ok` with an `Error`.)\n" - "\n" - " If the input is an `Error` rather than an `Ok`, the function is not called and\n" - " the original `Error` is returned.\n" - "\n" - " This function is the equivalent of calling `map` followed by `flatten`, and\n" - " it is useful for chaining together multiple functions that may fail.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " try(Ok(1), fn(x) { Ok(x + 1) })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " try(Ok(1), fn(x) { Ok(#(\"a\", x)) })\n" - " // -> Ok(#(\"a\", 1))\n" - " ```\n" - "\n" - " ```gleam\n" - " try(Ok(1), fn(_) { Error(\"Oh no\") })\n" - " // -> Error(\"Oh no\")\n" - " ```\n" - "\n" - " ```gleam\n" - " try(Error(Nil), fn(x) { Ok(x + 1) })\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec 'try'({ok, CMY} | {error, CMZ}, fun((CMY) -> {ok, CNC} | {error, CMZ})) -> {ok, - CNC} | - {error, CMZ}. -'try'(Result, Fun) -> - case Result of - {ok, X} -> - Fun(X); - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 169). --spec then({ok, CNH} | {error, CNI}, fun((CNH) -> {ok, CNL} | {error, CNI})) -> {ok, - CNL} | - {error, CNI}. -then(Result, Fun) -> - 'try'(Result, Fun). - --file("src/gleam/result.gleam", 191). -?DOC( - " Extracts the `Ok` value from a result, returning a default value if the result\n" - " is an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap(Ok(1), 0)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap(Error(\"\"), 0)\n" - " // -> 0\n" - " ```\n" -). --spec unwrap({ok, CNQ} | {error, any()}, CNQ) -> CNQ. -unwrap(Result, Default) -> - case Result of - {ok, V} -> - V; - - {error, _} -> - Default - end. - --file("src/gleam/result.gleam", 213). -?DOC( - " Extracts the `Ok` value from a result, evaluating the default function if the result\n" - " is an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_unwrap(Ok(1), fn() { 0 })\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_unwrap(Error(\"\"), fn() { 0 })\n" - " // -> 0\n" - " ```\n" -). --spec lazy_unwrap({ok, CNU} | {error, any()}, fun(() -> CNU)) -> CNU. -lazy_unwrap(Result, Default) -> - case Result of - {ok, V} -> - V; - - {error, _} -> - Default() - end. - --file("src/gleam/result.gleam", 235). -?DOC( - " Extracts the `Error` value from a result, returning a default value if the result\n" - " is an `Ok`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap_error(Error(1), 0)\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap_error(Ok(\"\"), 0)\n" - " // -> 0\n" - " ```\n" -). --spec unwrap_error({ok, any()} | {error, CNZ}, CNZ) -> CNZ. -unwrap_error(Result, Default) -> - case Result of - {ok, _} -> - Default; - - {error, E} -> - E - end. - --file("src/gleam/result.gleam", 243). --spec unwrap_both({ok, COC} | {error, COC}) -> COC. -unwrap_both(Result) -> - case Result of - {ok, A} -> - A; - - {error, A@1} -> - A@1 - end. - --file("src/gleam/result.gleam", 274). -?DOC( - " Returns the first value if it is `Ok`, otherwise returns the second value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " or(Ok(1), Ok(2))\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Ok(1), Error(\"Error 2\"))\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Error(\"Error 1\"), Ok(2))\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " or(Error(\"Error 1\"), Error(\"Error 2\"))\n" - " // -> Error(\"Error 2\")\n" - " ```\n" -). --spec 'or'({ok, COF} | {error, COG}, {ok, COF} | {error, COG}) -> {ok, COF} | - {error, COG}. -'or'(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second - end. - --file("src/gleam/result.gleam", 307). -?DOC( - " Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value.\n" - "\n" - " If you need access to the initial error value, use `result.try_recover`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lazy_or(Ok(1), fn() { Ok(2) })\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Ok(1), fn() { Error(\"Error 2\") })\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Error(\"Error 1\"), fn() { Ok(2) })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " lazy_or(Error(\"Error 1\"), fn() { Error(\"Error 2\") })\n" - " // -> Error(\"Error 2\")\n" - " ```\n" -). --spec lazy_or({ok, CON} | {error, COO}, fun(() -> {ok, CON} | {error, COO})) -> {ok, - CON} | - {error, COO}. -lazy_or(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second() - end. - --file("src/gleam/result.gleam", 333). -?DOC( - " Combines a list of results into a single result.\n" - " If all elements in the list are `Ok` then returns an `Ok` holding the list of values.\n" - " If any element is `Error` then returns the first error.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " all([Ok(1), Ok(2)])\n" - " // -> Ok([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " all([Ok(1), Error(\"e\")])\n" - " // -> Error(\"e\")\n" - " ```\n" -). --spec all(list({ok, COV} | {error, COW})) -> {ok, list(COV)} | {error, COW}. -all(Results) -> - gleam@list:try_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 353). --spec partition_loop(list({ok, CPK} | {error, CPL}), list(CPK), list(CPL)) -> {list(CPK), - list(CPL)}. -partition_loop(Results, Oks, Errors) -> - case Results of - [] -> - {Oks, Errors}; - - [{ok, A} | Rest] -> - partition_loop(Rest, [A | Oks], Errors); - - [{error, E} | Rest@1] -> - partition_loop(Rest@1, Oks, [E | Errors]) - end. - --file("src/gleam/result.gleam", 349). -?DOC( - " Given a list of results, returns a pair where the first element is a list\n" - " of all the values inside `Ok` and the second element is a list with all the\n" - " values inside `Error`. The values in both lists appear in reverse order with\n" - " respect to their position in the original list of results.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " partition([Ok(1), Error(\"a\"), Error(\"b\"), Ok(2)])\n" - " // -> #([2, 1], [\"b\", \"a\"])\n" - " ```\n" -). --spec partition(list({ok, CPD} | {error, CPE})) -> {list(CPD), list(CPE)}. -partition(Results) -> - partition_loop(Results, [], []). - --file("src/gleam/result.gleam", 375). -?DOC( - " Replace the value within a result\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " replace(Ok(1), Nil)\n" - " // -> Ok(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " replace(Error(1), Nil)\n" - " // -> Error(1)\n" - " ```\n" -). --spec replace({ok, any()} | {error, CPT}, CPW) -> {ok, CPW} | {error, CPT}. -replace(Result, Value) -> - case Result of - {ok, _} -> - {ok, Value}; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 396). -?DOC( - " Replace the error within a result\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " replace_error(Error(1), Nil)\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " replace_error(Ok(1), Nil)\n" - " // -> Ok(1)\n" - " ```\n" -). --spec replace_error({ok, CPZ} | {error, any()}, CQD) -> {ok, CPZ} | {error, CQD}. -replace_error(Result, Error) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, _} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 412). -?DOC( - " Given a list of results, returns only the values inside `Ok`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " values([Ok(1), Error(\"a\"), Ok(3)])\n" - " // -> [1, 3]\n" - " ```\n" -). --spec values(list({ok, CQG} | {error, any()})) -> list(CQG). -values(Results) -> - gleam@list:filter_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 445). -?DOC( - " Updates a value held within the `Error` of a result by calling a given function\n" - " on it, where the given function also returns a result. The two results are\n" - " then merged together into one result.\n" - "\n" - " If the result is an `Ok` rather than `Error` the function is not called and the\n" - " result stays the same.\n" - "\n" - " This function is useful for chaining together computations that may fail\n" - " and trying to recover from possible errors.\n" - "\n" - " If you do not need access to the initial error value, use `result.lazy_or`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " Ok(1) |> try_recover(with: fn(_) { Error(\"failed to recover\") })\n" - " // -> Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " Error(1) |> try_recover(with: fn(error) { Ok(error + 1) })\n" - " // -> Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " Error(1) |> try_recover(with: fn(error) { Error(\"failed to recover\") })\n" - " // -> Error(\"failed to recover\")\n" - " ```\n" -). --spec try_recover( - {ok, CQM} | {error, CQN}, - fun((CQN) -> {ok, CQM} | {error, CQQ}) -) -> {ok, CQM} | {error, CQQ}. -try_recover(Result, Fun) -> - case Result of - {ok, Value} -> - {ok, Value}; - - {error, Error} -> - Fun(Error) - end. diff --git a/build/packages/gleam_stdlib/src/gleam@set.erl b/build/packages/gleam_stdlib/src/gleam@set.erl deleted file mode 100644 index bb3c417..0000000 --- a/build/packages/gleam_stdlib/src/gleam@set.erl +++ /dev/null @@ -1,429 +0,0 @@ --module(gleam@set). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/set.gleam"). --export([new/0, size/1, is_empty/1, contains/2, delete/2, to_list/1, fold/3, filter/2, drop/2, take/2, intersection/2, difference/2, is_subset/2, is_disjoint/2, each/2, insert/2, from_list/1, map/2, union/2, symmetric_difference/2]). --export_type([set/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --opaque set(CVL) :: {set, gleam@dict:dict(CVL, list(nil))}. - --file("src/gleam/set.gleam", 32). -?DOC(" Creates a new empty set.\n"). --spec new() -> set(any()). -new() -> - {set, maps:new()}. - --file("src/gleam/set.gleam", 50). -?DOC( - " Gets the number of members in a set.\n" - "\n" - " This function runs in constant time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(1)\n" - " |> insert(2)\n" - " |> size\n" - " // -> 2\n" - " ```\n" -). --spec size(set(any())) -> integer(). -size(Set) -> - maps:size(erlang:element(2, Set)). - --file("src/gleam/set.gleam", 68). -?DOC( - " Determines whether or not the set is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> is_empty\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new() |> insert(1) |> is_empty\n" - " // -> False\n" - " ```\n" -). --spec is_empty(set(any())) -> boolean(). -is_empty(Set) -> - Set =:= new(). - --file("src/gleam/set.gleam", 110). -?DOC( - " Checks whether a set contains a given member.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(2)\n" - " |> contains(2)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(2)\n" - " |> contains(1)\n" - " // -> False\n" - " ```\n" -). --spec contains(set(CVW), CVW) -> boolean(). -contains(Set, Member) -> - _pipe = erlang:element(2, Set), - _pipe@1 = gleam_stdlib:map_get(_pipe, Member), - gleam@result:is_ok(_pipe@1). - --file("src/gleam/set.gleam", 131). -?DOC( - " Removes a member from a set. If the set does not contain the member then\n" - " the set is returned unchanged.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(2)\n" - " |> delete(2)\n" - " |> contains(1)\n" - " // -> False\n" - " ```\n" -). --spec delete(set(CVY), CVY) -> set(CVY). -delete(Set, Member) -> - {set, gleam@dict:delete(erlang:element(2, Set), Member)}. - --file("src/gleam/set.gleam", 149). -?DOC( - " Converts the set into a list of the contained members.\n" - "\n" - " The list has no specific ordering, any unintentional ordering may change in\n" - " future versions of Gleam or Erlang.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new() |> insert(2) |> to_list\n" - " // -> [2]\n" - " ```\n" -). --spec to_list(set(CWB)) -> list(CWB). -to_list(Set) -> - maps:keys(erlang:element(2, Set)). - --file("src/gleam/set.gleam", 190). -?DOC( - " Combines all entries into a single value by calling a given function on each\n" - " one.\n" - "\n" - " Sets are not ordered so the values are not returned in any specific order.\n" - " Do not write code that relies on the order entries are used by this\n" - " function as it may change in later versions of Gleam or Erlang.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 3, 9])\n" - " |> fold(0, fn(accumulator, member) { accumulator + member })\n" - " // -> 13\n" - " ```\n" -). --spec fold(set(CWH), CWJ, fun((CWJ, CWH) -> CWJ)) -> CWJ. -fold(Set, Initial, Reducer) -> - gleam@dict:fold( - erlang:element(2, Set), - Initial, - fun(A, K, _) -> Reducer(A, K) end - ). - --file("src/gleam/set.gleam", 214). -?DOC( - " Creates a new set from an existing set, minus any members that a given\n" - " function returns `False` for.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " from_list([1, 4, 6, 3, 675, 44, 67])\n" - " |> filter(keeping: int.is_even)\n" - " |> to_list\n" - " // -> [4, 6, 44]\n" - " ```\n" -). --spec filter(set(CWK), fun((CWK) -> boolean())) -> set(CWK). -filter(Set, Predicate) -> - {set, - gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}. - --file("src/gleam/set.gleam", 249). -?DOC( - " Creates a new set from a given set with all the same entries except any\n" - " entry found on the given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 2, 3, 4])\n" - " |> drop([1, 3])\n" - " |> to_list\n" - " // -> [2, 4]\n" - " ```\n" -). --spec drop(set(CWR), list(CWR)) -> set(CWR). -drop(Set, Disallowed) -> - gleam@list:fold(Disallowed, Set, fun delete/2). - --file("src/gleam/set.gleam", 267). -?DOC( - " Creates a new set from a given set, only including any members which are in\n" - " a given list.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 2, 3])\n" - " |> take([1, 3, 5])\n" - " |> to_list\n" - " // -> [1, 3]\n" - " ```\n" -). --spec take(set(CWV), list(CWV)) -> set(CWV). -take(Set, Desired) -> - {set, gleam@dict:take(erlang:element(2, Set), Desired)}. - --file("src/gleam/set.gleam", 287). --spec order(set(CXD), set(CXD)) -> {set(CXD), set(CXD)}. -order(First, Second) -> - case maps:size(erlang:element(2, First)) > maps:size( - erlang:element(2, Second) - ) of - true -> - {First, Second}; - - false -> - {Second, First} - end. - --file("src/gleam/set.gleam", 305). -?DOC( - " Creates a new set that contains members that are present in both given sets.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " intersection(from_list([1, 2]), from_list([2, 3])) |> to_list\n" - " // -> [2]\n" - " ```\n" -). --spec intersection(set(CXI), set(CXI)) -> set(CXI). -intersection(First, Second) -> - {Larger, Smaller} = order(First, Second), - take(Larger, to_list(Smaller)). - --file("src/gleam/set.gleam", 323). -?DOC( - " Creates a new set that contains members that are present in the first set\n" - " but not the second.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list\n" - " // -> [1]\n" - " ```\n" -). --spec difference(set(CXM), set(CXM)) -> set(CXM). -difference(First, Second) -> - drop(First, to_list(Second)). - --file("src/gleam/set.gleam", 344). -?DOC( - " Determines if a set is fully contained by another.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_subset(from_list([1]), from_list([1, 2]))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_subset(from_list([1, 2, 3]), from_list([3, 4, 5]))\n" - " // -> False\n" - " ```\n" -). --spec is_subset(set(CXQ), set(CXQ)) -> boolean(). -is_subset(First, Second) -> - intersection(First, Second) =:= First. - --file("src/gleam/set.gleam", 362). -?DOC( - " Determines if two sets contain no common members\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6]))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5]))\n" - " // -> False\n" - " ```\n" -). --spec is_disjoint(set(CXT), set(CXT)) -> boolean(). -is_disjoint(First, Second) -> - intersection(First, Second) =:= new(). - --file("src/gleam/set.gleam", 402). -?DOC( - " Calls a function for each member in a set, discarding the return\n" - " value.\n" - "\n" - " Useful for producing a side effect for every item of a set.\n" - "\n" - " ```gleam\n" - " let set = from_list([\"apple\", \"banana\", \"cherry\"])\n" - "\n" - " each(set, io.println)\n" - " // -> Nil\n" - " // apple\n" - " // banana\n" - " // cherry\n" - " ```\n" - "\n" - " The order of elements in the iteration is an implementation detail that\n" - " should not be relied upon.\n" -). --spec each(set(CYA), fun((CYA) -> any())) -> nil. -each(Set, Fun) -> - fold( - Set, - nil, - fun(Nil, Member) -> - Fun(Member), - Nil - end - ). - --file("src/gleam/set.gleam", 86). -?DOC( - " Inserts an member into the set.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " new()\n" - " |> insert(1)\n" - " |> insert(2)\n" - " |> size\n" - " // -> 2\n" - " ```\n" -). --spec insert(set(CVT), CVT) -> set(CVT). -insert(Set, Member) -> - {set, gleam@dict:insert(erlang:element(2, Set), Member, [])}. - --file("src/gleam/set.gleam", 167). -?DOC( - " Creates a new set of the members in a given list.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - " import gleam/list\n" - "\n" - " [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort(by: int.compare)\n" - " // -> [1, 2, 3, 4]\n" - " ```\n" -). --spec from_list(list(CWE)) -> set(CWE). -from_list(Members) -> - Dict = gleam@list:fold( - Members, - maps:new(), - fun(M, K) -> gleam@dict:insert(M, K, []) end - ), - {set, Dict}. - --file("src/gleam/set.gleam", 232). -?DOC( - " Creates a new set from a given set with the result of applying the given\n" - " function to each member.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_list([1, 2, 3, 4])\n" - " |> map(with: fn(x) { x * 2 })\n" - " |> to_list\n" - " // -> [2, 4, 6, 8]\n" - " ```\n" -). --spec map(set(CWN), fun((CWN) -> CWP)) -> set(CWP). -map(Set, Fun) -> - fold(Set, new(), fun(Acc, Member) -> insert(Acc, Fun(Member)) end). - --file("src/gleam/set.gleam", 282). -?DOC( - " Creates a new set that contains all members of both given sets.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " union(from_list([1, 2]), from_list([2, 3])) |> to_list\n" - " // -> [1, 2, 3]\n" - " ```\n" -). --spec union(set(CWZ), set(CWZ)) -> set(CWZ). -union(First, Second) -> - {Larger, Smaller} = order(First, Second), - fold(Smaller, Larger, fun insert/2). - --file("src/gleam/set.gleam", 374). -?DOC( - " Creates a new set that contains members that are present in either set, but\n" - " not both.\n" - "\n" - " ```gleam\n" - " symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) |> to_list\n" - " // -> [1, 2, 4]\n" - " ```\n" -). --spec symmetric_difference(set(CXW), set(CXW)) -> set(CXW). -symmetric_difference(First, Second) -> - difference(union(First, Second), intersection(First, Second)). diff --git a/build/packages/gleam_stdlib/src/gleam@string.erl b/build/packages/gleam_stdlib/src/gleam@string.erl deleted file mode 100644 index 63006b8..0000000 --- a/build/packages/gleam_stdlib/src/gleam@string.erl +++ /dev/null @@ -1,1012 +0,0 @@ --module(gleam@string). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/string.gleam"). --export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, slice/3, crop/2, drop_end/2, contains/2, starts_with/2, ends_with/2, split_once/2, append/2, concat/1, repeat/2, join/2, pad_start/3, pad_end/3, trim_start/1, trim_end/1, trim/1, pop_grapheme/1, to_graphemes/1, split/2, to_utf_codepoints/1, from_utf_codepoints/1, utf_codepoint/1, utf_codepoint_to_int/1, to_option/1, first/1, last/1, capitalise/1, inspect/1, byte_size/1, drop_start/2]). --export_type([direction/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Strings in Gleam are UTF-8 binaries. They can be written in your code as\n" - " text surrounded by `\"double quotes\"`.\n" -). - --type direction() :: leading | trailing. - --file("src/gleam/string.gleam", 23). -?DOC( - " Determines if a `String` is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_empty(\"\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_empty(\"the world\")\n" - " // -> False\n" - " ```\n" -). --spec is_empty(binary()) -> boolean(). -is_empty(Str) -> - Str =:= <<""/utf8>>. - --file("src/gleam/string.gleam", 51). -?DOC( - " Gets the number of grapheme clusters in a given `String`.\n" - "\n" - " This function has to iterate across the whole string to count the number of\n" - " graphemes, so it runs in linear time. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " length(\"Gleam\")\n" - " // -> 5\n" - " ```\n" - "\n" - " ```gleam\n" - " length(\"ß↑e̊\")\n" - " // -> 3\n" - " ```\n" - "\n" - " ```gleam\n" - " length(\"\")\n" - " // -> 0\n" - " ```\n" -). --spec length(binary()) -> integer(). -length(String) -> - string:length(String). - --file("src/gleam/string.gleam", 65). -?DOC( - " Reverses a `String`.\n" - "\n" - " This function has to iterate across the whole `String` so it runs in linear\n" - " time. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " reverse(\"stressed\")\n" - " // -> \"desserts\"\n" - " ```\n" -). --spec reverse(binary()) -> binary(). -reverse(String) -> - _pipe = String, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = string:reverse(_pipe@1), - unicode:characters_to_binary(_pipe@2). - --file("src/gleam/string.gleam", 86). -?DOC( - " Creates a new `String` by replacing all occurrences of a given substring.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " replace(\"www.example.com\", each: \".\", with: \"-\")\n" - " // -> \"www-example-com\"\n" - " ```\n" - "\n" - " ```gleam\n" - " replace(\"a,b,c,d,e\", each: \",\", with: \"/\")\n" - " // -> \"a/b/c/d/e\"\n" - " ```\n" -). --spec replace(binary(), binary(), binary()) -> binary(). -replace(String, Pattern, Substitute) -> - _pipe = String, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = gleam_stdlib:string_replace(_pipe@1, Pattern, Substitute), - unicode:characters_to_binary(_pipe@2). - --file("src/gleam/string.gleam", 111). -?DOC( - " Creates a new `String` with all the graphemes in the input `String` converted to\n" - " lowercase.\n" - "\n" - " Useful for case-insensitive comparisons.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " lowercase(\"X-FILES\")\n" - " // -> \"x-files\"\n" - " ```\n" -). --spec lowercase(binary()) -> binary(). -lowercase(String) -> - string:lowercase(String). - --file("src/gleam/string.gleam", 127). -?DOC( - " Creates a new `String` with all the graphemes in the input `String` converted to\n" - " uppercase.\n" - "\n" - " Useful for case-insensitive comparisons and VIRTUAL YELLING.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " uppercase(\"skinner\")\n" - " // -> \"SKINNER\"\n" - " ```\n" -). --spec uppercase(binary()) -> binary(). -uppercase(String) -> - string:uppercase(String). - --file("src/gleam/string.gleam", 145). -?DOC( - " Compares two `String`s to see which is \"larger\" by comparing their graphemes.\n" - "\n" - " This does not compare the size or length of the given `String`s.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " compare(\"Anthony\", \"Anthony\")\n" - " // -> order.Eq\n" - " ```\n" - "\n" - " ```gleam\n" - " compare(\"A\", \"B\")\n" - " // -> order.Lt\n" - " ```\n" -). --spec compare(binary(), binary()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - _ -> - case gleam_stdlib:less_than(A, B) of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/string.gleam", 194). -?DOC( - " Takes a substring given a start grapheme index and a length. Negative indexes\n" - " are taken starting from the *end* of the list.\n" - "\n" - " This function runs in linear time with the size of the index and the\n" - " length. Negative indexes are linear with the size of the input string in\n" - " addition to the other costs.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: 1, length: 2)\n" - " // -> \"le\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: 1, length: 10)\n" - " // -> \"leam\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: 10, length: 3)\n" - " // -> \"\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: -2, length: 2)\n" - " // -> \"am\"\n" - " ```\n" - "\n" - " ```gleam\n" - " slice(from: \"gleam\", at_index: -12, length: 2)\n" - " // -> \"\"\n" - " ```\n" -). --spec slice(binary(), integer(), integer()) -> binary(). -slice(String, Idx, Len) -> - case Len =< 0 of - true -> - <<""/utf8>>; - - false -> - case Idx < 0 of - true -> - Translated_idx = string:length(String) + Idx, - case Translated_idx < 0 of - true -> - <<""/utf8>>; - - false -> - gleam_stdlib:slice(String, Translated_idx, Len) - end; - - false -> - gleam_stdlib:slice(String, Idx, Len) - end - end. - --file("src/gleam/string.gleam", 232). -?DOC( - " Drops contents of the first `String` that occur before the second `String`.\n" - " If the `from` string does not contain the `before` string, `from` is\n" - " returned unchanged.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " crop(from: \"The Lone Gunmen\", before: \"Lone\")\n" - " // -> \"Lone Gunmen\"\n" - " ```\n" -). --spec crop(binary(), binary()) -> binary(). -crop(String, Substring) -> - gleam_stdlib:crop_string(String, Substring). - --file("src/gleam/string.gleam", 268). -?DOC( - " Drops *n* graphemes from the end of a `String`.\n" - "\n" - " This function traverses the full string, so it runs in linear time with the\n" - " size of the string. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop_end(from: \"Cigarette Smoking Man\", up_to: 2)\n" - " // -> \"Cigarette Smoking M\"\n" - " ```\n" -). --spec drop_end(binary(), integer()) -> binary(). -drop_end(String, Num_graphemes) -> - case Num_graphemes =< 0 of - true -> - String; - - false -> - slice(String, 0, string:length(String) - Num_graphemes) - end. - --file("src/gleam/string.gleam", 296). -?DOC( - " Checks if the first `String` contains the second.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " contains(does: \"theory\", contain: \"ory\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " contains(does: \"theory\", contain: \"the\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " contains(does: \"theory\", contain: \"THE\")\n" - " // -> False\n" - " ```\n" -). --spec contains(binary(), binary()) -> boolean(). -contains(Haystack, Needle) -> - gleam_stdlib:contains_string(Haystack, Needle). - --file("src/gleam/string.gleam", 309). -?DOC( - " Checks whether the first `String` starts with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " starts_with(\"theory\", \"ory\")\n" - " // -> False\n" - " ```\n" -). --spec starts_with(binary(), binary()) -> boolean(). -starts_with(String, Prefix) -> - gleam_stdlib:string_starts_with(String, Prefix). - --file("src/gleam/string.gleam", 322). -?DOC( - " Checks whether the first `String` ends with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " ends_with(\"theory\", \"ory\")\n" - " // -> True\n" - " ```\n" -). --spec ends_with(binary(), binary()) -> boolean(). -ends_with(String, Suffix) -> - gleam_stdlib:string_ends_with(String, Suffix). - --file("src/gleam/string.gleam", 361). -?DOC( - " Splits a `String` a single time on the given substring.\n" - "\n" - " Returns an `Error` if substring not present.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split_once(\"home/gleam/desktop/\", on: \"/\")\n" - " // -> Ok(#(\"home\", \"gleam/desktop/\"))\n" - " ```\n" - "\n" - " ```gleam\n" - " split_once(\"home/gleam/desktop/\", on: \"?\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec split_once(binary(), binary()) -> {ok, {binary(), binary()}} | - {error, nil}. -split_once(String, Substring) -> - case string:split(String, Substring) of - [First, Rest] -> - {ok, {First, Rest}}; - - _ -> - {error, nil} - end. - --file("src/gleam/string.gleam", 392). -?DOC( - " Creates a new `String` by joining two `String`s together.\n" - "\n" - " This function typically copies both `String`s and runs in linear time, but\n" - " the exact behaviour will depend on how the runtime you are using optimises\n" - " your code. Benchmark and profile your code if you need to understand its\n" - " performance better.\n" - "\n" - " If you are joining together large string and want to avoid copying any data\n" - " you may want to investigate using the [`string_tree`](../gleam/string_tree.html)\n" - " module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " append(to: \"butter\", suffix: \"fly\")\n" - " // -> \"butterfly\"\n" - " ```\n" -). --spec append(binary(), binary()) -> binary(). -append(First, Second) -> - <>. - --file("src/gleam/string.gleam", 412). --spec concat_loop(list(binary()), binary()) -> binary(). -concat_loop(Strings, Accumulator) -> - case Strings of - [String | Strings@1] -> - concat_loop(Strings@1, <>); - - [] -> - Accumulator - end. - --file("src/gleam/string.gleam", 408). -?DOC( - " Creates a new `String` by joining many `String`s together.\n" - "\n" - " This function copies all the `String`s and runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " concat([\"never\", \"the\", \"less\"])\n" - " // -> \"nevertheless\"\n" - " ```\n" -). --spec concat(list(binary())) -> binary(). -concat(Strings) -> - erlang:list_to_binary(Strings). - --file("src/gleam/string.gleam", 437). --spec repeat_loop(integer(), binary(), binary()) -> binary(). -repeat_loop(Times, Doubling_acc, Acc) -> - Acc@1 = case Times rem 2 of - 0 -> - Acc; - - _ -> - <> - end, - Times@1 = Times div 2, - case Times@1 =< 0 of - true -> - Acc@1; - - false -> - repeat_loop( - Times@1, - <>, - Acc@1 - ) - end. - --file("src/gleam/string.gleam", 430). -?DOC( - " Creates a new `String` by repeating a `String` a given number of times.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " repeat(\"ha\", times: 3)\n" - " // -> \"hahaha\"\n" - " ```\n" -). --spec repeat(binary(), integer()) -> binary(). -repeat(String, Times) -> - case Times =< 0 of - true -> - <<""/utf8>>; - - false -> - repeat_loop(Times, String, <<""/utf8>>) - end. - --file("src/gleam/string.gleam", 467). --spec join_loop(list(binary()), binary(), binary()) -> binary(). -join_loop(Strings, Separator, Accumulator) -> - case Strings of - [] -> - Accumulator; - - [String | Strings@1] -> - join_loop( - Strings@1, - Separator, - <<<>/binary, - String/binary>> - ) - end. - --file("src/gleam/string.gleam", 460). -?DOC( - " Joins many `String`s together with a given separator.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " join([\"home\",\"evan\",\"Desktop\"], with: \"/\")\n" - " // -> \"home/evan/Desktop\"\n" - " ```\n" -). --spec join(list(binary()), binary()) -> binary(). -join(Strings, Separator) -> - case Strings of - [] -> - <<""/utf8>>; - - [First | Rest] -> - join_loop(Rest, Separator, First) - end. - --file("src/gleam/string.gleam", 545). --spec padding(integer(), binary()) -> binary(). -padding(Size, Pad_string) -> - Pad_string_length = string:length(Pad_string), - Num_pads = case Pad_string_length of - 0 -> 0; - Gleam@denominator -> Size div Gleam@denominator - end, - Extra = case Pad_string_length of - 0 -> 0; - Gleam@denominator@1 -> Size rem Gleam@denominator@1 - end, - <<(repeat(Pad_string, Num_pads))/binary, - (slice(Pad_string, 0, Extra))/binary>>. - --file("src/gleam/string.gleam", 498). -?DOC( - " Pads the start of a `String` until it has a given length.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " pad_start(\"121\", to: 5, with: \".\")\n" - " // -> \"..121\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_start(\"121\", to: 3, with: \".\")\n" - " // -> \"121\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_start(\"121\", to: 2, with: \".\")\n" - " // -> \"121\"\n" - " ```\n" -). --spec pad_start(binary(), integer(), binary()) -> binary(). -pad_start(String, Desired_length, Pad_string) -> - Current_length = string:length(String), - To_pad_length = Desired_length - Current_length, - case To_pad_length =< 0 of - true -> - String; - - false -> - <<(padding(To_pad_length, Pad_string))/binary, String/binary>> - end. - --file("src/gleam/string.gleam", 531). -?DOC( - " Pads the end of a `String` until it has a given length.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " pad_end(\"123\", to: 5, with: \".\")\n" - " // -> \"123..\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_end(\"123\", to: 3, with: \".\")\n" - " // -> \"123\"\n" - " ```\n" - "\n" - " ```gleam\n" - " pad_end(\"123\", to: 2, with: \".\")\n" - " // -> \"123\"\n" - " ```\n" -). --spec pad_end(binary(), integer(), binary()) -> binary(). -pad_end(String, Desired_length, Pad_string) -> - Current_length = string:length(String), - To_pad_length = Desired_length - Current_length, - case To_pad_length =< 0 of - true -> - String; - - false -> - <> - end. - --file("src/gleam/string.gleam", 589). -?DOC( - " Removes whitespace at the start of a `String`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " trim_start(\" hats \\n\")\n" - " // -> \"hats \\n\"\n" - " ```\n" -). --spec trim_start(binary()) -> binary(). -trim_start(String) -> - string:trim(String, leading). - --file("src/gleam/string.gleam", 603). -?DOC( - " Removes whitespace at the end of a `String`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " trim_end(\" hats \\n\")\n" - " // -> \" hats\"\n" - " ```\n" -). --spec trim_end(binary()) -> binary(). -trim_end(String) -> - string:trim(String, trailing). - --file("src/gleam/string.gleam", 567). -?DOC( - " Removes whitespace on both sides of a `String`.\n" - "\n" - " Whitespace in this function is the set of nonbreakable whitespace\n" - " codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1].\n" - "\n" - " [1]: https://unicode.org/reports/tr31/\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " trim(\" hats \\n\")\n" - " // -> \"hats\"\n" - " ```\n" -). --spec trim(binary()) -> binary(). -trim(String) -> - _pipe = String, - _pipe@1 = trim_start(_pipe), - trim_end(_pipe@1). - --file("src/gleam/string.gleam", 630). -?DOC( - " Splits a non-empty `String` into its first element (head) and rest (tail).\n" - " This lets you pattern match on `String`s exactly as you would with lists.\n" - "\n" - " ## Performance\n" - "\n" - " There is a notable overhead to using this function, so you may not want to\n" - " use it in a tight loop. If you wish to efficiently parse a string you may\n" - " want to use alternatives such as the [splitter package](https://hex.pm/packages/splitter).\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " pop_grapheme(\"gleam\")\n" - " // -> Ok(#(\"g\", \"leam\"))\n" - " ```\n" - "\n" - " ```gleam\n" - " pop_grapheme(\"\")\n" - " // -> Error(Nil)\n" - " ```\n" -). --spec pop_grapheme(binary()) -> {ok, {binary(), binary()}} | {error, nil}. -pop_grapheme(String) -> - gleam_stdlib:string_pop_grapheme(String). - --file("src/gleam/string.gleam", 647). --spec to_graphemes_loop(binary(), list(binary())) -> list(binary()). -to_graphemes_loop(String, Acc) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {Grapheme, Rest}} -> - to_graphemes_loop(Rest, [Grapheme | Acc]); - - {error, _} -> - Acc - end. - --file("src/gleam/string.gleam", 641). -?DOC( - " Converts a `String` to a list of\n" - " [graphemes](https://en.wikipedia.org/wiki/Grapheme).\n" - "\n" - " ```gleam\n" - " to_graphemes(\"abc\")\n" - " // -> [\"a\", \"b\", \"c\"]\n" - " ```\n" -). --spec to_graphemes(binary()) -> list(binary()). -to_graphemes(String) -> - _pipe = String, - _pipe@1 = to_graphemes_loop(_pipe, []), - lists:reverse(_pipe@1). - --file("src/gleam/string.gleam", 333). -?DOC( - " Creates a list of `String`s by splitting a given string on a given substring.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split(\"home/gleam/desktop/\", on: \"/\")\n" - " // -> [\"home\", \"gleam\", \"desktop\", \"\"]\n" - " ```\n" -). --spec split(binary(), binary()) -> list(binary()). -split(X, Substring) -> - case Substring of - <<""/utf8>> -> - to_graphemes(X); - - _ -> - _pipe = X, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = gleam@string_tree:split(_pipe@1, Substring), - gleam@list:map(_pipe@2, fun unicode:characters_to_binary/1) - end. - --file("src/gleam/string.gleam", 694). --spec to_utf_codepoints_loop(bitstring(), list(integer())) -> list(integer()). -to_utf_codepoints_loop(Bit_array, Acc) -> - case Bit_array of - <> -> - to_utf_codepoints_loop(Rest, [First | Acc]); - - _ -> - lists:reverse(Acc) - end. - --file("src/gleam/string.gleam", 689). --spec do_to_utf_codepoints(binary()) -> list(integer()). -do_to_utf_codepoints(String) -> - to_utf_codepoints_loop(<>, []). - --file("src/gleam/string.gleam", 684). -?DOC( - " Converts a `String` to a `List` of `UtfCodepoint`.\n" - "\n" - " See and\n" - " for an\n" - " explanation on code points.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " \"a\" |> to_utf_codepoints\n" - " // -> [UtfCodepoint(97)]\n" - " ```\n" - "\n" - " ```gleam\n" - " // Semantically the same as:\n" - " // [\"🏳\", \"️\", \"‍\", \"🌈\"] or:\n" - " // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow]\n" - " \"🏳️‍🌈\" |> to_utf_codepoints\n" - " // -> [\n" - " // UtfCodepoint(127987),\n" - " // UtfCodepoint(65039),\n" - " // UtfCodepoint(8205),\n" - " // UtfCodepoint(127752),\n" - " // ]\n" - " ```\n" -). --spec to_utf_codepoints(binary()) -> list(integer()). -to_utf_codepoints(String) -> - do_to_utf_codepoints(String). - --file("src/gleam/string.gleam", 734). -?DOC( - " Converts a `List` of `UtfCodepoint`s to a `String`.\n" - "\n" - " See and\n" - " for an\n" - " explanation on code points.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(a) = utf_codepoint(97)\n" - " let assert Ok(b) = utf_codepoint(98)\n" - " let assert Ok(c) = utf_codepoint(99)\n" - " from_utf_codepoints([a, b, c])\n" - " // -> \"abc\"\n" - " ```\n" -). --spec from_utf_codepoints(list(integer())) -> binary(). -from_utf_codepoints(Utf_codepoints) -> - gleam_stdlib:utf_codepoint_list_to_string(Utf_codepoints). - --file("src/gleam/string.gleam", 740). -?DOC( - " Converts an integer to a `UtfCodepoint`.\n" - "\n" - " Returns an `Error` if the integer does not represent a valid UTF codepoint.\n" -). --spec utf_codepoint(integer()) -> {ok, integer()} | {error, nil}. -utf_codepoint(Value) -> - case Value of - I when I > 1114111 -> - {error, nil}; - - I@1 when (I@1 >= 55296) andalso (I@1 =< 57343) -> - {error, nil}; - - I@2 when I@2 < 0 -> - {error, nil}; - - I@3 -> - {ok, gleam_stdlib:identity(I@3)} - end. - --file("src/gleam/string.gleam", 761). -?DOC( - " Converts an UtfCodepoint to its ordinal code point value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert [utf_codepoint, ..] = to_utf_codepoints(\"💜\")\n" - " utf_codepoint_to_int(utf_codepoint)\n" - " // -> 128156\n" - " ```\n" -). --spec utf_codepoint_to_int(integer()) -> integer(). -utf_codepoint_to_int(Cp) -> - gleam_stdlib:identity(Cp). - --file("src/gleam/string.gleam", 778). -?DOC( - " Converts a `String` into `Option(String)` where an empty `String` becomes\n" - " `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " to_option(\"\")\n" - " // -> None\n" - " ```\n" - "\n" - " ```gleam\n" - " to_option(\"hats\")\n" - " // -> Some(\"hats\")\n" - " ```\n" -). --spec to_option(binary()) -> gleam@option:option(binary()). -to_option(String) -> - case String of - <<""/utf8>> -> - none; - - _ -> - {some, String} - end. - --file("src/gleam/string.gleam", 801). -?DOC( - " Returns the first grapheme cluster in a given `String` and wraps it in a\n" - " `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.\n" - " Otherwise, it returns `Ok(String)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " first(\"\")\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " first(\"icecream\")\n" - " // -> Ok(\"i\")\n" - " ```\n" -). --spec first(binary()) -> {ok, binary()} | {error, nil}. -first(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, _}} -> - {ok, First}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/string.gleam", 827). -?DOC( - " Returns the last grapheme cluster in a given `String` and wraps it in a\n" - " `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.\n" - " Otherwise, it returns `Ok(String)`.\n" - "\n" - " This function traverses the full string, so it runs in linear time with the\n" - " length of the string. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " last(\"\")\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " last(\"icecream\")\n" - " // -> Ok(\"m\")\n" - " ```\n" -). --spec last(binary()) -> {ok, binary()} | {error, nil}. -last(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, <<""/utf8>>}} -> - {ok, First}; - - {ok, {_, Rest}} -> - {ok, slice(Rest, -1, 1)}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/string.gleam", 845). -?DOC( - " Creates a new `String` with the first grapheme in the input `String`\n" - " converted to uppercase and the remaining graphemes to lowercase.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " capitalise(\"mamouna\")\n" - " // -> \"Mamouna\"\n" - " ```\n" -). --spec capitalise(binary()) -> binary(). -capitalise(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, Rest}} -> - append(string:uppercase(First), string:lowercase(Rest)); - - {error, _} -> - <<""/utf8>> - end. - --file("src/gleam/string.gleam", 876). -?DOC( - " Returns a `String` representation of a term in Gleam syntax.\n" - "\n" - " This may be occasionally useful for quick-and-dirty printing of values in\n" - " scripts. For error reporting and other uses prefer constructing strings by\n" - " pattern matching on the values.\n" - "\n" - " ## Limitations\n" - "\n" - " The output format of this function is not stable and could change at any\n" - " time. The output is not suitable for parsing.\n" - "\n" - " This function works using runtime reflection, so the output may not be\n" - " perfectly accurate for data structures where the runtime structure doesn't\n" - " hold enough information to determine the original syntax. For example,\n" - " tuples with an Erlang atom in the first position will be mistaken for Gleam\n" - " records.\n" - "\n" - " ## Security and safety\n" - "\n" - " There is no limit to how large the strings that this function can produce.\n" - " Be careful not to call this function with large data structures or you\n" - " could use very large amounts of memory, potentially causing runtime\n" - " problems.\n" -). --spec inspect(any()) -> binary(). -inspect(Term) -> - _pipe = Term, - _pipe@1 = gleam_stdlib:inspect(_pipe), - unicode:characters_to_binary(_pipe@1). - --file("src/gleam/string.gleam", 900). -?DOC( - " Returns the number of bytes in a `String`.\n" - "\n" - " This function runs in constant time on Erlang and in linear time on\n" - " JavaScript.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " byte_size(\"🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻\")\n" - " // -> 58\n" - " ```\n" -). --spec byte_size(binary()) -> integer(). -byte_size(String) -> - erlang:byte_size(String). - --file("src/gleam/string.gleam", 245). -?DOC( - " Drops *n* graphemes from the start of a `String`.\n" - "\n" - " This function runs in linear time with the number of graphemes to drop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " drop_start(from: \"The Lone Gunmen\", up_to: 2)\n" - " // -> \"e Lone Gunmen\"\n" - " ```\n" -). --spec drop_start(binary(), integer()) -> binary(). -drop_start(String, Num_graphemes) -> - case Num_graphemes =< 0 of - true -> - String; - - false -> - Prefix = gleam_stdlib:slice(String, 0, Num_graphemes), - Prefix_size = erlang:byte_size(Prefix), - binary:part( - String, - Prefix_size, - erlang:byte_size(String) - Prefix_size - ) - end. diff --git a/build/packages/gleam_stdlib/src/gleam@string_tree.erl b/build/packages/gleam_stdlib/src/gleam@string_tree.erl deleted file mode 100644 index 0d72b4d..0000000 --- a/build/packages/gleam_stdlib/src/gleam@string_tree.erl +++ /dev/null @@ -1,207 +0,0 @@ --module(gleam@string_tree). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/string_tree.gleam"). --export([append_tree/2, prepend_tree/2, from_strings/1, new/0, concat/1, from_string/1, prepend/2, append/2, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]). --export_type([string_tree/0, direction/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type string_tree() :: any(). - --type direction() :: all. - --file("src/gleam/string_tree.gleam", 61). -?DOC( - " Appends some `StringTree` onto the end of another.\n" - "\n" - " Runs in constant time.\n" -). --spec append_tree(string_tree(), string_tree()) -> string_tree(). -append_tree(Tree, Suffix) -> - gleam_stdlib:iodata_append(Tree, Suffix). - --file("src/gleam/string_tree.gleam", 48). -?DOC( - " Prepends some `StringTree` onto the start of another.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend_tree(string_tree(), string_tree()) -> string_tree(). -prepend_tree(Tree, Prefix) -> - gleam_stdlib:iodata_append(Prefix, Tree). - --file("src/gleam/string_tree.gleam", 69). -?DOC( - " Converts a list of strings into a `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec from_strings(list(binary())) -> string_tree(). -from_strings(Strings) -> - gleam_stdlib:identity(Strings). - --file("src/gleam/string_tree.gleam", 24). -?DOC( - " Create an empty `StringTree`. Useful as the start of a pipe chaining many\n" - " trees together.\n" -). --spec new() -> string_tree(). -new() -> - gleam_stdlib:identity([]). - --file("src/gleam/string_tree.gleam", 77). -?DOC( - " Joins a list of trees into a single tree.\n" - "\n" - " Runs in constant time.\n" -). --spec concat(list(string_tree())) -> string_tree(). -concat(Trees) -> - gleam_stdlib:identity(Trees). - --file("src/gleam/string_tree.gleam", 85). -?DOC( - " Converts a string into a `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec from_string(binary()) -> string_tree(). -from_string(String) -> - gleam_stdlib:identity(String). - --file("src/gleam/string_tree.gleam", 32). -?DOC( - " Prepends a `String` onto the start of some `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend(string_tree(), binary()) -> string_tree(). -prepend(Tree, Prefix) -> - gleam_stdlib:iodata_append(gleam_stdlib:identity(Prefix), Tree). - --file("src/gleam/string_tree.gleam", 40). -?DOC( - " Appends a `String` onto the end of some `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec append(string_tree(), binary()) -> string_tree(). -append(Tree, Second) -> - gleam_stdlib:iodata_append(Tree, gleam_stdlib:identity(Second)). - --file("src/gleam/string_tree.gleam", 94). -?DOC( - " Turns a `StringTree` into a `String`\n" - "\n" - " This function is implemented natively by the virtual machine and is highly\n" - " optimised.\n" -). --spec to_string(string_tree()) -> binary(). -to_string(Tree) -> - unicode:characters_to_binary(Tree). - --file("src/gleam/string_tree.gleam", 100). -?DOC(" Returns the size of the `StringTree` in bytes.\n"). --spec byte_size(string_tree()) -> integer(). -byte_size(Tree) -> - erlang:iolist_size(Tree). - --file("src/gleam/string_tree.gleam", 104). -?DOC(" Joins the given trees into a new tree separated with the given string.\n"). --spec join(list(string_tree()), binary()) -> string_tree(). -join(Trees, Sep) -> - _pipe = Trees, - _pipe@1 = gleam@list:intersperse(_pipe, gleam_stdlib:identity(Sep)), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/string_tree.gleam", 115). -?DOC( - " Converts a `StringTree` to a new one where the contents have been\n" - " lowercased.\n" -). --spec lowercase(string_tree()) -> string_tree(). -lowercase(Tree) -> - string:lowercase(Tree). - --file("src/gleam/string_tree.gleam", 122). -?DOC( - " Converts a `StringTree` to a new one where the contents have been\n" - " uppercased.\n" -). --spec uppercase(string_tree()) -> string_tree(). -uppercase(Tree) -> - string:uppercase(Tree). - --file("src/gleam/string_tree.gleam", 127). -?DOC(" Converts a `StringTree` to a new one with the contents reversed.\n"). --spec reverse(string_tree()) -> string_tree(). -reverse(Tree) -> - string:reverse(Tree). - --file("src/gleam/string_tree.gleam", 145). -?DOC(" Splits a `StringTree` on a given pattern into a list of trees.\n"). --spec split(string_tree(), binary()) -> list(string_tree()). -split(Tree, Pattern) -> - string:split(Tree, Pattern, all). - --file("src/gleam/string_tree.gleam", 156). -?DOC(" Replaces all instances of a pattern with a given string substitute.\n"). --spec replace(string_tree(), binary(), binary()) -> string_tree(). -replace(Tree, Pattern, Substitute) -> - gleam_stdlib:string_replace(Tree, Pattern, Substitute). - --file("src/gleam/string_tree.gleam", 182). -?DOC( - " Compares two string trees to determine if they have the same textual\n" - " content.\n" - "\n" - " Comparing two string trees using the `==` operator may return `False` even\n" - " if they have the same content as they may have been build in different ways,\n" - " so using this function is often preferred.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_strings([\"a\", \"b\"]) == from_string(\"ab\")\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_equal(from_strings([\"a\", \"b\"]), from_string(\"ab\"))\n" - " // -> True\n" - " ```\n" -). --spec is_equal(string_tree(), string_tree()) -> boolean(). -is_equal(A, B) -> - string:equal(A, B). - --file("src/gleam/string_tree.gleam", 206). -?DOC( - " Inspects a `StringTree` to determine if it is equivalent to an empty string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " from_string(\"ok\") |> is_empty\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " from_string(\"\") |> is_empty\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " from_strings([]) |> is_empty\n" - " // -> True\n" - " ```\n" -). --spec is_empty(string_tree()) -> boolean(). -is_empty(Tree) -> - string:is_empty(Tree). diff --git a/build/packages/gleam_stdlib/src/gleam@uri.erl b/build/packages/gleam_stdlib/src/gleam@uri.erl deleted file mode 100644 index 0819463..0000000 --- a/build/packages/gleam_stdlib/src/gleam@uri.erl +++ /dev/null @@ -1,1044 +0,0 @@ --module(gleam@uri). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/uri.gleam"). --export([parse_query/1, percent_encode/1, query_to_string/1, percent_decode/1, path_segments/1, to_string/1, origin/1, merge/2, parse/1]). --export_type([uri/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Utilities for working with URIs\n" - "\n" - " This module provides functions for working with URIs (for example, parsing\n" - " URIs or encoding query strings). The functions in this module are implemented\n" - " according to [RFC 3986](https://tools.ietf.org/html/rfc3986).\n" - "\n" - " Query encoding (Form encoding) is defined in the\n" - " [W3C specification](https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data).\n" -). - --type uri() :: {uri, - gleam@option:option(binary()), - gleam@option:option(binary()), - gleam@option:option(binary()), - gleam@option:option(integer()), - binary(), - gleam@option:option(binary()), - gleam@option:option(binary())}. - --file("src/gleam/uri.gleam", 289). --spec is_valid_host_within_brackets_char(integer()) -> boolean(). -is_valid_host_within_brackets_char(Char) -> - (((((48 >= Char) andalso (Char =< 57)) orelse ((65 >= Char) andalso (Char =< 90))) - orelse ((97 >= Char) andalso (Char =< 122))) - orelse (Char =:= 58)) - orelse (Char =:= 46). - --file("src/gleam/uri.gleam", 506). --spec parse_fragment(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_fragment(Rest, Pieces) -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - {some, Rest}}}. - --file("src/gleam/uri.gleam", 478). --spec parse_query_with_question_mark_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_query_with_question_mark_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"#"/utf8, Rest/binary>> when Size =:= 0 -> - parse_fragment(Rest, Pieces); - - <<"#"/utf8, Rest@1/binary>> -> - Query = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - {some, Query}, - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@1); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - {some, Original}, - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_query_with_question_mark_loop( - Original, - Rest@2, - Pieces, - Size + 1 - ) - end. - --file("src/gleam/uri.gleam", 471). --spec parse_query_with_question_mark(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_query_with_question_mark(Uri_string, Pieces) -> - parse_query_with_question_mark_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 437). --spec parse_path_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_path_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"?"/utf8, Rest/binary>> -> - Path = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Path, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest, Pieces@1); - - <<"#"/utf8, Rest@1/binary>> -> - Path@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Path@1, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@2); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Original, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_path_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 433). --spec parse_path(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_path(Uri_string, Pieces) -> - parse_path_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 388). --spec parse_port_loop(binary(), uri(), integer()) -> {ok, uri()} | {error, nil}. -parse_port_loop(Uri_string, Pieces, Port) -> - case Uri_string of - <<"0"/utf8, Rest/binary>> -> - parse_port_loop(Rest, Pieces, Port * 10); - - <<"1"/utf8, Rest@1/binary>> -> - parse_port_loop(Rest@1, Pieces, (Port * 10) + 1); - - <<"2"/utf8, Rest@2/binary>> -> - parse_port_loop(Rest@2, Pieces, (Port * 10) + 2); - - <<"3"/utf8, Rest@3/binary>> -> - parse_port_loop(Rest@3, Pieces, (Port * 10) + 3); - - <<"4"/utf8, Rest@4/binary>> -> - parse_port_loop(Rest@4, Pieces, (Port * 10) + 4); - - <<"5"/utf8, Rest@5/binary>> -> - parse_port_loop(Rest@5, Pieces, (Port * 10) + 5); - - <<"6"/utf8, Rest@6/binary>> -> - parse_port_loop(Rest@6, Pieces, (Port * 10) + 6); - - <<"7"/utf8, Rest@7/binary>> -> - parse_port_loop(Rest@7, Pieces, (Port * 10) + 7); - - <<"8"/utf8, Rest@8/binary>> -> - parse_port_loop(Rest@8, Pieces, (Port * 10) + 8); - - <<"9"/utf8, Rest@9/binary>> -> - parse_port_loop(Rest@9, Pieces, (Port * 10) + 9); - - <<"?"/utf8, Rest@10/binary>> -> - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@10, Pieces@1); - - <<"#"/utf8, Rest@11/binary>> -> - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@11, Pieces@2); - - <<"/"/utf8, _/binary>> -> - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@3); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 353). --spec parse_port(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_port(Uri_string, Pieces) -> - case Uri_string of - <<":0"/utf8, Rest/binary>> -> - parse_port_loop(Rest, Pieces, 0); - - <<":1"/utf8, Rest@1/binary>> -> - parse_port_loop(Rest@1, Pieces, 1); - - <<":2"/utf8, Rest@2/binary>> -> - parse_port_loop(Rest@2, Pieces, 2); - - <<":3"/utf8, Rest@3/binary>> -> - parse_port_loop(Rest@3, Pieces, 3); - - <<":4"/utf8, Rest@4/binary>> -> - parse_port_loop(Rest@4, Pieces, 4); - - <<":5"/utf8, Rest@5/binary>> -> - parse_port_loop(Rest@5, Pieces, 5); - - <<":6"/utf8, Rest@6/binary>> -> - parse_port_loop(Rest@6, Pieces, 6); - - <<":7"/utf8, Rest@7/binary>> -> - parse_port_loop(Rest@7, Pieces, 7); - - <<":8"/utf8, Rest@8/binary>> -> - parse_port_loop(Rest@8, Pieces, 8); - - <<":9"/utf8, Rest@9/binary>> -> - parse_port_loop(Rest@9, Pieces, 9); - - <<":"/utf8>> -> - {ok, Pieces}; - - <<""/utf8>> -> - {ok, Pieces}; - - <<"?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<":?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<"#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<":#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_path(Uri_string, Pieces); - - <<":"/utf8, Rest@12/binary>> -> - case Rest@12 of - <<"/"/utf8, _/binary>> -> - parse_path(Rest@12, Pieces); - - _ -> - {error, nil} - end; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 309). --spec parse_host_outside_of_brackets_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_host_outside_of_brackets_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Original}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<":"/utf8, _/binary>> -> - Host = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Uri_string, Pieces@1); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@1}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@2}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest, Pieces@3); - - <<"#"/utf8, Rest@1/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@3}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@4); - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_host_outside_of_brackets_loop( - Original, - Rest@2, - Pieces, - Size + 1 - ) - end. - --file("src/gleam/uri.gleam", 229). --spec parse_host_within_brackets_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_host_within_brackets_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Uri_string}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<"]"/utf8, Rest/binary>> when Size =:= 0 -> - parse_port(Rest, Pieces); - - <<"]"/utf8, Rest@1/binary>> -> - Host = binary:part(Original, 0, Size + 1), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Rest@1, Pieces@1); - - <<"/"/utf8, _/binary>> when Size =:= 0 -> - parse_path(Uri_string, Pieces); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@1}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest@2/binary>> when Size =:= 0 -> - parse_query_with_question_mark(Rest@2, Pieces); - - <<"?"/utf8, Rest@3/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@2}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@3, Pieces@3); - - <<"#"/utf8, Rest@4/binary>> when Size =:= 0 -> - parse_fragment(Rest@4, Pieces); - - <<"#"/utf8, Rest@5/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@3}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@5, Pieces@4); - - _ -> - {Char, Rest@6} = gleam_stdlib:string_pop_codeunit(Uri_string), - case is_valid_host_within_brackets_char(Char) of - true -> - parse_host_within_brackets_loop( - Original, - Rest@6, - Pieces, - Size + 1 - ); - - false -> - parse_host_outside_of_brackets_loop( - Original, - Original, - Pieces, - 0 - ) - end - end. - --file("src/gleam/uri.gleam", 222). --spec parse_host_within_brackets(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_host_within_brackets(Uri_string, Pieces) -> - parse_host_within_brackets_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 302). --spec parse_host_outside_of_brackets(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_host_outside_of_brackets(Uri_string, Pieces) -> - parse_host_outside_of_brackets_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 199). --spec parse_host(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_host(Uri_string, Pieces) -> - case Uri_string of - <<"["/utf8, _/binary>> -> - parse_host_within_brackets(Uri_string, Pieces); - - <<":"/utf8, _/binary>> -> - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Uri_string, Pieces@1); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - parse_host_outside_of_brackets(Uri_string, Pieces) - end. - --file("src/gleam/uri.gleam", 167). --spec parse_userinfo_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_userinfo_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"@"/utf8, Rest/binary>> when Size =:= 0 -> - parse_host(Rest, Pieces); - - <<"@"/utf8, Rest@1/binary>> -> - Userinfo = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - {some, Userinfo}, - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_host(Rest@1, Pieces@1); - - <<""/utf8>> -> - parse_host(Original, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - <<"?"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - <<"#"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_userinfo_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 163). --spec parse_authority_pieces(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_authority_pieces(String, Pieces) -> - parse_userinfo_loop(String, String, Pieces, 0). - --file("src/gleam/uri.gleam", 150). --spec parse_authority_with_slashes(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_authority_with_slashes(Uri_string, Pieces) -> - case Uri_string of - <<"//"/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<"//"/utf8, Rest/binary>> -> - parse_authority_pieces(Rest, Pieces); - - _ -> - parse_path(Uri_string, Pieces) - end. - --file("src/gleam/uri.gleam", 91). --spec parse_scheme_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_scheme_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"/"/utf8, _/binary>> when Size =:= 0 -> - parse_authority_with_slashes(Uri_string, Pieces); - - <<"/"/utf8, _/binary>> -> - Scheme = binary:part(Original, 0, Size), - Pieces@1 = {uri, - {some, string:lowercase(Scheme)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_authority_with_slashes(Uri_string, Pieces@1); - - <<"?"/utf8, Rest/binary>> when Size =:= 0 -> - parse_query_with_question_mark(Rest, Pieces); - - <<"?"/utf8, Rest@1/binary>> -> - Scheme@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - {some, string:lowercase(Scheme@1)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@1, Pieces@2); - - <<"#"/utf8, Rest@2/binary>> when Size =:= 0 -> - parse_fragment(Rest@2, Pieces); - - <<"#"/utf8, Rest@3/binary>> -> - Scheme@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - {some, string:lowercase(Scheme@2)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@3, Pieces@3); - - <<":"/utf8, _/binary>> when Size =:= 0 -> - {error, nil}; - - <<":"/utf8, Rest@4/binary>> -> - Scheme@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - {some, string:lowercase(Scheme@3)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_authority_with_slashes(Rest@4, Pieces@4); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Original, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@5} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_scheme_loop(Original, Rest@5, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 537). -?DOC( - " Parses an urlencoded query string into a list of key value pairs.\n" - " Returns an error for invalid encoding.\n" - "\n" - " The opposite operation is `uri.query_to_string`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse_query(\"a=1&b=2\")\n" - " // -> Ok([#(\"a\", \"1\"), #(\"b\", \"2\")])\n" - " ```\n" -). --spec parse_query(binary()) -> {ok, list({binary(), binary()})} | {error, nil}. -parse_query(Query) -> - gleam_stdlib:parse_query(Query). - --file("src/gleam/uri.gleam", 573). -?DOC( - " Encodes a string into a percent encoded representation.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " percent_encode(\"100% great\")\n" - " // -> \"100%25%20great\"\n" - " ```\n" -). --spec percent_encode(binary()) -> binary(). -percent_encode(Value) -> - gleam_stdlib:percent_encode(Value). - --file("src/gleam/uri.gleam", 558). --spec query_pair({binary(), binary()}) -> gleam@string_tree:string_tree(). -query_pair(Pair) -> - gleam_stdlib:identity( - [gleam_stdlib:percent_encode(erlang:element(1, Pair)), - <<"="/utf8>>, - gleam_stdlib:percent_encode(erlang:element(2, Pair))] - ). - --file("src/gleam/uri.gleam", 550). -?DOC( - " Encodes a list of key value pairs as a URI query string.\n" - "\n" - " The opposite operation is `uri.parse_query`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " query_to_string([#(\"a\", \"1\"), #(\"b\", \"2\")])\n" - " // -> \"a=1&b=2\"\n" - " ```\n" -). --spec query_to_string(list({binary(), binary()})) -> binary(). -query_to_string(Query) -> - _pipe = Query, - _pipe@1 = gleam@list:map(_pipe, fun query_pair/1), - _pipe@2 = gleam@list:intersperse( - _pipe@1, - gleam_stdlib:identity(<<"&"/utf8>>) - ), - _pipe@3 = gleam_stdlib:identity(_pipe@2), - unicode:characters_to_binary(_pipe@3). - --file("src/gleam/uri.gleam", 586). -?DOC( - " Decodes a percent encoded string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " percent_decode(\"100%25%20great+fun\")\n" - " // -> Ok(\"100% great+fun\")\n" - " ```\n" -). --spec percent_decode(binary()) -> {ok, binary()} | {error, nil}. -percent_decode(Value) -> - gleam_stdlib:percent_decode(Value). - --file("src/gleam/uri.gleam", 608). --spec remove_dot_segments_loop(list(binary()), list(binary())) -> list(binary()). -remove_dot_segments_loop(Input, Accumulator) -> - case Input of - [] -> - lists:reverse(Accumulator); - - [Segment | Rest] -> - Accumulator@5 = case {Segment, Accumulator} of - {<<""/utf8>>, Accumulator@1} -> - Accumulator@1; - - {<<"."/utf8>>, Accumulator@2} -> - Accumulator@2; - - {<<".."/utf8>>, []} -> - []; - - {<<".."/utf8>>, [_ | Accumulator@3]} -> - Accumulator@3; - - {Segment@1, Accumulator@4} -> - [Segment@1 | Accumulator@4] - end, - remove_dot_segments_loop(Rest, Accumulator@5) - end. - --file("src/gleam/uri.gleam", 604). --spec remove_dot_segments(list(binary())) -> list(binary()). -remove_dot_segments(Input) -> - remove_dot_segments_loop(Input, []). - --file("src/gleam/uri.gleam", 600). -?DOC( - " Splits the path section of a URI into it's constituent segments.\n" - "\n" - " Removes empty segments and resolves dot-segments as specified in\n" - " [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " path_segments(\"/users/1\")\n" - " // -> [\"users\" ,\"1\"]\n" - " ```\n" -). --spec path_segments(binary()) -> list(binary()). -path_segments(Path) -> - remove_dot_segments(gleam@string:split(Path, <<"/"/utf8>>)). - --file("src/gleam/uri.gleam", 639). -?DOC( - " Encodes a `Uri` value as a URI string.\n" - "\n" - " The opposite operation is `uri.parse`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let uri = Uri(..empty, scheme: Some(\"https\"), host: Some(\"example.com\"))\n" - " to_string(uri)\n" - " // -> \"https://example.com\"\n" - " ```\n" -). --spec to_string(uri()) -> binary(). -to_string(Uri) -> - Parts = case erlang:element(8, Uri) of - {some, Fragment} -> - [<<"#"/utf8>>, Fragment]; - - none -> - [] - end, - Parts@1 = case erlang:element(7, Uri) of - {some, Query} -> - [<<"?"/utf8>>, Query | Parts]; - - none -> - Parts - end, - Parts@2 = [erlang:element(6, Uri) | Parts@1], - Parts@3 = case {erlang:element(4, Uri), - gleam_stdlib:string_starts_with(erlang:element(6, Uri), <<"/"/utf8>>)} of - {{some, Host}, false} when Host =/= <<""/utf8>> -> - [<<"/"/utf8>> | Parts@2]; - - {_, _} -> - Parts@2 - end, - Parts@4 = case {erlang:element(4, Uri), erlang:element(5, Uri)} of - {{some, _}, {some, Port}} -> - [<<":"/utf8>>, erlang:integer_to_binary(Port) | Parts@3]; - - {_, _} -> - Parts@3 - end, - Parts@5 = case {erlang:element(2, Uri), - erlang:element(3, Uri), - erlang:element(4, Uri)} of - {{some, S}, {some, U}, {some, H}} -> - [S, <<"://"/utf8>>, U, <<"@"/utf8>>, H | Parts@4]; - - {{some, S@1}, none, {some, H@1}} -> - [S@1, <<"://"/utf8>>, H@1 | Parts@4]; - - {{some, S@2}, {some, _}, none} -> - [S@2, <<":"/utf8>> | Parts@4]; - - {{some, S@2}, none, none} -> - [S@2, <<":"/utf8>> | Parts@4]; - - {none, none, {some, H@2}} -> - [<<"//"/utf8>>, H@2 | Parts@4]; - - {_, _, _} -> - Parts@4 - end, - erlang:list_to_binary(Parts@5). - --file("src/gleam/uri.gleam", 683). -?DOC( - " Fetches the origin of a URI.\n" - "\n" - " Returns the origin of a uri as defined in\n" - " [RFC 6454](https://tools.ietf.org/html/rfc6454)\n" - "\n" - " The supported URI schemes are `http` and `https`.\n" - " URLs without a scheme will return `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(uri) = parse(\"https://example.com/path?foo#bar\")\n" - " origin(uri)\n" - " // -> Ok(\"https://example.com\")\n" - " ```\n" -). --spec origin(uri()) -> {ok, binary()} | {error, nil}. -origin(Uri) -> - {uri, Scheme, _, Host, Port, _, _, _} = Uri, - case {Host, Scheme} of - {{some, H}, {some, <<"https"/utf8>>}} when Port =:= {some, 443} -> - {ok, erlang:list_to_binary([<<"https://"/utf8>>, H])}; - - {{some, H@1}, {some, <<"http"/utf8>>}} when Port =:= {some, 80} -> - {ok, erlang:list_to_binary([<<"http://"/utf8>>, H@1])}; - - {{some, H@2}, {some, S}} when (S =:= <<"http"/utf8>>) orelse (S =:= <<"https"/utf8>>) -> - case Port of - {some, P} -> - {ok, - erlang:list_to_binary( - [S, - <<"://"/utf8>>, - H@2, - <<":"/utf8>>, - erlang:integer_to_binary(P)] - )}; - - none -> - {ok, erlang:list_to_binary([S, <<"://"/utf8>>, H@2])} - end; - - {_, _} -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 764). --spec drop_last(list(DDO)) -> list(DDO). -drop_last(Elements) -> - gleam@list:take(Elements, erlang:length(Elements) - 1). - --file("src/gleam/uri.gleam", 768). --spec join_segments(list(binary())) -> binary(). -join_segments(Segments) -> - gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). - --file("src/gleam/uri.gleam", 706). -?DOC( - " Resolves a URI with respect to the given base URI.\n" - "\n" - " The base URI must be an absolute URI or this function will return an error.\n" - " The algorithm for merging uris is described in\n" - " [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2).\n" -). --spec merge(uri(), uri()) -> {ok, uri()} | {error, nil}. -merge(Base, Relative) -> - case Base of - {uri, {some, _}, _, {some, _}, _, _, _, _} -> - case Relative of - {uri, _, _, {some, _}, _, _, _, _} -> - Path = begin - _pipe = erlang:element(6, Relative), - _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), - _pipe@2 = remove_dot_segments(_pipe@1), - join_segments(_pipe@2) - end, - Resolved = {uri, - gleam@option:'or'( - erlang:element(2, Relative), - erlang:element(2, Base) - ), - none, - erlang:element(4, Relative), - gleam@option:'or'( - erlang:element(5, Relative), - erlang:element(5, Base) - ), - Path, - erlang:element(7, Relative), - erlang:element(8, Relative)}, - {ok, Resolved}; - - _ -> - {New_path, New_query} = case erlang:element(6, Relative) of - <<""/utf8>> -> - {erlang:element(6, Base), - gleam@option:'or'( - erlang:element(7, Relative), - erlang:element(7, Base) - )}; - - _ -> - Path_segments = case gleam_stdlib:string_starts_with( - erlang:element(6, Relative), - <<"/"/utf8>> - ) of - true -> - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ); - - false -> - _pipe@3 = erlang:element(6, Base), - _pipe@4 = gleam@string:split( - _pipe@3, - <<"/"/utf8>> - ), - _pipe@5 = drop_last(_pipe@4), - lists:append( - _pipe@5, - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ) - ) - end, - Path@1 = begin - _pipe@6 = Path_segments, - _pipe@7 = remove_dot_segments(_pipe@6), - join_segments(_pipe@7) - end, - {Path@1, erlang:element(7, Relative)} - end, - Resolved@1 = {uri, - erlang:element(2, Base), - none, - erlang:element(4, Base), - erlang:element(5, Base), - New_path, - New_query, - erlang:element(8, Relative)}, - {ok, Resolved@1} - end; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 81). -?DOC( - " Parses a compliant URI string into the `Uri` Type.\n" - " If the string is not a valid URI string then an error is returned.\n" - "\n" - " The opposite operation is `uri.to_string`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " parse(\"https://example.com:1234/a/b?query=true#fragment\")\n" - " // -> Ok(\n" - " // Uri(\n" - " // scheme: Some(\"https\"),\n" - " // userinfo: None,\n" - " // host: Some(\"example.com\"),\n" - " // port: Some(1234),\n" - " // path: \"/a/b\",\n" - " // query: Some(\"query=true\"),\n" - " // fragment: Some(\"fragment\")\n" - " // )\n" - " // )\n" - " ```\n" -). --spec parse(binary()) -> {ok, uri()} | {error, nil}. -parse(Uri_string) -> - gleam_stdlib:uri_parse(Uri_string). diff --git a/build/packages/gleam_stdlib/src/gleam_stdlib.app.src b/build/packages/gleam_stdlib/src/gleam_stdlib.app.src deleted file mode 100644 index 761251e..0000000 --- a/build/packages/gleam_stdlib/src/gleam_stdlib.app.src +++ /dev/null @@ -1,31 +0,0 @@ -{application, gleam_stdlib, [ - {vsn, "0.65.0"}, - {applications, []}, - {description, "A standard library for the Gleam programming language"}, - {modules, [gleam@bit_array, - gleam@bool, - gleam@bytes_tree, - gleam@dict, - gleam@dynamic, - gleam@dynamic@decode, - gleam@float, - gleam@function, - gleam@int, - gleam@io, - gleam@list, - gleam@option, - gleam@order, - gleam@pair, - gleam@result, - gleam@set, - gleam@string, - gleam@string_tree, - gleam@uri, - gleam_stdlib, - gleam_stdlib@@main, - gleam_stdlib_test_ffi, - gleeunit_ffi, - gleeunit_gleam_panic_ffi, - gleeunit_progress]}, - {registered, []} -]}. diff --git a/build/packages/gleam_stdlib/src/gleam_stdlib.erl b/build/packages/gleam_stdlib/src/gleam_stdlib.erl deleted file mode 100644 index 2c416f4..0000000 --- a/build/packages/gleam_stdlib/src/gleam_stdlib.erl +++ /dev/null @@ -1,534 +0,0 @@ --module(gleam_stdlib). - --export([ - map_get/2, iodata_append/2, identity/1, parse_int/1, parse_float/1, - less_than/2, string_pop_grapheme/1, string_pop_codeunit/1, - string_starts_with/2, wrap_list/1, string_ends_with/2, string_pad/4, - uri_parse/1, bit_array_slice/3, percent_encode/1, percent_decode/1, - base64_decode/1, parse_query/1, bit_array_concat/1, - base64_encode/2, tuple_get/2, classify_dynamic/1, print/1, - println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, - int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, - crop_string/2, base16_encode/1, base16_decode/1, string_replace/3, slice/3, - bit_array_to_int_and_size/1, bit_array_pad_to_bytes/1, index/2, list/5, - dict/1, int/1, float/1, bit_array/1, is_null/1 -]). - -%% Taken from OTP's uri_string module --define(DEC2HEX(X), - if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; - ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 - end). - -%% Taken from OTP's uri_string module --define(HEX2DEC(X), - if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; - ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; - ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 - end). - --define(is_lowercase_char(X), - (X > 96 andalso X < 123)). --define(is_underscore_char(X), - (X == 95)). --define(is_digit_char(X), - (X > 47 andalso X < 58)). --define(is_ascii_character(X), - (erlang:is_integer(X) andalso X >= 32 andalso X =< 126)). - -uppercase(X) -> X - 32. - -map_get(Map, Key) -> - case maps:find(Key, Map) of - error -> {error, nil}; - OkFound -> OkFound - end. - -iodata_append(Iodata, String) -> [Iodata, String]. - -identity(X) -> X. - -classify_dynamic(nil) -> <<"Nil">>; -classify_dynamic(null) -> <<"Nil">>; -classify_dynamic(undefined) -> <<"Nil">>; -classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; -classify_dynamic(X) when is_atom(X) -> <<"Atom">>; -classify_dynamic(X) when is_binary(X) -> <<"String">>; -classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>; -classify_dynamic(X) when is_integer(X) -> <<"Int">>; -classify_dynamic(X) when is_float(X) -> <<"Float">>; -classify_dynamic(X) when is_list(X) -> <<"List">>; -classify_dynamic(X) when is_map(X) -> <<"Dict">>; -classify_dynamic(X) when is_tuple(X) -> <<"Array">>; -classify_dynamic(X) when is_reference(X) -> <<"Reference">>; -classify_dynamic(X) when is_pid(X) -> <<"Pid">>; -classify_dynamic(X) when is_port(X) -> <<"Port">>; -classify_dynamic(X) when - is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse - is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse - is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse - is_function(X, 9) orelse is_function(X, 10) orelse is_function(X, 11) orelse - is_function(X, 12) -> <<"Function">>; -classify_dynamic(_) -> <<"Unknown">>. - -tuple_get(_tup, Index) when Index < 0 -> {error, nil}; -tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil}; -tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}. - -int_from_base_string(String, Base) -> - case catch binary_to_integer(String, Base) of - Int when is_integer(Int) -> {ok, Int}; - _ -> {error, nil} - end. - -parse_int(String) -> - case catch binary_to_integer(String) of - Int when is_integer(Int) -> {ok, Int}; - _ -> {error, nil} - end. - -parse_float(String) -> - case catch binary_to_float(String) of - Float when is_float(Float) -> {ok, Float}; - _ -> {error, nil} - end. - -less_than(Lhs, Rhs) -> - Lhs < Rhs. - -string_starts_with(_, <<>>) -> true; -string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false; -string_starts_with(String, Prefix) -> - PrefixSize = byte_size(Prefix), - Prefix == binary_part(String, 0, PrefixSize). - -string_ends_with(_, <<>>) -> true; -string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false; -string_ends_with(String, Suffix) -> - SuffixSize = byte_size(Suffix), - Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize). - -string_pad(String, Length, Dir, PadString) -> - Chars = string:pad(String, Length, Dir, binary_to_list(PadString)), - case unicode:characters_to_binary(Chars) of - Bin when is_binary(Bin) -> Bin; - Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}}) - end. - -string_pop_grapheme(String) -> - case string:next_grapheme(String) of - [ Next | Rest ] when is_binary(Rest) -> - {ok, {unicode:characters_to_binary([Next]), Rest}}; - - [ Next | Rest ] -> - {ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}}; - - _ -> {error, nil} - end. - -string_pop_codeunit(<>) -> {Cp, Rest}; -string_pop_codeunit(Binary) -> {0, Binary}. - -bit_array_pad_to_bytes(Bin) -> - case erlang:bit_size(Bin) rem 8 of - 0 -> Bin; - TrailingBits -> - PaddingBits = 8 - TrailingBits, - <> - end. - -bit_array_concat(BitArrays) -> - list_to_bitstring(BitArrays). - --if(?OTP_RELEASE >= 26). -base64_encode(Bin, Padding) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - base64:encode(PaddedBin, #{padding => Padding}). --else. -base64_encode(_Bin, _Padding) -> - erlang:error(<<"Erlang OTP/26 or higher is required to use base64:encode">>). --endif. - -bit_array_slice(Bin, Pos, Len) -> - try {ok, binary:part(Bin, Pos, Len)} - catch error:badarg -> {error, nil} - end. - -base64_decode(S) -> - try {ok, base64:decode(S)} - catch error:_ -> {error, nil} - end. - -wrap_list(X) when is_list(X) -> X; -wrap_list(X) -> [X]. - -parse_query(Query) -> - case uri_string:dissect_query(Query) of - {error, _, _} -> {error, nil}; - Pairs -> - Pairs1 = lists:map(fun - ({K, true}) -> {K, <<"">>}; - (Pair) -> Pair - end, Pairs), - {ok, Pairs1} - end. - -percent_encode(B) -> percent_encode(B, <<>>). -percent_encode(<<>>, Acc) -> - Acc; -percent_encode(<>, Acc) -> - case percent_ok(H) of - true -> - percent_encode(T, <>); - false -> - <> = <>, - percent_encode(T, <>) - end. - -percent_decode(Cs) -> percent_decode(Cs, <<>>). -percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> - case is_hex_digit(C0) andalso is_hex_digit(C1) of - true -> - B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), - percent_decode(Cs, <>); - false -> - {error, nil} - end; -percent_decode(<>, Acc) -> - percent_decode(Cs, <>); -percent_decode(<<>>, Acc) -> - check_utf8(Acc). - -percent_ok($!) -> true; -percent_ok($$) -> true; -percent_ok($') -> true; -percent_ok($() -> true; -percent_ok($)) -> true; -percent_ok($*) -> true; -percent_ok($+) -> true; -percent_ok($-) -> true; -percent_ok($.) -> true; -percent_ok($_) -> true; -percent_ok($~) -> true; -percent_ok(C) when $0 =< C, C =< $9 -> true; -percent_ok(C) when $A =< C, C =< $Z -> true; -percent_ok(C) when $a =< C, C =< $z -> true; -percent_ok(_) -> false. - -is_hex_digit(C) -> - ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). - -check_utf8(Cs) -> - case unicode:characters_to_list(Cs) of - {incomplete, _, _} -> {error, nil}; - {error, _, _} -> {error, nil}; - _ -> {ok, Cs} - end. - -uri_parse(String) -> - case uri_string:parse(String) of - {error, _, _} -> {error, nil}; - Uri -> - Port = - try maps:get(port, Uri) of - undefined -> none; - Value -> {some, Value} - catch _:_ -> none - end, - {ok, {uri, - maps_get_optional(Uri, scheme), - maps_get_optional(Uri, userinfo), - maps_get_optional(Uri, host), - Port, - maps_get_or(Uri, path, <<>>), - maps_get_optional(Uri, query), - maps_get_optional(Uri, fragment) - }} - end. - -maps_get_optional(Map, Key) -> - try {some, maps:get(Key, Map)} - catch _:_ -> none - end. - -maps_get_or(Map, Key, Default) -> - try maps:get(Key, Map) - catch _:_ -> Default - end. - -print(String) -> - io:put_chars(String), - nil. - -println(String) -> - io:put_chars([String, $\n]), - nil. - -print_error(String) -> - io:put_chars(standard_error, String), - nil. - -println_error(String) -> - io:put_chars(standard_error, [String, $\n]), - nil. - -inspect(true) -> - "True"; -inspect(false) -> - "False"; -inspect(nil) -> - "Nil"; -inspect(Data) when is_map(Data) -> - Fields = [ - [<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>] - || {Key, Value} <- maps:to_list(Data) - ], - ["dict.from_list([", lists:join(", ", Fields), "])"]; -inspect(Atom) when is_atom(Atom) -> - erlang:element(2, inspect_atom(Atom)); -inspect(Any) when is_integer(Any) -> - erlang:integer_to_list(Any); -inspect(Any) when is_float(Any) -> - io_lib_format:fwrite_g(Any); -inspect(Binary) when is_binary(Binary) -> - case inspect_maybe_utf8_string(Binary, <<>>) of - {ok, InspectedUtf8String} -> InspectedUtf8String; - {error, not_a_utf8_string} -> - Segments = [erlang:integer_to_list(X) || <> <= Binary], - ["<<", lists:join(", ", Segments), ">>"] - end; -inspect(Bits) when is_bitstring(Bits) -> - inspect_bit_array(Bits); -inspect(List) when is_list(List) -> - case inspect_list(List, true) of - {charlist, _} -> ["charlist.from_string(\"", list_to_binary(List), "\")"]; - {proper, Elements} -> ["[", Elements, "]"]; - {improper, Elements} -> ["//erl([", Elements, "])"] - end; -inspect(Any) when is_tuple(Any) % Record constructors - andalso is_atom(element(1, Any)) - andalso element(1, Any) =/= false - andalso element(1, Any) =/= true - andalso element(1, Any) =/= nil --> - [Atom | ArgsList] = erlang:tuple_to_list(Any), - InspectedArgs = lists:map(fun inspect/1, ArgsList), - case inspect_atom(Atom) of - {gleam_atom, GleamAtom} -> - Args = lists:join(<<", ">>, InspectedArgs), - [GleamAtom, "(", Args, ")"]; - {erlang_atom, ErlangAtom} -> - Args = lists:join(<<", ">>, [ErlangAtom | InspectedArgs]), - ["#(", Args, ")"] - end; -inspect(Tuple) when is_tuple(Tuple) -> - Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)), - ["#(", lists:join(", ", Elements), ")"]; -inspect(Any) when is_function(Any) -> - {arity, Arity} = erlang:fun_info(Any, arity), - ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), - Args = lists:join(<<", ">>, - lists:map(fun(Arg) -> <> end, ArgsAsciiCodes) - ), - ["//fn(", Args, ") { ... }"]; -inspect(Any) -> - ["//erl(", io_lib:format("~p", [Any]), ")"]. - -inspect_atom(Atom) -> - Binary = erlang:atom_to_binary(Atom), - case inspect_maybe_gleam_atom(Binary, none, <<>>) of - {ok, Inspected} -> {gleam_atom, Inspected}; - {error, _} -> {erlang_atom, ["atom.create(\"", Binary, "\")"]} - end. - -inspect_maybe_gleam_atom(<<>>, none, _) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, none, _) when ?is_digit_char(First) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, _PrevChar, _Acc) - when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, none, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) -> - inspect_maybe_gleam_atom(Rest, $_, Acc); -inspect_maybe_gleam_atom(<>, $_, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<>, _PrevChar, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) -> - {ok, Acc}; -inspect_maybe_gleam_atom(A, B, C) -> - erlang:display({A, B, C}), - throw({gleam_error, A, B, C}). - -inspect_list([], _) -> - {proper, []}; -inspect_list([First], true) when ?is_ascii_character(First) -> - {charlist, nil}; -inspect_list([First], _) -> - {proper, [inspect(First)]}; -inspect_list([First | Rest], ValidCharlist) when is_list(Rest) -> - StillValidCharlist = ValidCharlist andalso ?is_ascii_character(First), - {Kind, Inspected} = inspect_list(Rest, StillValidCharlist), - {Kind, [inspect(First), <<", ">> | Inspected]}; -inspect_list([First | ImproperTail], _) -> - {improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}. - -inspect_bit_array(Bits) -> - Text = inspect_bit_array(Bits, <<"<<">>), - <>">>. - -inspect_bit_array(<<>>, Acc) -> - Acc; -inspect_bit_array(<>, Acc) -> - inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X))); -inspect_bit_array(Rest, Acc) -> - Size = bit_size(Rest), - <> = Rest, - X1 = erlang:integer_to_binary(X), - Size1 = erlang:integer_to_binary(Size), - Segment = <>, - inspect_bit_array(<<>>, append_segment(Acc, Segment)). - -bit_array_to_int_and_size(A) -> - Size = bit_size(A), - <> = A, - {A1, Size}. - -append_segment(<<"<<">>, Segment) -> - <<"<<", Segment/binary>>; -append_segment(Acc, Segment) -> - <>. - - -inspect_maybe_utf8_string(Binary, Acc) -> - case Binary of - <<>> -> {ok, <<$", Acc/binary, $">>}; - <> -> - Escaped = case First of - $" -> <<$\\, $">>; - $\\ -> <<$\\, $\\>>; - $\r -> <<$\\, $r>>; - $\n -> <<$\\, $n>>; - $\t -> <<$\\, $t>>; - $\f -> <<$\\, $f>>; - X when X > 126, X < 160 -> convert_to_u(X); - X when X < 32 -> convert_to_u(X); - Other -> <> - end, - inspect_maybe_utf8_string(Rest, <>); - _ -> {error, not_a_utf8_string} - end. - -convert_to_u(Code) -> - list_to_binary(io_lib:format("\\u{~4.16.0B}", [Code])). - -float_to_string(Float) when is_float(Float) -> - erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)). - -utf_codepoint_list_to_string(List) -> - case unicode:characters_to_binary(List) of - {error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}}); - Binary -> Binary - end. - -crop_string(String, Prefix) -> - case string:find(String, Prefix) of - nomatch -> String; - New -> New - end. - -contains_string(String, Substring) -> - is_bitstring(string:find(String, Substring)). - -base16_encode(Bin) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - binary:encode_hex(PaddedBin). - -base16_decode(String) -> - try - {ok, binary:decode_hex(String)} - catch - _:_ -> {error, nil} - end. - -string_replace(String, Pattern, Replacement) -> - string:replace(String, Pattern, Replacement, all). - -slice(String, Index, Length) -> - case string:slice(String, Index, Length) of - X when is_binary(X) -> X; - X when is_list(X) -> unicode:characters_to_binary(X) - end. - -index([X | _], 0) -> - {ok, {some, X}}; -index([_, X | _], 1) -> - {ok, {some, X}}; -index([_, _, X | _], 2) -> - {ok, {some, X}}; -index([_, _, _, X | _], 3) -> - {ok, {some, X}}; -index([_, _, _, _, X | _], 4) -> - {ok, {some, X}}; -index([_, _, _, _, _, X | _], 5) -> - {ok, {some, X}}; -index([_, _, _, _, _, _, X | _], 6) -> - {ok, {some, X}}; -index([_, _, _, _, _, _, _, X | _], 7) -> - {ok, {some, X}}; -index(Tuple, Index) when is_tuple(Tuple) andalso is_integer(Index) -> - {ok, try - {some, element(Index + 1, Tuple)} - catch _:_ -> - none - end}; -index(Map, Key) when is_map(Map) -> - {ok, try - {some, maps:get(Key, Map)} - catch _:_ -> - none - end}; -index(_, Index) when is_integer(Index) -> - {error, <<"Indexable">>}; -index(_, _) -> - {error, <<"Dict">>}. - -list(T, A, B, C, D) when is_tuple(T) -> - list(tuple_to_list(T), A, B, C, D); -list([], _, _, _, Acc) -> - {lists:reverse(Acc), []}; -list([X | Xs], Decode, PushPath, Index, Acc) -> - {Out, Errors} = Decode(X), - case Errors of - [] -> list(Xs, Decode, PushPath, Index + 1, [Out | Acc]); - _ -> PushPath({[], Errors}, integer_to_binary(Index)) - end; -list(Unexpected, _, _, _, []) -> - Found = gleam@dynamic:classify(Unexpected), - Error = {decode_error, <<"List"/utf8>>, Found, []}, - {[], [Error]}; -list(_, _, _, _, Acc) -> - {lists:reverse(Acc), []}. - -dict(#{} = Data) -> {ok, Data}; -dict(_) -> {error, nil}. - -int(I) when is_integer(I) -> {ok, I}; -int(_) -> {error, 0}. - -float(F) when is_float(F) -> {ok, F}; -float(_) -> {error, 0.0}. - -bit_array(B) when is_bitstring(B) -> {ok, B}; -bit_array(_) -> {error, <<>>}. - -is_null(X) -> - X =:= undefined orelse X =:= null orelse X =:= nil. diff --git a/build/packages/gleam_stdlib/src/gleam_stdlib.mjs b/build/packages/gleam_stdlib/src/gleam_stdlib.mjs deleted file mode 100644 index ebac45f..0000000 --- a/build/packages/gleam_stdlib/src/gleam_stdlib.mjs +++ /dev/null @@ -1,1048 +0,0 @@ -import { - BitArray, - Error, - List, - Ok, - Result, - UtfCodepoint, - stringBits, - toBitArray, - bitArraySlice, - NonEmpty, - Empty, - CustomType, -} from "./gleam.mjs"; -import { Some, None } from "./gleam/option.mjs"; -import Dict from "./dict.mjs"; -import { classify } from "./gleam/dynamic.mjs"; -import { DecodeError } from "./gleam/dynamic/decode.mjs"; - -const Nil = undefined; -const NOT_FOUND = {}; - -export function identity(x) { - return x; -} - -export function parse_int(value) { - if (/^[-+]?(\d+)$/.test(value)) { - return new Ok(parseInt(value)); - } else { - return new Error(Nil); - } -} - -export function parse_float(value) { - if (/^[-+]?(\d+)\.(\d+)([eE][-+]?\d+)?$/.test(value)) { - return new Ok(parseFloat(value)); - } else { - return new Error(Nil); - } -} - -export function to_string(term) { - return term.toString(); -} - -export function int_to_base_string(int, base) { - return int.toString(base).toUpperCase(); -} - -const int_base_patterns = { - 2: /[^0-1]/, - 3: /[^0-2]/, - 4: /[^0-3]/, - 5: /[^0-4]/, - 6: /[^0-5]/, - 7: /[^0-6]/, - 8: /[^0-7]/, - 9: /[^0-8]/, - 10: /[^0-9]/, - 11: /[^0-9a]/, - 12: /[^0-9a-b]/, - 13: /[^0-9a-c]/, - 14: /[^0-9a-d]/, - 15: /[^0-9a-e]/, - 16: /[^0-9a-f]/, - 17: /[^0-9a-g]/, - 18: /[^0-9a-h]/, - 19: /[^0-9a-i]/, - 20: /[^0-9a-j]/, - 21: /[^0-9a-k]/, - 22: /[^0-9a-l]/, - 23: /[^0-9a-m]/, - 24: /[^0-9a-n]/, - 25: /[^0-9a-o]/, - 26: /[^0-9a-p]/, - 27: /[^0-9a-q]/, - 28: /[^0-9a-r]/, - 29: /[^0-9a-s]/, - 30: /[^0-9a-t]/, - 31: /[^0-9a-u]/, - 32: /[^0-9a-v]/, - 33: /[^0-9a-w]/, - 34: /[^0-9a-x]/, - 35: /[^0-9a-y]/, - 36: /[^0-9a-z]/, -}; - -export function int_from_base_string(string, base) { - if (int_base_patterns[base].test(string.replace(/^-/, "").toLowerCase())) { - return new Error(Nil); - } - - const result = parseInt(string, base); - - if (isNaN(result)) { - return new Error(Nil); - } - - return new Ok(result); -} - -export function string_replace(string, target, substitute) { - return string.replaceAll(target, substitute); -} - -export function string_reverse(string) { - return [...string].reverse().join(""); -} - -export function string_length(string) { - if (string === "") { - return 0; - } - const iterator = graphemes_iterator(string); - if (iterator) { - let i = 0; - for (const _ of iterator) { - i++; - } - return i; - } else { - return string.match(/./gsu).length; - } -} - -export function graphemes(string) { - const iterator = graphemes_iterator(string); - if (iterator) { - return List.fromArray(Array.from(iterator).map((item) => item.segment)); - } else { - return List.fromArray(string.match(/./gsu)); - } -} - -let segmenter = undefined; - -function graphemes_iterator(string) { - if (globalThis.Intl && Intl.Segmenter) { - segmenter ||= new Intl.Segmenter(); - return segmenter.segment(string)[Symbol.iterator](); - } -} - -export function pop_grapheme(string) { - let first; - const iterator = graphemes_iterator(string); - if (iterator) { - first = iterator.next().value?.segment; - } else { - first = string.match(/./su)?.[0]; - } - if (first) { - return new Ok([first, string.slice(first.length)]); - } else { - return new Error(Nil); - } -} - -export function pop_codeunit(str) { - return [str.charCodeAt(0) | 0, str.slice(1)]; -} - -export function lowercase(string) { - return string.toLowerCase(); -} - -export function uppercase(string) { - return string.toUpperCase(); -} - -export function less_than(a, b) { - return a < b; -} - -export function add(a, b) { - return a + b; -} - -export function split(xs, pattern) { - return List.fromArray(xs.split(pattern)); -} - -export function concat(xs) { - let result = ""; - for (const x of xs) { - result = result + x; - } - return result; -} - -export function length(data) { - return data.length; -} - -export function string_byte_slice(string, index, length) { - return string.slice(index, index + length); -} - -export function string_grapheme_slice(string, idx, len) { - if (len <= 0 || idx >= string.length) { - return ""; - } - - const iterator = graphemes_iterator(string); - if (iterator) { - while (idx-- > 0) { - iterator.next(); - } - - let result = ""; - - while (len-- > 0) { - const v = iterator.next().value; - if (v === undefined) { - break; - } - - result += v.segment; - } - - return result; - } else { - return string - .match(/./gsu) - .slice(idx, idx + len) - .join(""); - } -} - -export function string_codeunit_slice(str, from, length) { - return str.slice(from, from + length); -} -export function crop_string(string, substring) { - return string.substring(string.indexOf(substring)); -} - -export function contains_string(haystack, needle) { - return haystack.indexOf(needle) >= 0; -} - -export function starts_with(haystack, needle) { - return haystack.startsWith(needle); -} - -export function ends_with(haystack, needle) { - return haystack.endsWith(needle); -} - -export function split_once(haystack, needle) { - const index = haystack.indexOf(needle); - if (index >= 0) { - const before = haystack.slice(0, index); - const after = haystack.slice(index + needle.length); - return new Ok([before, after]); - } else { - return new Error(Nil); - } -} - -const unicode_whitespaces = [ - "\u0020", // Space - "\u0009", // Horizontal tab - "\u000A", // Line feed - "\u000B", // Vertical tab - "\u000C", // Form feed - "\u000D", // Carriage return - "\u0085", // Next line - "\u2028", // Line separator - "\u2029", // Paragraph separator -].join(""); - -const trim_start_regex = /* @__PURE__ */ new RegExp( - `^[${unicode_whitespaces}]*`, -); -const trim_end_regex = /* @__PURE__ */ new RegExp(`[${unicode_whitespaces}]*$`); - -export function trim_start(string) { - return string.replace(trim_start_regex, ""); -} - -export function trim_end(string) { - return string.replace(trim_end_regex, ""); -} - -export function bit_array_from_string(string) { - return toBitArray([stringBits(string)]); -} - -export function bit_array_bit_size(bit_array) { - return bit_array.bitSize; -} - -export function bit_array_byte_size(bit_array) { - return bit_array.byteSize; -} - -export function bit_array_pad_to_bytes(bit_array) { - const trailingBitsCount = bit_array.bitSize % 8; - - // If the bit array is a whole number of bytes it can be returned unchanged - if (trailingBitsCount === 0) { - return bit_array; - } - - const finalByte = bit_array.byteAt(bit_array.byteSize - 1); - - // The required final byte has its unused trailing bits set to zero - const unusedBitsCount = 8 - trailingBitsCount; - const correctFinalByte = (finalByte >> unusedBitsCount) << unusedBitsCount; - - // If the unused bits in the final byte are already set to zero then the - // existing buffer can be re-used, avoiding a copy - if (finalByte === correctFinalByte) { - return new BitArray( - bit_array.rawBuffer, - bit_array.byteSize * 8, - bit_array.bitOffset, - ); - } - - // Copy the bit array into a new aligned buffer and set the correct final byte - const buffer = new Uint8Array(bit_array.byteSize); - for (let i = 0; i < buffer.length - 1; i++) { - buffer[i] = bit_array.byteAt(i); - } - buffer[buffer.length - 1] = correctFinalByte; - - return new BitArray(buffer); -} - -export function bit_array_concat(bit_arrays) { - return toBitArray(bit_arrays.toArray()); -} - -export function console_log(term) { - console.log(term); -} - -export function console_error(term) { - console.error(term); -} - -export function crash(message) { - throw new globalThis.Error(message); -} - -export function bit_array_to_string(bit_array) { - // If the bit array isn't a whole number of bytes then return an error - if (bit_array.bitSize % 8 !== 0) { - return new Error(Nil); - } - - try { - const decoder = new TextDecoder("utf-8", { fatal: true }); - - if (bit_array.bitOffset === 0) { - return new Ok(decoder.decode(bit_array.rawBuffer)); - } else { - // The input data isn't aligned, so copy it into a new aligned buffer so - // that TextDecoder can be used - const buffer = new Uint8Array(bit_array.byteSize); - for (let i = 0; i < buffer.length; i++) { - buffer[i] = bit_array.byteAt(i); - } - return new Ok(decoder.decode(buffer)); - } - } catch { - return new Error(Nil); - } -} - -export function print(string) { - if (typeof process === "object" && process.stdout?.write) { - process.stdout.write(string); // We can write without a trailing newline - } else if (typeof Deno === "object") { - Deno.stdout.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline - } else { - console.log(string); // We're in a browser. Newlines are mandated - } -} - -export function print_error(string) { - if (typeof process === "object" && process.stderr?.write) { - process.stderr.write(string); // We can write without a trailing newline - } else if (typeof Deno === "object") { - Deno.stderr.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline - } else { - console.error(string); // We're in a browser. Newlines are mandated - } -} - -export function print_debug(string) { - if (typeof process === "object" && process.stderr?.write) { - process.stderr.write(string + "\n"); // If we're in Node.js, use `stderr` - } else if (typeof Deno === "object") { - Deno.stderr.writeSync(new TextEncoder().encode(string + "\n")); // If we're in Deno, use `stderr` - } else { - console.log(string); // Otherwise, use `console.log` (so that it doesn't look like an error) - } -} - -export function ceiling(float) { - return Math.ceil(float); -} - -export function floor(float) { - return Math.floor(float); -} - -export function round(float) { - return Math.round(float); -} - -export function truncate(float) { - return Math.trunc(float); -} - -export function power(base, exponent) { - // It is checked in Gleam that: - // - The base is non-negative and that the exponent is not fractional. - // - The base is non-zero and the exponent is non-negative (otherwise - // the result will essentially be division by zero). - // It can thus be assumed that valid input is passed to the Math.pow - // function and a NaN or Infinity value will not be produced. - return Math.pow(base, exponent); -} - -export function random_uniform() { - const random_uniform_result = Math.random(); - // With round-to-nearest-even behavior, the ranges claimed for the functions below - // (excluding the one for Math.random() itself) aren't exact. - // If extremely large bounds are chosen (2^53 or higher), - // it's possible in extremely rare cases to calculate the usually-excluded upper bound. - // Note that as numbers in JavaScript are IEEE 754 floating point numbers - // See: - // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: - if (random_uniform_result === 1.0) { - return random_uniform(); - } - return random_uniform_result; -} - -export function bit_array_slice(bits, position, length) { - const start = Math.min(position, position + length); - const end = Math.max(position, position + length); - - if (start < 0 || end * 8 > bits.bitSize) { - return new Error(Nil); - } - - return new Ok(bitArraySlice(bits, start * 8, end * 8)); -} - -export function codepoint(int) { - return new UtfCodepoint(int); -} - -export function string_to_codepoint_integer_list(string) { - return List.fromArray(Array.from(string).map((item) => item.codePointAt(0))); -} - -export function utf_codepoint_list_to_string(utf_codepoint_integer_list) { - return utf_codepoint_integer_list - .toArray() - .map((x) => String.fromCodePoint(x.value)) - .join(""); -} - -export function utf_codepoint_to_int(utf_codepoint) { - return utf_codepoint.value; -} - -export function new_map() { - return Dict.new(); -} - -export function map_size(map) { - return map.size; -} - -export function map_to_list(map) { - return List.fromArray(map.entries()); -} - -export function map_remove(key, map) { - return map.delete(key); -} - -export function map_get(map, key) { - const value = map.get(key, NOT_FOUND); - if (value === NOT_FOUND) { - return new Error(Nil); - } - return new Ok(value); -} - -export function map_insert(key, value, map) { - return map.set(key, value); -} - -function unsafe_percent_decode(string) { - return decodeURIComponent(string || ""); -} - -function unsafe_percent_decode_query(string) { - return decodeURIComponent((string || "").replace("+", " ")); -} - -export function percent_decode(string) { - try { - return new Ok(unsafe_percent_decode(string)); - } catch { - return new Error(Nil); - } -} - -export function percent_encode(string) { - return encodeURIComponent(string).replace("%2B", "+"); -} - -export function parse_query(query) { - try { - const pairs = []; - for (const section of query.split("&")) { - const [key, value] = section.split("="); - if (!key) continue; - - const decodedKey = unsafe_percent_decode_query(key); - const decodedValue = unsafe_percent_decode_query(value); - pairs.push([decodedKey, decodedValue]); - } - return new Ok(List.fromArray(pairs)); - } catch { - return new Error(Nil); - } -} - -const b64EncodeLookup = [ - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, -]; - -let b64TextDecoder; - -// Implementation based on https://github.com/mitschabaude/fast-base64/blob/main/js.js -export function base64_encode(bit_array, padding) { - b64TextDecoder ??= new TextDecoder(); - - bit_array = bit_array_pad_to_bytes(bit_array); - - const m = bit_array.byteSize; - const k = m % 3; - const n = Math.floor(m / 3) * 4 + (k && k + 1); - const N = Math.ceil(m / 3) * 4; - const encoded = new Uint8Array(N); - - for (let i = 0, j = 0; j < m; i += 4, j += 3) { - const y = - (bit_array.byteAt(j) << 16) + - (bit_array.byteAt(j + 1) << 8) + - (bit_array.byteAt(j + 2) | 0); - - encoded[i] = b64EncodeLookup[y >> 18]; - encoded[i + 1] = b64EncodeLookup[(y >> 12) & 0x3f]; - encoded[i + 2] = b64EncodeLookup[(y >> 6) & 0x3f]; - encoded[i + 3] = b64EncodeLookup[y & 0x3f]; - } - - let base64 = b64TextDecoder.decode(new Uint8Array(encoded.buffer, 0, n)); - - if (padding) { - if (k === 1) { - base64 += "=="; - } else if (k === 2) { - base64 += "="; - } - } - - return base64; -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64 -export function base64_decode(sBase64) { - try { - const binString = atob(sBase64); - const length = binString.length; - const array = new Uint8Array(length); - for (let i = 0; i < length; i++) { - array[i] = binString.charCodeAt(i); - } - return new Ok(new BitArray(array)); - } catch { - return new Error(Nil); - } -} - -export function classify_dynamic(data) { - if (typeof data === "string") { - return "String"; - } else if (typeof data === "boolean") { - return "Bool"; - } else if (data instanceof Result) { - return "Result"; - } else if (data instanceof List) { - return "List"; - } else if (data instanceof BitArray) { - return "BitArray"; - } else if (data instanceof Dict) { - return "Dict"; - } else if (Number.isInteger(data)) { - return "Int"; - } else if (Array.isArray(data)) { - return `Array`; - } else if (typeof data === "number") { - return "Float"; - } else if (data === null) { - return "Nil"; - } else if (data === undefined) { - return "Nil"; - } else { - const type = typeof data; - return type.charAt(0).toUpperCase() + type.slice(1); - } -} - -export function byte_size(string) { - return new TextEncoder().encode(string).length; -} - -// In JavaScript bitwise operations convert numbers to a sequence of 32 bits -// while Erlang uses arbitrary precision. -// To get around this problem and get consistent results use BigInt and then -// downcast the value back to a Number value. - -export function bitwise_and(x, y) { - return Number(BigInt(x) & BigInt(y)); -} - -export function bitwise_not(x) { - return Number(~BigInt(x)); -} - -export function bitwise_or(x, y) { - return Number(BigInt(x) | BigInt(y)); -} - -export function bitwise_exclusive_or(x, y) { - return Number(BigInt(x) ^ BigInt(y)); -} - -export function bitwise_shift_left(x, y) { - return Number(BigInt(x) << BigInt(y)); -} - -export function bitwise_shift_right(x, y) { - return Number(BigInt(x) >> BigInt(y)); -} - -export function inspect(v) { - return new Inspector().inspect(v); -} - -export function float_to_string(float) { - const string = float.toString().replace("+", ""); - if (string.indexOf(".") >= 0) { - return string; - } else { - const index = string.indexOf("e"); - if (index >= 0) { - return string.slice(0, index) + ".0" + string.slice(index); - } else { - return string + ".0"; - } - } -} - -class Inspector { - #references = new Set(); - - inspect(v) { - const t = typeof v; - if (v === true) return "True"; - if (v === false) return "False"; - if (v === null) return "//js(null)"; - if (v === undefined) return "Nil"; - if (t === "string") return this.#string(v); - if (t === "bigint" || Number.isInteger(v)) return v.toString(); - if (t === "number") return float_to_string(v); - if (v instanceof UtfCodepoint) return this.#utfCodepoint(v); - if (v instanceof BitArray) return this.#bit_array(v); - if (v instanceof RegExp) return `//js(${v})`; - if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; - if (v instanceof globalThis.Error) return `//js(${v.toString()})`; - if (v instanceof Function) { - const args = []; - for (const i of Array(v.length).keys()) - args.push(String.fromCharCode(i + 97)); - return `//fn(${args.join(", ")}) { ... }`; - } - - if (this.#references.size === this.#references.add(v).size) { - return "//js(circular reference)"; - } - - let printed; - if (Array.isArray(v)) { - printed = `#(${v.map((v) => this.inspect(v)).join(", ")})`; - } else if (v instanceof List) { - printed = this.#list(v); - } else if (v instanceof CustomType) { - printed = this.#customType(v); - } else if (v instanceof Dict) { - printed = this.#dict(v); - } else if (v instanceof Set) { - return `//js(Set(${[...v].map((v) => this.inspect(v)).join(", ")}))`; - } else { - printed = this.#object(v); - } - this.#references.delete(v); - return printed; - } - - #object(v) { - const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; - const props = []; - for (const k of Object.keys(v)) { - props.push(`${this.inspect(k)}: ${this.inspect(v[k])}`); - } - const body = props.length ? " " + props.join(", ") + " " : ""; - const head = name === "Object" ? "" : name + " "; - return `//js(${head}{${body}})`; - } - - #dict(map) { - let body = "dict.from_list(["; - let first = true; - map.forEach((value, key) => { - if (!first) body = body + ", "; - body = body + "#(" + this.inspect(key) + ", " + this.inspect(value) + ")"; - first = false; - }); - return body + "])"; - } - - #customType(record) { - const props = Object.keys(record) - .map((label) => { - const value = this.inspect(record[label]); - return isNaN(parseInt(label)) ? `${label}: ${value}` : value; - }) - .join(", "); - return props - ? `${record.constructor.name}(${props})` - : record.constructor.name; - } - - #list(list) { - if (list instanceof Empty) { - return "[]"; - } - - let char_out = 'charlist.from_string("'; - let list_out = "["; - - let current = list; - while (current instanceof NonEmpty) { - let element = current.head; - current = current.tail; - - if (list_out !== "[") { - list_out += ", "; - } - list_out += this.inspect(element); - - if (char_out) { - if (Number.isInteger(element) && element >= 32 && element <= 126) { - char_out += String.fromCharCode(element); - } else { - char_out = null; - } - } - } - - if (char_out) { - return char_out + '")'; - } else { - return list_out + "]"; - } - } - - #string(str) { - let new_str = '"'; - for (let i = 0; i < str.length; i++) { - const char = str[i]; - switch (char) { - case "\n": - new_str += "\\n"; - break; - case "\r": - new_str += "\\r"; - break; - case "\t": - new_str += "\\t"; - break; - case "\f": - new_str += "\\f"; - break; - case "\\": - new_str += "\\\\"; - break; - case '"': - new_str += '\\"'; - break; - default: - if (char < " " || (char > "~" && char < "\u{00A0}")) { - new_str += - "\\u{" + - char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + - "}"; - } else { - new_str += char; - } - } - } - new_str += '"'; - return new_str; - } - - #utfCodepoint(codepoint) { - return `//utfcodepoint(${String.fromCodePoint(codepoint.value)})`; - } - - #bit_array(bits) { - if (bits.bitSize === 0) { - return "<<>>"; - } - - let acc = "<<"; - - for (let i = 0; i < bits.byteSize - 1; i++) { - acc += bits.byteAt(i).toString(); - acc += ", "; - } - - if (bits.byteSize * 8 === bits.bitSize) { - acc += bits.byteAt(bits.byteSize - 1).toString(); - } else { - const trailingBitsCount = bits.bitSize % 8; - acc += bits.byteAt(bits.byteSize - 1) >> (8 - trailingBitsCount); - acc += `:size(${trailingBitsCount})`; - } - - acc += ">>"; - return acc; - } -} - -export function base16_encode(bit_array) { - const trailingBitsCount = bit_array.bitSize % 8; - - let result = ""; - - for (let i = 0; i < bit_array.byteSize; i++) { - let byte = bit_array.byteAt(i); - - if (i === bit_array.byteSize - 1 && trailingBitsCount !== 0) { - const unusedBitsCount = 8 - trailingBitsCount; - byte = (byte >> unusedBitsCount) << unusedBitsCount; - } - - result += byte.toString(16).padStart(2, "0").toUpperCase(); - } - - return result; -} - -export function base16_decode(string) { - const bytes = new Uint8Array(string.length / 2); - for (let i = 0; i < string.length; i += 2) { - const a = parseInt(string[i], 16); - const b = parseInt(string[i + 1], 16); - if (isNaN(a) || isNaN(b)) return new Error(Nil); - bytes[i / 2] = a * 16 + b; - } - return new Ok(new BitArray(bytes)); -} - -export function bit_array_to_int_and_size(bits) { - const trailingBitsCount = bits.bitSize % 8; - const unusedBitsCount = trailingBitsCount === 0 ? 0 : 8 - trailingBitsCount; - - return [bits.byteAt(0) >> unusedBitsCount, bits.bitSize]; -} - -export function bit_array_starts_with(bits, prefix) { - if (prefix.bitSize > bits.bitSize) { - return false; - } - - // Check any whole bytes - const byteCount = Math.trunc(prefix.bitSize / 8); - for (let i = 0; i < byteCount; i++) { - if (bits.byteAt(i) !== prefix.byteAt(i)) { - return false; - } - } - - // Check any trailing bits at the end of the prefix - if (prefix.bitSize % 8 !== 0) { - const unusedBitsCount = 8 - (prefix.bitSize % 8); - if ( - bits.byteAt(byteCount) >> unusedBitsCount !== - prefix.byteAt(byteCount) >> unusedBitsCount - ) { - return false; - } - } - - return true; -} - -export function log(x) { - // It is checked in Gleam that: - // - The input is strictly positive (x > 0) - // - This ensures that Math.log will never return NaN or -Infinity - // The function can thus safely pass the input to Math.log - // and a valid finite float will always be produced. - return Math.log(x); -} - -export function exp(x) { - return Math.exp(x); -} - -export function list_to_array(list) { - let current = list; - let array = []; - while (current instanceof NonEmpty) { - array.push(current.head); - current = current.tail; - } - return array; -} - -export function index(data, key) { - // Dictionaries and dictionary-like objects can be indexed - if (data instanceof Dict || data instanceof WeakMap || data instanceof Map) { - const token = {}; - const entry = data.get(key, token); - if (entry === token) return new Ok(new None()); - return new Ok(new Some(entry)); - } - - const key_is_int = Number.isInteger(key); - - // Only elements 0-7 of lists can be indexed, negative indices are not allowed - if (key_is_int && key >= 0 && key < 8 && data instanceof List) { - let i = 0; - for (const value of data) { - if (i === key) return new Ok(new Some(value)); - i++; - } - return new Error("Indexable"); - } - - // Arrays and objects can be indexed - if ( - (key_is_int && Array.isArray(data)) || - (data && typeof data === "object") || - (data && Object.getPrototypeOf(data) === Object.prototype) - ) { - if (key in data) return new Ok(new Some(data[key])); - return new Ok(new None()); - } - - return new Error(key_is_int ? "Indexable" : "Dict"); -} - -export function list(data, decode, pushPath, index, emptyList) { - if (!(data instanceof List || Array.isArray(data))) { - const error = new DecodeError("List", classify(data), emptyList); - return [emptyList, List.fromArray([error])]; - } - - const decoded = []; - - for (const element of data) { - const layer = decode(element); - const [out, errors] = layer; - - if (errors instanceof NonEmpty) { - const [_, errors] = pushPath(layer, index.toString()); - return [emptyList, errors]; - } - decoded.push(out); - index++; - } - - return [List.fromArray(decoded), emptyList]; -} - -export function dict(data) { - if (data instanceof Dict) { - return new Ok(data); - } - if (data instanceof Map || data instanceof WeakMap) { - return new Ok(Dict.fromMap(data)); - } - if (data == null) { - return new Error("Dict"); - } - if (typeof data !== "object") { - return new Error("Dict"); - } - const proto = Object.getPrototypeOf(data); - if (proto === Object.prototype || proto === null) { - return new Ok(Dict.fromObject(data)); - } - return new Error("Dict"); -} - -export function bit_array(data) { - if (data instanceof BitArray) return new Ok(data); - if (data instanceof Uint8Array) return new Ok(new BitArray(data)); - return new Error(new BitArray(new Uint8Array())); -} - -export function float(data) { - if (typeof data === "number") return new Ok(data); - return new Error(0.0); -} - -export function int(data) { - if (Number.isInteger(data)) return new Ok(data); - return new Error(0); -} - -export function string(data) { - if (typeof data === "string") return new Ok(data); - return new Error(""); -} - -export function is_null(data) { - return data === null || data === undefined; -} diff --git a/build/packages/gleam_time/README.md b/build/packages/gleam_time/README.md deleted file mode 100644 index 4c4360f..0000000 --- a/build/packages/gleam_time/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# Time 🕰️ - -Work with time in Gleam! - -[![Package Version](https://img.shields.io/hexpm/v/gleam_time)](https://hex.pm/packages/gleam_time) -[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/gleam_time/) - -```sh -gleam add gleam_time -``` - -This package is the foundation of all code that works with time in Gleam. If -your program uses time then you should be using the types in this package, and -you might choose to add other packages to provide additional functionality. - -## How not to have time related bugs - -Time is famously difficult to work with! It's a very complex area, and there's -many approaches that seem reasonable or obvious, but then commonly result in -bugs. This package is carefully designed to help you avoid these problems, so -it is wise to read this documentation before continuing. - -It is important to understand there are two main ways that time is represented: - -- **Calendar time**: This is how humans commonly think and communicate about - time. For example, "10pm on the 5th of January". This is easy for a human to - read, but is it typically ambiguous and hard to work with! 10pm in - Killorglin, Ireland is not the same point in time as 10pm in Harare, - Zimbabwe. The exact meaning of calendar time depends on daylight savings - time, leap years, leap seconds, and continuously changing national and - political declarations. To make calendar time unambiguous you will need to - know what time zone it is for, and to have an up-to-date time zone database. - -- **Epoch time**: Epoch time is defined as an exact amount of since some fixed - point in time. It is always unambiguous as is not impacted by geopolitics, - time zones, etc. It is efficient for computers to work with, and it is less - likely to result in buggy code. - -In this package epoch time is provided by the `gleam/time/timestamp` module, -and calendar time is provided by the `gleam/time/calendar` module. - -Time zone information has to be loaded from elsewhere, but which approch is -best will depend on your application. User interfaces may want to read current -time zone information from the user's web browser or operating system. Server -side applications may want to embed or downloads a full copy of the time zone -database and then ask clients which time zone they want to use. - -For an entertaining overview of some of the problems of calendar time view this -video: ["The Problem with Time & Timezones" by Computerphile](https://www.youtube.com/watch?v=-5wpm-gesOY). - -### Which time representation should you use? - -> **tldr**: Use `gleam/time/timestamp`. - -The longer, more detailed answer: - -- Default to `gleam/time/timestamp`, which is epoch time. It is - unambiguous, efficient, and significantly less likely to result in logic - bugs. - -- When writing time to a database or other data storage use epoch time, - using whatever epoch format it supports. For example, PostgreSQL - `timestamp` and `timestampz` are both epoch time, and `timestamp` is - preferred as it is more straightforward to use as your application is - also using epoch time. - -- When communicating with other computer systems continue to use epoch - time. For example, when sending times to another program you could - encode time as UNIX timestamps (seconds since 00:00:00 UTC on 1 January - 1970). - -- When communicating with humans use epoch time internally, and convert - to-and-from calendar time at the last moment, when iteracting with the - human user. It may also help the users to also show the time as a fuzzy - duration from the present time, such as "about 4 days ago". - -- When representing "fuzzy" human time concepts that don't exact periods - in time, such as "one month" (varies depending on which month, which - year, and in which time zone) and "Christmas Day" (varies depending on - which year and time zone) then use calendar time. - -Any time you do use calendar time you should be extra careful! It is very -easy to make mistake with. Avoid it where possible. - -## Special thanks - -This package was created with great help from several kind contributors. In -alphabetical order: - -- [Hayleigh Thompson](https://github.com/hayleigh-dot-dev) -- [John Strunk](https://github.com/jrstrunk) -- [Ryan Moore](https://github.com/mooreryan) -- [Shayan Javani](https://github.com/massivefermion) - -These non-Gleam projects where highly influential on the design of this -package: - -- Elm's `elm/time` package. -- Go's `time` module. -- Rust's `std::time` module. -- Elixir's standard library time modules and `timex` package. diff --git a/build/packages/gleam_time/gleam.toml b/build/packages/gleam_time/gleam.toml deleted file mode 100644 index 90f4a22..0000000 --- a/build/packages/gleam_time/gleam.toml +++ /dev/null @@ -1,19 +0,0 @@ -name = "gleam_time" -version = "1.6.0" -description = "Work with time in Gleam!" -gleam = ">= 1.11.0" -licences = ["Apache-2.0"] -repository = { type = "github", user = "gleam-lang", repo = "time" } -links = [ - { title = "Sponsor", href = "https://github.com/sponsors/lpil" } -] - -[dependencies] -gleam_stdlib = ">= 0.44.0 and < 2.0.0" - -[dev-dependencies] -gleeunit = ">= 1.0.0 and < 2.0.0" -qcheck = ">= 1.0.0 and < 2.0.0" -simplifile = ">= 2.2.0 and < 3.0.0" -gleam_regexp = ">= 1.0.0 and < 2.0.0" -prng = ">= 4.0.1 and < 5.0.0" diff --git a/build/packages/gleam_time/include/gleam@time@calendar_Date.hrl b/build/packages/gleam_time/include/gleam@time@calendar_Date.hrl deleted file mode 100644 index b746fad..0000000 --- a/build/packages/gleam_time/include/gleam@time@calendar_Date.hrl +++ /dev/null @@ -1,5 +0,0 @@ --record(date, { - year :: integer(), - month :: gleam@time@calendar:month(), - day :: integer() -}). diff --git a/build/packages/gleam_time/include/gleam@time@calendar_TimeOfDay.hrl b/build/packages/gleam_time/include/gleam@time@calendar_TimeOfDay.hrl deleted file mode 100644 index b5a103d..0000000 --- a/build/packages/gleam_time/include/gleam@time@calendar_TimeOfDay.hrl +++ /dev/null @@ -1,6 +0,0 @@ --record(time_of_day, { - hours :: integer(), - minutes :: integer(), - seconds :: integer(), - nanoseconds :: integer() -}). diff --git a/build/packages/gleam_time/include/gleam@time@duration_Duration.hrl b/build/packages/gleam_time/include/gleam@time@duration_Duration.hrl deleted file mode 100644 index 5477733..0000000 --- a/build/packages/gleam_time/include/gleam@time@duration_Duration.hrl +++ /dev/null @@ -1 +0,0 @@ --record(duration, {seconds :: integer(), nanoseconds :: integer()}). diff --git a/build/packages/gleam_time/include/gleam@time@timestamp_Timestamp.hrl b/build/packages/gleam_time/include/gleam@time@timestamp_Timestamp.hrl deleted file mode 100644 index b05bafe..0000000 --- a/build/packages/gleam_time/include/gleam@time@timestamp_Timestamp.hrl +++ /dev/null @@ -1 +0,0 @@ --record(timestamp, {seconds :: integer(), nanoseconds :: integer()}). diff --git a/build/packages/gleam_time/src/gleam/time/calendar.gleam b/build/packages/gleam_time/src/gleam/time/calendar.gleam deleted file mode 100644 index ac81c11..0000000 --- a/build/packages/gleam_time/src/gleam/time/calendar.gleam +++ /dev/null @@ -1,346 +0,0 @@ -//// This module is for working with the Gregorian calendar, established by -//// Pope Gregory XIII in 1582! -//// -//// ## When should you use this module? -//// -//// > **tldr:** You probably want to use [`gleam/time/timestamp`](./timestamp.html) -//// > instead! -//// -//// Calendar time is difficult to work with programmatically, it is the source -//// of most time-related bugs in software. Compared to _epoch time_, which the -//// `gleam/time/timestamp` module uses, there are many disadvantages to -//// calendar time: -//// -//// - They are ambiguous if you don't know what time-zone is being used. -//// -//// - A time-zone database is required to understand calendar time even when -//// you have the time zone. These are large and your program has to -//// continously be updated as new versions of the database are published. -//// -//// - The type permits invalid states. e.g. `days` could be set to the number -//// 32, but this should not be possible! -//// -//// - There is not a single unique canonical value for each point in time, -//// thanks to time zones. Two different `Date` + `TimeOfDay` value pairs -//// could represent the same point in time. This means that you can't check -//// for time equality with `==` when using calendar types. -//// -//// - They are computationally complex, using a more memory to represent and -//// requiring a lot more CPU time to manipulate. -//// -//// There are also advantages to calendar time: -//// -//// - Calendar time is how human's talk about time, so if you want to show a -//// time or take a time from a human user then calendar time will make it -//// easier for them. -//// -//// - They can represent more abstract time periods such as "New Year's Day". -//// This may seem like an exact window of time at first, but really the -//// definition of "New Year's Day" is more fuzzy than that. When it starts -//// and ends will depend where in the world you are, so if you want to refer -//// to a day as a global concept instead of a fixed window of time for that -//// day in a specific location, then calendar time can represent that. -//// -//// So when should you use calendar time? These are our recommendations: -//// -//// - Default to `gleam/time/timestamp`, which is epoch time. It is -//// unambiguous, efficient, and significantly less likely to result in logic -//// bugs. -//// -//// - When writing time to a database or other data storage use epoch time, -//// using whatever epoch format it supports. For example, PostgreSQL -//// `timestamp` and `timestampz` are both epoch time, and `timestamp` is -//// preferred as it is more straightforward to use as your application is -//// also using epoch time. -//// -//// - When communicating with other computer systems continue to use epoch -//// time. For example, when sending times to another program you could -//// encode time as UNIX timestamps (seconds since 00:00:00 UTC on 1 January -//// 1970). -//// -//// - When communicating with humans use epoch time internally, and convert -//// to-and-from calendar time at the last moment, when iteracting with the -//// human user. It may also help the users to also show the time as a fuzzy -//// duration from the present time, such as "about 4 days ago". -//// -//// - When representing "fuzzy" human time concepts that don't exact periods -//// in time, such as "one month" (varies depending on which month, which -//// year, and in which time zone) and "Christmas Day" (varies depending on -//// which year and time zone) then use calendar time. -//// -//// Any time you do use calendar time you should be extra careful! It is very -//// easy to make mistake with. Avoid it where possible. -//// -//// ## Time zone offsets -//// -//// This package includes the `utc_offset` value and the `local_offset` -//// function, which are the offset for the UTC time zone and get the time -//// offset the computer running the program is configured to respectively. -//// -//// If you need to use other offsets in your program then you will need to get -//// them from somewhere else, such as from a package which loads the -//// [IANA Time Zone Database](https://www.iana.org/time-zones), or from the -//// website visitor's web browser, which your frontend can send for you. -//// -//// ## Use in APIs -//// -//// If you are making an API such as a HTTP JSON API you are encouraged to use -//// Unix timestamps instead of calendar times. - -import gleam/int -import gleam/order.{type Order} -import gleam/time/duration - -/// The Gregorian calendar date. Ambiguous without a time zone. -/// -/// Prefer to represent your time using the `Timestamp` type, and convert it -/// only to calendar types when you need to display them. See the documentation -/// for this module for more information. -/// -pub type Date { - Date(year: Int, month: Month, day: Int) -} - -/// The time of day. Ambiguous without a date and time zone. -/// -pub type TimeOfDay { - TimeOfDay(hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -} - -/// The 12 months of the year. -pub type Month { - January - February - March - April - May - June - July - August - September - October - November - December -} - -/// The offset for the [Coordinated Universal Time (UTC)](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) -/// time zone. -/// -/// The utc zone has no time adjustments, it is always zero. It never observes -/// daylight-saving time and it never shifts around based on political -/// restructuring. -/// -pub const utc_offset = duration.empty - -/// Get the offset for the computer's currently configured time zone. -/// -/// Note this may not be the time zone that is correct to use for your user. -/// For example, if you are making a web application that runs on a server you -/// want _their_ computer's time zone, not yours. -/// -/// This is the _current local_ offset, not the current local time zone. This -/// means that while it will result in the expected outcome for the current -/// time, it may result in unexpected output if used with other timestamps. For -/// example: a timestamp that would locally be during daylight savings time if -/// is it not currently daylight savings time when this function is called. -/// -pub fn local_offset() -> duration.Duration { - duration.seconds(local_time_offset_seconds()) -} - -@external(erlang, "gleam_time_ffi", "local_time_offset_seconds") -@external(javascript, "../../gleam_time_ffi.mjs", "local_time_offset_seconds") -fn local_time_offset_seconds() -> Int - -/// Returns the English name for a month. -/// -/// # Examples -/// -/// ```gleam -/// month_to_string(April) -/// // -> "April" -/// ``` -pub fn month_to_string(month: Month) -> String { - case month { - January -> "January" - February -> "February" - March -> "March" - April -> "April" - May -> "May" - June -> "June" - July -> "July" - August -> "August" - September -> "September" - October -> "October" - November -> "November" - December -> "December" - } -} - -/// Returns the number for the month, where January is 1 and December is 12. -/// -/// # Examples -/// -/// ```gleam -/// month_to_int(January) -/// // -> 1 -/// ``` -pub fn month_to_int(month: Month) -> Int { - case month { - January -> 1 - February -> 2 - March -> 3 - April -> 4 - May -> 5 - June -> 6 - July -> 7 - August -> 8 - September -> 9 - October -> 10 - November -> 11 - December -> 12 - } -} - -/// Returns the month for a given number, where January is 1 and December is 12. -/// -/// # Examples -/// -/// ```gleam -/// month_from_int(1) -/// // -> Ok(January) -/// ``` -pub fn month_from_int(month: Int) -> Result(Month, Nil) { - case month { - 1 -> Ok(January) - 2 -> Ok(February) - 3 -> Ok(March) - 4 -> Ok(April) - 5 -> Ok(May) - 6 -> Ok(June) - 7 -> Ok(July) - 8 -> Ok(August) - 9 -> Ok(September) - 10 -> Ok(October) - 11 -> Ok(November) - 12 -> Ok(December) - _ -> Error(Nil) - } -} - -/// Checks if a given date is valid. -/// -/// This function properly accounts for leap years when validating February days. -/// A leap year occurs every 4 years, except for years divisible by 100, -/// unless they are also divisible by 400. -/// -/// # Examples -/// -/// ```gleam -/// is_valid_date(Date(2023, April, 15)) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_valid_date(Date(2023, April, 31)) -/// // -> False -/// ``` -/// -/// ```gleam -/// is_valid_date(Date(2024, February, 29)) -/// // -> True (2024 is a leap year) -/// ``` -/// -pub fn is_valid_date(date: Date) -> Bool { - let Date(year:, month:, day:) = date - case day < 1 { - True -> False - False -> - case month { - January | March | May | July | August | October | December -> day <= 31 - April | June | September | November -> day <= 30 - February -> { - let max_february_days = case is_leap_year(year) { - True -> 29 - False -> 28 - } - day <= max_february_days - } - } - } -} - -/// Determines if a given year is a leap year. -/// -/// A leap year occurs every 4 years, except for years divisible by 100, -/// unless they are also divisible by 400. -/// -/// # Examples -/// -/// ```gleam -/// is_leap_year(2024) -/// // -> True -/// ``` -/// -/// ```gleam -/// is_leap_year(2023) -/// // -> False -/// ``` -/// -pub fn is_leap_year(year: Int) -> Bool { - case year % 400 == 0 { - True -> True - False -> - case year % 100 == 0 { - True -> False - False -> year % 4 == 0 - } - } -} - -/// Checks if a time of day is valid. -/// -/// Validates that hours are 0-23, minutes are 0-59, seconds are 0-59, -/// and nanoseconds are 0-999,999,999. -/// -/// # Examples -/// -/// ```gleam -/// is_valid_time_of_day(TimeOfDay(12, 30, 45, 123456789)) -/// // -> True -/// ``` -/// -pub fn is_valid_time_of_day(time: TimeOfDay) -> Bool { - let TimeOfDay(hours:, minutes:, seconds:, nanoseconds:) = time - - hours >= 0 - && hours <= 23 - && minutes >= 0 - && minutes <= 59 - && seconds >= 0 - && seconds <= 59 - && nanoseconds >= 0 - && nanoseconds <= 999_999_999 -} - -/// Naively compares two dates without any time zone information, returning an -/// order. -/// -/// ## Correctness -/// -/// This function compares dates without any time zone information, only using -/// the rules for the gregorian calendar. This is typically sufficient, but be -/// aware that in reality some time zones will change their calendar date -/// occasionally. This can result in days being skipped, out of order, or -/// happening multiple times. -/// -/// If you need real-world correct time ordering then use the -/// `gleam/time/timestamp` module instead. -/// -pub fn naive_date_compare(one: Date, other: Date) -> Order { - int.compare(one.year, other.year) - |> order.lazy_break_tie(fn() { - int.compare(month_to_int(one.month), month_to_int(other.month)) - }) - |> order.lazy_break_tie(fn() { int.compare(one.day, other.day) }) -} diff --git a/build/packages/gleam_time/src/gleam/time/duration.gleam b/build/packages/gleam_time/src/gleam/time/duration.gleam deleted file mode 100644 index a3b7483..0000000 --- a/build/packages/gleam_time/src/gleam/time/duration.gleam +++ /dev/null @@ -1,297 +0,0 @@ -import gleam/bool -import gleam/int -import gleam/order -import gleam/string - -/// An amount of time, with up to nanosecond precision. -/// -/// This type does not represent calendar periods such as "1 month" or "2 -/// days". Those periods will be different lengths of time depending on which -/// month or day they apply to. For example, January is longer than February. -/// A different type should be used for calendar periods. -/// -pub opaque type Duration { - // When compiling to JavaScript ints have limited precision and size. This - // means that if we were to store the the timestamp in a single int the - // duration would not be able to represent very large or small durations. - // Durations are instead represented as a number of seconds and a number of - // nanoseconds. - // - // If you have manually adjusted the seconds and nanoseconds values the - // `normalise` function can be used to ensure the time is represented the - // intended way, with `nanoseconds` being positive and less than 1 second. - // - // The duration is the sum of the seconds and the nanoseconds. - Duration(seconds: Int, nanoseconds: Int) -} - -/// A division of time. -/// -/// Note that not all months and years are the same length, so a reasonable -/// average length is used by this module. -/// -pub type Unit { - Nanosecond - /// 1000 nanoseconds. - Microsecond - /// 1000 microseconds. - Millisecond - /// 1000 milliseconds. - Second - /// 60 seconds. - Minute - /// 60 minutes. - Hour - /// 24 hours. - Day - /// 7 days. - Week - /// About 30.4375 days. Real calendar months vary in length. - Month - /// About 365.25 days. Real calendar years vary in length. - Year -} - -/// Convert a duration to a number of the largest number of a unit, serving as -/// a rough description of the duration that a human can understand. -/// -/// The size used for each unit are described in the documentation for the -/// `Unit` type. -/// -/// ```gleam -/// seconds(125) -/// |> approximate -/// // -> #(2, Minute) -/// ``` -/// -/// This function rounds _towards zero_. This means that if a duration is just -/// short of 2 days then it will approximate to 1 day. -/// -/// ```gleam -/// hours(47) -/// |> approximate -/// // -> #(1, Day) -/// ``` -/// -pub fn approximate(duration: Duration) -> #(Int, Unit) { - let Duration(seconds: s, nanoseconds: ns) = duration - let minute = 60 - let hour = minute * 60 - let day = hour * 24 - let week = day * 7 - let year = day * 365 + hour * 6 - let month = year / 12 - let microsecond = 1000 - let millisecond = microsecond * 1000 - case Nil { - _ if s < 0 -> { - let #(amount, unit) = Duration(-s, -ns) |> normalise |> approximate - #(-amount, unit) - } - _ if s >= year -> #(s / year, Year) - _ if s >= month -> #(s / month, Month) - _ if s >= week -> #(s / week, Week) - _ if s >= day -> #(s / day, Day) - _ if s >= hour -> #(s / hour, Hour) - _ if s >= minute -> #(s / minute, Minute) - _ if s > 0 -> #(s, Second) - _ if ns >= millisecond -> #(ns / millisecond, Millisecond) - _ if ns >= microsecond -> #(ns / microsecond, Microsecond) - _ -> #(ns, Nanosecond) - } -} - -/// Ensure the duration is represented with `nanoseconds` being positive and -/// less than 1 second. -/// -/// This function does not change the amount of time that the duratoin refers -/// to, it only adjusts the values used to represent the time. -/// -fn normalise(duration: Duration) -> Duration { - let multiplier = 1_000_000_000 - let nanoseconds = duration.nanoseconds % multiplier - let overflow = duration.nanoseconds - nanoseconds - let seconds = duration.seconds + overflow / multiplier - case nanoseconds >= 0 { - True -> Duration(seconds, nanoseconds) - False -> Duration(seconds - 1, multiplier + nanoseconds) - } -} - -/// Compare one duration to another, indicating whether the first spans a -/// larger amount of time (and so is greater) or smaller amount of time (and so -/// is lesser) than the second. -/// -/// # Examples -/// -/// ```gleam -/// compare(seconds(1), seconds(2)) -/// // -> order.Lt -/// ``` -/// -/// Whether a duration is negative or positive doesn't matter for comparing -/// them, only the amount of time spanned matters. -/// -/// ```gleam -/// compare(seconds(-2), seconds(1)) -/// // -> order.Gt -/// ``` -/// -pub fn compare(left: Duration, right: Duration) -> order.Order { - let parts = fn(x: Duration) { - case x.seconds >= 0 { - True -> #(x.seconds, x.nanoseconds) - False -> #(x.seconds * -1 - 1, 1_000_000_000 - x.nanoseconds) - } - } - let #(ls, lns) = parts(left) - let #(rs, rns) = parts(right) - int.compare(ls, rs) - |> order.break_tie(int.compare(lns, rns)) -} - -/// Calculate the difference between two durations. -/// -/// This is effectively substracting the first duration from the second. -/// -/// # Examples -/// -/// ```gleam -/// difference(seconds(1), seconds(5)) -/// // -> seconds(4) -/// ``` -/// -pub fn difference(left: Duration, right: Duration) -> Duration { - Duration(right.seconds - left.seconds, right.nanoseconds - left.nanoseconds) - |> normalise -} - -/// Add two durations together. -/// -/// # Examples -/// -/// ```gleam -/// add(seconds(1), seconds(5)) -/// // -> seconds(6) -/// ``` -/// -pub fn add(left: Duration, right: Duration) -> Duration { - Duration(left.seconds + right.seconds, left.nanoseconds + right.nanoseconds) - |> normalise -} - -/// Convert the duration to an [ISO8601][1] formatted duration string. -/// -/// The ISO8601 duration format is ambiguous without context due to months and -/// years having different lengths, and because of leap seconds. This function -/// encodes the duration as days, hours, and seconds without any leap seconds. -/// Be sure to take this into account when using the duration strings. -/// -/// [1]: https://en.wikipedia.org/wiki/ISO_8601#Durations -/// -pub fn to_iso8601_string(duration: Duration) -> String { - use <- bool.guard(duration == empty, "PT0S") - let split = fn(total, limit) { - let amount = total % limit - let remainder = { total - amount } / limit - #(amount, remainder) - } - let #(seconds, rest) = split(duration.seconds, 60) - let #(minutes, rest) = split(rest, 60) - let #(hours, rest) = split(rest, 24) - let days = rest - let add = fn(out, value, unit) { - case value { - 0 -> out - _ -> out <> int.to_string(value) <> unit - } - } - let output = - "P" - |> add(days, "D") - |> string.append("T") - |> add(hours, "H") - |> add(minutes, "M") - case seconds, duration.nanoseconds { - 0, 0 -> output - _, 0 -> output <> int.to_string(seconds) <> "S" - _, _ -> { - let f = nanosecond_digits(duration.nanoseconds, 0, "") - output <> int.to_string(seconds) <> "." <> f <> "S" - } - } -} - -fn nanosecond_digits(n: Int, position: Int, acc: String) -> String { - case position { - 9 -> acc - _ if acc == "" && n % 10 == 0 -> { - nanosecond_digits(n / 10, position + 1, acc) - } - _ -> { - let acc = int.to_string(n % 10) <> acc - nanosecond_digits(n / 10, position + 1, acc) - } - } -} - -/// Create a duration of a number of seconds. -pub fn seconds(amount: Int) -> Duration { - Duration(amount, 0) -} - -/// Create a duration of a number of minutes. -pub fn minutes(amount: Int) -> Duration { - seconds(amount * 60) -} - -/// Create a duration of a number of hours. -pub fn hours(amount: Int) -> Duration { - seconds(amount * 60 * 60) -} - -/// Create a duration of a number of milliseconds. -pub fn milliseconds(amount: Int) -> Duration { - let remainder = amount % 1000 - let overflow = amount - remainder - let nanoseconds = remainder * 1_000_000 - let seconds = overflow / 1000 - Duration(seconds, nanoseconds) - |> normalise -} - -/// Create a duration of a number of nanoseconds. -/// -/// # JavaScript int limitations -/// -/// Remember that JavaScript can only perfectly represent ints between positive -/// and negative 9,007,199,254,740,991! If you use a single call to this -/// function to create durations larger than that number of nanoseconds then -/// you will likely not get exactly the value you expect. Use `seconds` and -/// `milliseconds` as much as possible for large durations. -/// -pub fn nanoseconds(amount: Int) -> Duration { - Duration(0, amount) - |> normalise -} - -/// Convert the duration to a number of seconds. -/// -/// There may be some small loss of precision due to `Duration` being -/// nanosecond accurate and `Float` not being able to represent this. -/// -pub fn to_seconds(duration: Duration) -> Float { - let seconds = int.to_float(duration.seconds) - let nanoseconds = int.to_float(duration.nanoseconds) - seconds +. { nanoseconds /. 1_000_000_000.0 } -} - -/// Convert the duration to a number of seconds and nanoseconds. There is no -/// loss of precision with this conversion on any target. -/// -pub fn to_seconds_and_nanoseconds(duration: Duration) -> #(Int, Int) { - #(duration.seconds, duration.nanoseconds) -} - -@internal -pub const empty = Duration(0, 0) diff --git a/build/packages/gleam_time/src/gleam/time/timestamp.gleam b/build/packages/gleam_time/src/gleam/time/timestamp.gleam deleted file mode 100644 index 02fa890..0000000 --- a/build/packages/gleam_time/src/gleam/time/timestamp.gleam +++ /dev/null @@ -1,899 +0,0 @@ -//// Welcome to the timestamp module! This module and its `Timestamp` type are -//// what you will be using most commonly when working with time in Gleam. -//// -//// A timestamp represents a moment in time, represented as an amount of time -//// since the calendar time 00:00:00 UTC on 1 January 1970, also known as the -//// _Unix epoch_. -//// -//// # Wall clock time and monotonicity -//// -//// Time is very complicated, especially on computers! While they generally do -//// a good job of keeping track of what the time is, computers can get -//// out-of-sync and start to report a time that is too late or too early. Most -//// computers use "network time protocol" to tell each other what they think -//// the time is, and computers that realise they are running too fast or too -//// slow will adjust their clock to correct it. When this happens it can seem -//// to your program that the current time has changed, and it may have even -//// jumped backwards in time! -//// -//// This measure of time is called _wall clock time_, and it is what people -//// commonly think of when they think of time. It is important to be aware that -//// it can go backwards, and your program must not rely on it only ever going -//// forwards at a steady rate. For example, for tracking what order events happen -//// in. -//// -//// This module uses wall clock time. If your program needs time values to always -//// increase you will need a _monotonic_ time instead. It's uncommon that you -//// would need monotonic time, one example might be if you're making a -//// benchmarking framework. -//// -//// The exact way that time works will depend on what runtime you use. The -//// Erlang documentation on time has a lot of detail about time generally as well -//// as how it works on the BEAM, it is worth reading. -//// . -//// -//// # Converting to local calendar time -//// -//// Timestamps don't take into account time zones, so a moment in time will -//// have the same timestamp value regardless of where you are in the world. To -//// convert them to local time you will need to know the offset for the time -//// zone you wish to use, likely from a time zone database. See the -//// `gleam/time/calendar` module for more information. -//// - -import gleam/bit_array -import gleam/float -import gleam/int -import gleam/list -import gleam/order -import gleam/result -import gleam/string -import gleam/time/calendar -import gleam/time/duration.{type Duration} - -const seconds_per_day: Int = 86_400 - -const seconds_per_hour: Int = 3600 - -const seconds_per_minute: Int = 60 - -const nanoseconds_per_second: Int = 1_000_000_000 - -/// The `:` character as a byte -const byte_colon: Int = 0x3A - -/// The `-` character as a byte -const byte_minus: Int = 0x2D - -/// The `0` character as a byte -const byte_zero: Int = 0x30 - -/// The `9` character as a byte -const byte_nine: Int = 0x39 - -/// The `t` character as a byte -const byte_t_lowercase: Int = 0x74 - -/// The `T` character as a byte -const byte_t_uppercase: Int = 0x54 - -/// The `T` character as a byte -const byte_space: Int = 0x20 - -/// The Julian seconds of the UNIX epoch (Julian day is 2_440_588) -const julian_seconds_unix_epoch: Int = 210_866_803_200 - -/// The main time type, which you should favour over other types such as -/// calendar time types. It is efficient, unambiguous, and it is not possible -/// to construct an invalid timestamp. -/// -/// The most common situation in which you may need a different time data -/// structure is when you need to display time to human for them to read. When -/// you need to do this convert the timestamp to calendar time when presenting -/// it, but internally always keep the time as a timestamp. -/// -pub opaque type Timestamp { - // When compiling to JavaScript ints have limited precision and size. This - // means that if we were to store the the timestamp in a single int the - // timestamp would not be able to represent times far in the future or in the - // past, or distinguish between two times that are close together. Timestamps - // are instead represented as a number of seconds and a number of nanoseconds. - // - // If you have manually adjusted the seconds and nanoseconds values the - // `normalise` function can be used to ensure the time is represented the - // intended way, with `nanoseconds` being positive and less than 1 second. - // - // The timestamp is the sum of the seconds and the nanoseconds. - Timestamp(seconds: Int, nanoseconds: Int) -} - -/// The epoch of Unix time, which is 00:00:00 UTC on 1 January 1970. -pub const unix_epoch = Timestamp(0, 0) - -/// Ensure the time is represented with `nanoseconds` being positive and less -/// than 1 second. -/// -/// This function does not change the time that the timestamp refers to, it -/// only adjusts the values used to represent the time. -/// -fn normalise(timestamp: Timestamp) -> Timestamp { - let multiplier = 1_000_000_000 - let nanoseconds = timestamp.nanoseconds % multiplier - let overflow = timestamp.nanoseconds - nanoseconds - let seconds = timestamp.seconds + overflow / multiplier - case nanoseconds >= 0 { - True -> Timestamp(seconds, nanoseconds) - False -> Timestamp(seconds - 1, multiplier + nanoseconds) - } -} - -/// Compare one timestamp to another, indicating whether the first is further -/// into the future (greater) or further into the past (lesser) than the -/// second. -/// -/// # Examples -/// -/// ```gleam -/// compare(from_unix_seconds(1), from_unix_seconds(2)) -/// // -> order.Lt -/// ``` -/// -pub fn compare(left: Timestamp, right: Timestamp) -> order.Order { - order.break_tie( - int.compare(left.seconds, right.seconds), - int.compare(left.nanoseconds, right.nanoseconds), - ) -} - -/// Get the current system time. -/// -/// Note this time is not unique or monotonic, it could change at any time or -/// even go backwards! The exact behaviour will depend on the runtime used. See -/// the module documentation for more information. -/// -/// On Erlang this uses [`erlang:system_time/1`][1]. On JavaScript this uses -/// [`Date.now`][2]. -/// -/// [1]: https://www.erlang.org/doc/apps/erts/erlang#system_time/1 -/// [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now -/// -pub fn system_time() -> Timestamp { - let #(seconds, nanoseconds) = get_system_time() - normalise(Timestamp(seconds, nanoseconds)) -} - -@external(erlang, "gleam_time_ffi", "system_time") -@external(javascript, "../../gleam_time_ffi.mjs", "system_time") -fn get_system_time() -> #(Int, Int) - -/// Calculate the difference between two timestamps. -/// -/// This is effectively substracting the first timestamp from the second. -/// -/// # Examples -/// -/// ```gleam -/// difference(from_unix_seconds(1), from_unix_seconds(5)) -/// // -> duration.seconds(4) -/// ``` -/// -pub fn difference(left: Timestamp, right: Timestamp) -> Duration { - let seconds = duration.seconds(right.seconds - left.seconds) - let nanoseconds = duration.nanoseconds(right.nanoseconds - left.nanoseconds) - duration.add(seconds, nanoseconds) -} - -/// Add a duration to a timestamp. -/// -/// # Examples -/// -/// ```gleam -/// add(from_unix_seconds(1000), duration.seconds(5)) -/// // -> from_unix_seconds(1005) -/// ``` -/// -pub fn add(timestamp: Timestamp, duration: Duration) -> Timestamp { - let #(seconds, nanoseconds) = duration.to_seconds_and_nanoseconds(duration) - Timestamp(timestamp.seconds + seconds, timestamp.nanoseconds + nanoseconds) - |> normalise -} - -/// Convert a timestamp to a RFC 3339 formatted time string, with an offset -/// supplied as an additional argument. -/// -/// The output of this function is also ISO 8601 compatible so long as the -/// offset not negative. Offsets have at-most minute precision, so an offset -/// with higher precision will be rounded to the nearest minute. -/// -/// If you are making an API such as a HTTP JSON API you are encouraged to use -/// Unix timestamps instead of this format or ISO 8601. Unix timestamps are a -/// better choice as they don't contain offset information. Consider: -/// -/// - UTC offsets are not time zones. This does not and cannot tell us the time -/// zone in which the date was recorded. So what are we supposed to do with -/// this information? -/// - Users typically want dates formatted according to their local time zone. -/// What if the provided UTC offset is different from the current user's time -/// zone? What are we supposed to do with it then? -/// - Despite it being useless (or worse, a source of bugs), the UTC offset -/// creates a larger payload to transfer. -/// -/// They also uses more memory than a unix timestamp. The way they are better -/// than Unix timestamp is that it is easier for a human to read them, but -/// this is a hinderance that tooling can remedy, and APIs are not primarily -/// for humans. -/// -/// # Examples -/// -/// ```gleam -/// timestamp.from_unix_seconds_and_nanoseconds(1000, 123_000_000) -/// |> to_rfc3339(calendar.utc_offset) -/// // -> "1970-01-01T00:16:40.123Z" -/// ``` -/// -/// ```gleam -/// timestamp.from_unix_seconds(1000) -/// |> to_rfc3339(duration.seconds(3600)) -/// // -> "1970-01-01T01:16:40+01:00" -/// ``` -/// -pub fn to_rfc3339(timestamp: Timestamp, offset: Duration) -> String { - let offset = duration_to_minutes(offset) - let #(years, months, days, hours, minutes, seconds) = - to_calendar_from_offset(timestamp, offset) - - let offset_minutes = modulo(offset, 60) - let offset_hours = int.absolute_value(floored_div(offset, 60.0)) - - let n2 = pad_digit(_, to: 2) - let n4 = pad_digit(_, to: 4) - let out = "" - let out = out <> n4(years) <> "-" <> n2(months) <> "-" <> n2(days) - let out = out <> "T" - let out = out <> n2(hours) <> ":" <> n2(minutes) <> ":" <> n2(seconds) - let out = out <> show_second_fraction(timestamp.nanoseconds) - case int.compare(offset, 0) { - order.Eq -> out <> "Z" - order.Gt -> out <> "+" <> n2(offset_hours) <> ":" <> n2(offset_minutes) - order.Lt -> out <> "-" <> n2(offset_hours) <> ":" <> n2(offset_minutes) - } -} - -fn pad_digit(digit: Int, to desired_length: Int) -> String { - int.to_string(digit) |> string.pad_start(desired_length, "0") -} - -/// Convert a `Timestamp` to calendar time, suitable for presenting to a human -/// to read. -/// -/// If you want a machine to use the time value then you should not use this -/// function and should instead keep it as a timestamp. See the documentation -/// for the `gleam/time/calendar` module for more information. -/// -/// # Examples -/// -/// ```gleam -/// timestamp.from_unix_seconds(0) -/// |> timestamp.to_calendar(calendar.utc_offset) -/// // -> #(Date(1970, January, 1), TimeOfDay(0, 0, 0, 0)) -/// ``` -/// -pub fn to_calendar( - timestamp: Timestamp, - offset: Duration, -) -> #(calendar.Date, calendar.TimeOfDay) { - let offset = duration_to_minutes(offset) - let #(year, month, day, hours, minutes, seconds) = - to_calendar_from_offset(timestamp, offset) - let month = case month { - 1 -> calendar.January - 2 -> calendar.February - 3 -> calendar.March - 4 -> calendar.April - 5 -> calendar.May - 6 -> calendar.June - 7 -> calendar.July - 8 -> calendar.August - 9 -> calendar.September - 10 -> calendar.October - 11 -> calendar.November - _ -> calendar.December - } - let nanoseconds = timestamp.nanoseconds - let date = calendar.Date(year:, month:, day:) - let time = calendar.TimeOfDay(hours:, minutes:, seconds:, nanoseconds:) - #(date, time) -} - -fn duration_to_minutes(duration: duration.Duration) -> Int { - float.round(duration.to_seconds(duration) /. 60.0) -} - -fn to_calendar_from_offset( - timestamp: Timestamp, - offset: Int, -) -> #(Int, Int, Int, Int, Int, Int) { - let total = timestamp.seconds + { offset * 60 } - let seconds = modulo(total, 60) - let total_minutes = floored_div(total, 60.0) - let minutes = modulo(total, 60 * 60) / 60 - let hours = modulo(total, 24 * 60 * 60) / { 60 * 60 } - let #(year, month, day) = to_civil(total_minutes) - #(year, month, day, hours, minutes, seconds) -} - -/// Create a `Timestamp` from a human-readable calendar time. -/// -/// # Examples -/// -/// ```gleam -/// timestamp.from_calendar( -/// date: calendar.Date(2024, calendar.December, 25), -/// time: calendar.TimeOfDay(12, 30, 50, 0), -/// offset: calendar.utc_offset, -/// ) -/// |> timestamp.to_rfc3339(calendar.utc_offset) -/// // -> "2024-12-25T12:30:50Z" -/// ``` -/// -pub fn from_calendar( - date date: calendar.Date, - time time: calendar.TimeOfDay, - offset offset: Duration, -) -> Timestamp { - let month = case date.month { - calendar.January -> 1 - calendar.February -> 2 - calendar.March -> 3 - calendar.April -> 4 - calendar.May -> 5 - calendar.June -> 6 - calendar.July -> 7 - calendar.August -> 8 - calendar.September -> 9 - calendar.October -> 10 - calendar.November -> 11 - calendar.December -> 12 - } - from_date_time( - year: date.year, - month:, - day: date.day, - hours: time.hours, - minutes: time.minutes, - seconds: time.seconds, - second_fraction_as_nanoseconds: time.nanoseconds, - offset_seconds: float.round(duration.to_seconds(offset)), - ) -} - -fn modulo(n: Int, m: Int) -> Int { - case int.modulo(n, m) { - Ok(n) -> n - Error(_) -> 0 - } -} - -fn floored_div(numerator: Int, denominator: Float) -> Int { - let n = int.to_float(numerator) /. denominator - float.round(float.floor(n)) -} - -// Adapted from Elm's Time module -fn to_civil(minutes: Int) -> #(Int, Int, Int) { - let raw_day = floored_div(minutes, { 60.0 *. 24.0 }) + 719_468 - let era = case raw_day >= 0 { - True -> raw_day / 146_097 - False -> { raw_day - 146_096 } / 146_097 - } - let day_of_era = raw_day - era * 146_097 - let year_of_era = - { - day_of_era - - { day_of_era / 1460 } - + { day_of_era / 36_524 } - - { day_of_era / 146_096 } - } - / 365 - let year = year_of_era + era * 400 - let day_of_year = - day_of_era - - { 365 * year_of_era + { year_of_era / 4 } - { year_of_era / 100 } } - let mp = { 5 * day_of_year + 2 } / 153 - let month = case mp < 10 { - True -> mp + 3 - False -> mp - 9 - } - let day = day_of_year - { 153 * mp + 2 } / 5 + 1 - let year = case month <= 2 { - True -> year + 1 - False -> year - } - #(year, month, day) -} - -/// Converts nanoseconds into a `String` representation of fractional seconds. -/// -/// Assumes that `nanoseconds < 1_000_000_000`, which will be true for any -/// normalised timestamp. -/// -fn show_second_fraction(nanoseconds: Int) -> String { - case int.compare(nanoseconds, 0) { - // Zero fractional seconds are not shown. - order.Lt | order.Eq -> "" - order.Gt -> { - let second_fraction_part = { - nanoseconds - |> get_zero_padded_digits - |> remove_trailing_zeros - |> list.map(int.to_string) - |> string.join("") - } - - "." <> second_fraction_part - } - } -} - -/// Given a list of digits, return new list with any trailing zeros removed. -/// -fn remove_trailing_zeros(digits: List(Int)) -> List(Int) { - let reversed_digits = list.reverse(digits) - - do_remove_trailing_zeros(reversed_digits) -} - -fn do_remove_trailing_zeros(reversed_digits) { - case reversed_digits { - [] -> [] - [digit, ..digits] if digit == 0 -> do_remove_trailing_zeros(digits) - reversed_digits -> list.reverse(reversed_digits) - } -} - -/// Returns the list of digits of `number`. If the number of digits is less -/// than 9, the result is zero-padded at the front. -/// -fn get_zero_padded_digits(number: Int) -> List(Int) { - do_get_zero_padded_digits(number, [], 0) -} - -fn do_get_zero_padded_digits( - number: Int, - digits: List(Int), - count: Int, -) -> List(Int) { - case number { - number if number <= 0 && count >= 9 -> digits - number if number <= 0 -> - // Zero-pad the digits at the front until we have at least 9 digits. - do_get_zero_padded_digits(number, [0, ..digits], count + 1) - number -> { - let digit = number % 10 - let number = floored_div(number, 10.0) - do_get_zero_padded_digits(number, [digit, ..digits], count + 1) - } - } -} - -/// Parses an [RFC 3339 formatted time string][spec] into a `Timestamp`. -/// -/// [spec]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6 -/// -/// # Examples -/// -/// ```gleam -/// let assert Ok(ts) = timestamp.parse_rfc3339("1970-01-01T00:00:01Z") -/// timestamp.to_unix_seconds_and_nanoseconds(ts) -/// // -> #(1, 0) -/// ``` -/// -/// Parsing an invalid timestamp returns an error. -/// -/// ```gleam -/// let assert Error(Nil) = timestamp.parse_rfc3339("1995-10-31") -/// ``` -/// -/// ## Time zones -/// -/// It may at first seem that the RFC 3339 format includes timezone -/// information, as it can specify an offset such as `Z` or `+3`, so why does -/// this function not return calendar time with a time zone? There are multiple -/// reasons: -/// -/// - RFC 3339's timestamp format is based on calendar time, but it is -/// unambigous, so it can be converted into epoch time when being parsed. It -/// is always better to internally use epoch time to represent unambiguous -/// points in time, so we perform that conversion as a convenience and to -/// ensure that programmers with less time experience don't accidentally use -/// a less suitable time representation. -/// -/// - RFC 3339's contains _calendar time offset_ information, not time zone -/// information. This is enough to convert it to an unambiguous timestamp, -/// but it is not enough information to reliably work with calendar time. -/// Without the time zone and the time zone database it's not possible to -/// know what time period that offset is valid for, so it cannot be used -/// without risk of bugs. -/// -/// ## Behaviour details -/// -/// - Follows the grammar specified in section 5.6 Internet Date/Time Format of -/// RFC 3339 . -/// - The `T` and `Z` characters may alternatively be lower case `t` or `z`, -/// respectively. -/// - Full dates and full times must be separated by `T` or `t`. A space is also -/// permitted. -/// - Leap seconds rules are not considered. That is, any timestamp may -/// specify digts `00` - `60` for the seconds. -/// - Any part of a fractional second that cannot be represented in the -/// nanosecond precision is tructated. That is, for the time string, -/// `"1970-01-01T00:00:00.1234567899Z"`, the fractional second `.1234567899` -/// will be represented as `123_456_789` in the `Timestamp`. -/// -pub fn parse_rfc3339(input: String) -> Result(Timestamp, Nil) { - let bytes = bit_array.from_string(input) - - // Date - use #(year, bytes) <- result.try(parse_year(from: bytes)) - use bytes <- result.try(accept_byte(from: bytes, value: byte_minus)) - use #(month, bytes) <- result.try(parse_month(from: bytes)) - use bytes <- result.try(accept_byte(from: bytes, value: byte_minus)) - use #(day, bytes) <- result.try(parse_day(from: bytes, year:, month:)) - - use bytes <- result.try(accept_date_time_separator(from: bytes)) - - // Time - use #(hours, bytes) <- result.try(parse_hours(from: bytes)) - use bytes <- result.try(accept_byte(from: bytes, value: byte_colon)) - use #(minutes, bytes) <- result.try(parse_minutes(from: bytes)) - use bytes <- result.try(accept_byte(from: bytes, value: byte_colon)) - use #(seconds, bytes) <- result.try(parse_seconds(from: bytes)) - use #(second_fraction_as_nanoseconds, bytes) <- result.try( - parse_second_fraction_as_nanoseconds(from: bytes), - ) - - // Offset - use #(offset_seconds, bytes) <- result.try(parse_offset(from: bytes)) - - // Done - use Nil <- result.try(accept_empty(bytes)) - - Ok(from_date_time( - year:, - month:, - day:, - hours:, - minutes:, - seconds:, - second_fraction_as_nanoseconds:, - offset_seconds:, - )) -} - -fn parse_year(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - parse_digits(from: bytes, count: 4) -} - -fn parse_month(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - use #(month, bytes) <- result.try(parse_digits(from: bytes, count: 2)) - case 1 <= month && month <= 12 { - True -> Ok(#(month, bytes)) - False -> Error(Nil) - } -} - -fn parse_day( - from bytes: BitArray, - year year, - month month, -) -> Result(#(Int, BitArray), Nil) { - use #(day, bytes) <- result.try(parse_digits(from: bytes, count: 2)) - - use max_day <- result.try(case month { - 1 | 3 | 5 | 7 | 8 | 10 | 12 -> Ok(31) - 4 | 6 | 9 | 11 -> Ok(30) - 2 -> { - case is_leap_year(year) { - True -> Ok(29) - False -> Ok(28) - } - } - _ -> Error(Nil) - }) - - case 1 <= day && day <= max_day { - True -> Ok(#(day, bytes)) - False -> Error(Nil) - } -} - -// Implementation from RFC 3339 Appendix C -fn is_leap_year(year: Int) -> Bool { - year % 4 == 0 && { year % 100 != 0 || year % 400 == 0 } -} - -fn parse_hours(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - use #(hours, bytes) <- result.try(parse_digits(from: bytes, count: 2)) - case 0 <= hours && hours <= 23 { - True -> Ok(#(hours, bytes)) - False -> Error(Nil) - } -} - -fn parse_minutes(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - use #(minutes, bytes) <- result.try(parse_digits(from: bytes, count: 2)) - case 0 <= minutes && minutes <= 59 { - True -> Ok(#(minutes, bytes)) - False -> Error(Nil) - } -} - -fn parse_seconds(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - use #(seconds, bytes) <- result.try(parse_digits(from: bytes, count: 2)) - // Max of 60 for leap seconds. We don't bother to check if this leap second - // actually occurred in the past or not. - case 0 <= seconds && seconds <= 60 { - True -> Ok(#(seconds, bytes)) - False -> Error(Nil) - } -} - -// Truncates any part of the fraction that is beyond the nanosecond precision. -fn parse_second_fraction_as_nanoseconds(from bytes: BitArray) { - case bytes { - <<".", byte, remaining_bytes:bytes>> - if byte_zero <= byte && byte <= byte_nine - -> { - do_parse_second_fraction_as_nanoseconds( - from: <>, - acc: 0, - power: nanoseconds_per_second, - ) - } - // bytes starts with a ".", which should introduce a fraction, but it does - // not, and so it is an ill-formed input. - <<".", _:bytes>> -> Error(Nil) - // bytes does not start with a "." so there is no fraction. Call this 0 - // nanoseconds. - _ -> Ok(#(0, bytes)) - } -} - -fn do_parse_second_fraction_as_nanoseconds( - from bytes: BitArray, - acc acc: Int, - power power: Int, -) -> Result(#(Int, BitArray), a) { - // Each digit place to the left in the fractional second is 10x fewer - // nanoseconds. - let power = power / 10 - - case bytes { - <> - if byte_zero <= byte && byte <= byte_nine && power < 1 - -> { - // We already have the max precision for nanoseconds. Truncate any - // remaining digits. - do_parse_second_fraction_as_nanoseconds( - from: remaining_bytes, - acc:, - power:, - ) - } - <> if byte_zero <= byte && byte <= byte_nine -> { - // We have not yet reached the precision limit. Parse the next digit. - let digit = byte - 0x30 - do_parse_second_fraction_as_nanoseconds( - from: remaining_bytes, - acc: acc + digit * power, - power:, - ) - } - _ -> Ok(#(acc, bytes)) - } -} - -fn parse_offset(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - case bytes { - <<"Z", remaining_bytes:bytes>> | <<"z", remaining_bytes:bytes>> -> - Ok(#(0, remaining_bytes)) - _ -> parse_numeric_offset(bytes) - } -} - -fn parse_numeric_offset(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) { - use #(sign, bytes) <- result.try(parse_sign(from: bytes)) - use #(hours, bytes) <- result.try(parse_hours(from: bytes)) - use bytes <- result.try(accept_byte(from: bytes, value: byte_colon)) - use #(minutes, bytes) <- result.try(parse_minutes(from: bytes)) - - let offset_seconds = offset_to_seconds(sign, hours:, minutes:) - - Ok(#(offset_seconds, bytes)) -} - -fn parse_sign(from bytes) { - case bytes { - <<"+", remaining_bytes:bytes>> -> Ok(#("+", remaining_bytes)) - <<"-", remaining_bytes:bytes>> -> Ok(#("-", remaining_bytes)) - _ -> Error(Nil) - } -} - -fn offset_to_seconds(sign, hours hours, minutes minutes) { - let abs_seconds = hours * seconds_per_hour + minutes * seconds_per_minute - - case sign { - "-" -> -abs_seconds - _ -> abs_seconds - } -} - -/// Parse and return the given number of digits from the given bytes. -/// -fn parse_digits( - from bytes: BitArray, - count count: Int, -) -> Result(#(Int, BitArray), Nil) { - do_parse_digits(from: bytes, count:, acc: 0, k: 0) -} - -fn do_parse_digits( - from bytes: BitArray, - count count: Int, - acc acc: Int, - k k: Int, -) -> Result(#(Int, BitArray), Nil) { - case bytes { - _ if k >= count -> Ok(#(acc, bytes)) - <> if byte_zero <= byte && byte <= byte_nine -> - do_parse_digits( - from: remaining_bytes, - count:, - acc: acc * 10 + { byte - 0x30 }, - k: k + 1, - ) - _ -> Error(Nil) - } -} - -/// Accept the given value from `bytes` and move past it if found. -/// -fn accept_byte(from bytes: BitArray, value value: Int) -> Result(BitArray, Nil) { - case bytes { - <> if byte == value -> Ok(remaining_bytes) - _ -> Error(Nil) - } -} - -fn accept_date_time_separator(from bytes: BitArray) -> Result(BitArray, Nil) { - case bytes { - <> - if byte == byte_t_uppercase - || byte == byte_t_lowercase - || byte == byte_space - -> Ok(remaining_bytes) - _ -> Error(Nil) - } -} - -fn accept_empty(from bytes: BitArray) -> Result(Nil, Nil) { - case bytes { - <<>> -> Ok(Nil) - _ -> Error(Nil) - } -} - -/// Note: The caller of this function must ensure that all inputs are valid. -/// -fn from_date_time( - year year: Int, - month month: Int, - day day: Int, - hours hours: Int, - minutes minutes: Int, - seconds seconds: Int, - second_fraction_as_nanoseconds second_fraction_as_nanoseconds: Int, - offset_seconds offset_seconds: Int, -) -> Timestamp { - let julian_seconds = - julian_seconds_from_parts(year:, month:, day:, hours:, minutes:, seconds:) - - let julian_seconds_since_epoch = julian_seconds - julian_seconds_unix_epoch - - Timestamp( - seconds: julian_seconds_since_epoch - offset_seconds, - nanoseconds: second_fraction_as_nanoseconds, - ) - |> normalise -} - -/// `julian_seconds_from_parts(year, month, day, hours, minutes, seconds)` -/// returns the number of Julian -/// seconds represented by the given arguments. -/// -/// Note: It is the callers responsibility to ensure the inputs are valid. -/// -/// See https://www.tondering.dk/claus/cal/julperiod.php#formula -/// -fn julian_seconds_from_parts( - year year: Int, - month month: Int, - day day: Int, - hours hours: Int, - minutes minutes: Int, - seconds seconds: Int, -) { - let julian_day_seconds = - julian_day_from_ymd(year:, month:, day:) * seconds_per_day - - julian_day_seconds - + { hours * seconds_per_hour } - + { minutes * seconds_per_minute } - + seconds -} - -/// Note: It is the callers responsibility to ensure the inputs are valid. -/// -/// See https://www.tondering.dk/claus/cal/julperiod.php#formula -/// -fn julian_day_from_ymd(year year: Int, month month: Int, day day: Int) -> Int { - let adjustment = { 14 - month } / 12 - let adjusted_year = year + 4800 - adjustment - let adjusted_month = month + 12 * adjustment - 3 - - day - + { { 153 * adjusted_month } + 2 } - / 5 - + 365 - * adjusted_year - + { adjusted_year / 4 } - - { adjusted_year / 100 } - + { adjusted_year / 400 } - - 32_045 -} - -/// Create a timestamp from a number of seconds since 00:00:00 UTC on 1 January -/// 1970. -/// -pub fn from_unix_seconds(seconds: Int) -> Timestamp { - Timestamp(seconds, 0) -} - -/// Create a timestamp from a number of seconds and nanoseconds since 00:00:00 -/// UTC on 1 January 1970. -/// -/// # JavaScript int limitations -/// -/// Remember that JavaScript can only perfectly represent ints between positive -/// and negative 9,007,199,254,740,991! If you only use the nanosecond field -/// then you will almost certainly not get the date value you want due to this -/// loss of precision. Always use seconds primarily and then use nanoseconds -/// for the final sub-second adjustment. -/// -pub fn from_unix_seconds_and_nanoseconds( - seconds seconds: Int, - nanoseconds nanoseconds: Int, -) -> Timestamp { - Timestamp(seconds, nanoseconds) - |> normalise -} - -/// Convert the timestamp to a number of seconds since 00:00:00 UTC on 1 -/// January 1970. -/// -/// There may be some small loss of precision due to `Timestamp` being -/// nanosecond accurate and `Float` not being able to represent this. -/// -pub fn to_unix_seconds(timestamp: Timestamp) -> Float { - let seconds = int.to_float(timestamp.seconds) - let nanoseconds = int.to_float(timestamp.nanoseconds) - seconds +. { nanoseconds /. 1_000_000_000.0 } -} - -/// Convert the timestamp to a number of seconds and nanoseconds since 00:00:00 -/// UTC on 1 January 1970. There is no loss of precision with this conversion -/// on any target. -pub fn to_unix_seconds_and_nanoseconds(timestamp: Timestamp) -> #(Int, Int) { - #(timestamp.seconds, timestamp.nanoseconds) -} diff --git a/build/packages/gleam_time/src/gleam@time@calendar.erl b/build/packages/gleam_time/src/gleam@time@calendar.erl deleted file mode 100644 index e295d09..0000000 --- a/build/packages/gleam_time/src/gleam@time@calendar.erl +++ /dev/null @@ -1,468 +0,0 @@ --module(gleam@time@calendar). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/time/calendar.gleam"). --export([local_offset/0, month_to_string/1, month_to_int/1, month_from_int/1, is_leap_year/1, is_valid_date/1, is_valid_time_of_day/1, naive_date_compare/2]). --export_type([date/0, time_of_day/0, month/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " This module is for working with the Gregorian calendar, established by\n" - " Pope Gregory XIII in 1582!\n" - "\n" - " ## When should you use this module?\n" - "\n" - " > **tldr:** You probably want to use [`gleam/time/timestamp`](./timestamp.html)\n" - " > instead!\n" - "\n" - " Calendar time is difficult to work with programmatically, it is the source\n" - " of most time-related bugs in software. Compared to _epoch time_, which the\n" - " `gleam/time/timestamp` module uses, there are many disadvantages to\n" - " calendar time:\n" - "\n" - " - They are ambiguous if you don't know what time-zone is being used.\n" - "\n" - " - A time-zone database is required to understand calendar time even when\n" - " you have the time zone. These are large and your program has to\n" - " continously be updated as new versions of the database are published.\n" - "\n" - " - The type permits invalid states. e.g. `days` could be set to the number\n" - " 32, but this should not be possible!\n" - "\n" - " - There is not a single unique canonical value for each point in time,\n" - " thanks to time zones. Two different `Date` + `TimeOfDay` value pairs\n" - " could represent the same point in time. This means that you can't check\n" - " for time equality with `==` when using calendar types.\n" - "\n" - " - They are computationally complex, using a more memory to represent and\n" - " requiring a lot more CPU time to manipulate.\n" - "\n" - " There are also advantages to calendar time:\n" - "\n" - " - Calendar time is how human's talk about time, so if you want to show a\n" - " time or take a time from a human user then calendar time will make it\n" - " easier for them.\n" - "\n" - " - They can represent more abstract time periods such as \"New Year's Day\".\n" - " This may seem like an exact window of time at first, but really the\n" - " definition of \"New Year's Day\" is more fuzzy than that. When it starts\n" - " and ends will depend where in the world you are, so if you want to refer\n" - " to a day as a global concept instead of a fixed window of time for that\n" - " day in a specific location, then calendar time can represent that.\n" - "\n" - " So when should you use calendar time? These are our recommendations:\n" - "\n" - " - Default to `gleam/time/timestamp`, which is epoch time. It is\n" - " unambiguous, efficient, and significantly less likely to result in logic\n" - " bugs.\n" - "\n" - " - When writing time to a database or other data storage use epoch time,\n" - " using whatever epoch format it supports. For example, PostgreSQL\n" - " `timestamp` and `timestampz` are both epoch time, and `timestamp` is\n" - " preferred as it is more straightforward to use as your application is\n" - " also using epoch time.\n" - "\n" - " - When communicating with other computer systems continue to use epoch\n" - " time. For example, when sending times to another program you could\n" - " encode time as UNIX timestamps (seconds since 00:00:00 UTC on 1 January\n" - " 1970).\n" - "\n" - " - When communicating with humans use epoch time internally, and convert\n" - " to-and-from calendar time at the last moment, when iteracting with the\n" - " human user. It may also help the users to also show the time as a fuzzy\n" - " duration from the present time, such as \"about 4 days ago\".\n" - "\n" - " - When representing \"fuzzy\" human time concepts that don't exact periods\n" - " in time, such as \"one month\" (varies depending on which month, which\n" - " year, and in which time zone) and \"Christmas Day\" (varies depending on\n" - " which year and time zone) then use calendar time.\n" - "\n" - " Any time you do use calendar time you should be extra careful! It is very\n" - " easy to make mistake with. Avoid it where possible.\n" - "\n" - " ## Time zone offsets\n" - "\n" - " This package includes the `utc_offset` value and the `local_offset`\n" - " function, which are the offset for the UTC time zone and get the time\n" - " offset the computer running the program is configured to respectively.\n" - "\n" - " If you need to use other offsets in your program then you will need to get\n" - " them from somewhere else, such as from a package which loads the\n" - " [IANA Time Zone Database](https://www.iana.org/time-zones), or from the\n" - " website visitor's web browser, which your frontend can send for you.\n" - "\n" - " ## Use in APIs\n" - "\n" - " If you are making an API such as a HTTP JSON API you are encouraged to use\n" - " Unix timestamps instead of calendar times.\n" -). - --type date() :: {date, integer(), month(), integer()}. - --type time_of_day() :: {time_of_day, integer(), integer(), integer(), integer()}. - --type month() :: january | - february | - march | - april | - may | - june | - july | - august | - september | - october | - november | - december. - --file("src/gleam/time/calendar.gleam", 147). -?DOC( - " Get the offset for the computer's currently configured time zone.\n" - "\n" - " Note this may not be the time zone that is correct to use for your user.\n" - " For example, if you are making a web application that runs on a server you\n" - " want _their_ computer's time zone, not yours.\n" - "\n" - " This is the _current local_ offset, not the current local time zone. This\n" - " means that while it will result in the expected outcome for the current\n" - " time, it may result in unexpected output if used with other timestamps. For\n" - " example: a timestamp that would locally be during daylight savings time if\n" - " is it not currently daylight savings time when this function is called.\n" -). --spec local_offset() -> gleam@time@duration:duration(). -local_offset() -> - gleam@time@duration:seconds(gleam_time_ffi:local_time_offset_seconds()). - --file("src/gleam/time/calendar.gleam", 163). -?DOC( - " Returns the English name for a month.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " month_to_string(April)\n" - " // -> \"April\"\n" - " ```\n" -). --spec month_to_string(month()) -> binary(). -month_to_string(Month) -> - case Month of - january -> - <<"January"/utf8>>; - - february -> - <<"February"/utf8>>; - - march -> - <<"March"/utf8>>; - - april -> - <<"April"/utf8>>; - - may -> - <<"May"/utf8>>; - - june -> - <<"June"/utf8>>; - - july -> - <<"July"/utf8>>; - - august -> - <<"August"/utf8>>; - - september -> - <<"September"/utf8>>; - - october -> - <<"October"/utf8>>; - - november -> - <<"November"/utf8>>; - - december -> - <<"December"/utf8>> - end. - --file("src/gleam/time/calendar.gleam", 188). -?DOC( - " Returns the number for the month, where January is 1 and December is 12.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " month_to_int(January)\n" - " // -> 1\n" - " ```\n" -). --spec month_to_int(month()) -> integer(). -month_to_int(Month) -> - case Month of - january -> - 1; - - february -> - 2; - - march -> - 3; - - april -> - 4; - - may -> - 5; - - june -> - 6; - - july -> - 7; - - august -> - 8; - - september -> - 9; - - october -> - 10; - - november -> - 11; - - december -> - 12 - end. - --file("src/gleam/time/calendar.gleam", 213). -?DOC( - " Returns the month for a given number, where January is 1 and December is 12.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " month_from_int(1)\n" - " // -> Ok(January)\n" - " ```\n" -). --spec month_from_int(integer()) -> {ok, month()} | {error, nil}. -month_from_int(Month) -> - case Month of - 1 -> - {ok, january}; - - 2 -> - {ok, february}; - - 3 -> - {ok, march}; - - 4 -> - {ok, april}; - - 5 -> - {ok, may}; - - 6 -> - {ok, june}; - - 7 -> - {ok, july}; - - 8 -> - {ok, august}; - - 9 -> - {ok, september}; - - 10 -> - {ok, october}; - - 11 -> - {ok, november}; - - 12 -> - {ok, december}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/calendar.gleam", 290). -?DOC( - " Determines if a given year is a leap year.\n" - "\n" - " A leap year occurs every 4 years, except for years divisible by 100,\n" - " unless they are also divisible by 400.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " is_leap_year(2024)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_leap_year(2023)\n" - " // -> False\n" - " ```\n" -). --spec is_leap_year(integer()) -> boolean(). -is_leap_year(Year) -> - case (Year rem 400) =:= 0 of - true -> - true; - - false -> - case (Year rem 100) =:= 0 of - true -> - false; - - false -> - (Year rem 4) =:= 0 - end - end. - --file("src/gleam/time/calendar.gleam", 254). -?DOC( - " Checks if a given date is valid.\n" - "\n" - " This function properly accounts for leap years when validating February days.\n" - " A leap year occurs every 4 years, except for years divisible by 100,\n" - " unless they are also divisible by 400.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " is_valid_date(Date(2023, April, 15))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_valid_date(Date(2023, April, 31))\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_valid_date(Date(2024, February, 29))\n" - " // -> True (2024 is a leap year)\n" - " ```\n" -). --spec is_valid_date(date()) -> boolean(). -is_valid_date(Date) -> - {date, Year, Month, Day} = Date, - case Day < 1 of - true -> - false; - - false -> - case Month of - january -> - Day =< 31; - - march -> - Day =< 31; - - may -> - Day =< 31; - - july -> - Day =< 31; - - august -> - Day =< 31; - - october -> - Day =< 31; - - december -> - Day =< 31; - - april -> - Day =< 30; - - june -> - Day =< 30; - - september -> - Day =< 30; - - november -> - Day =< 30; - - february -> - Max_february_days = case is_leap_year(Year) of - true -> - 29; - - false -> - 28 - end, - Day =< Max_february_days - end - end. - --file("src/gleam/time/calendar.gleam", 313). -?DOC( - " Checks if a time of day is valid.\n" - "\n" - " Validates that hours are 0-23, minutes are 0-59, seconds are 0-59,\n" - " and nanoseconds are 0-999,999,999.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " is_valid_time_of_day(TimeOfDay(12, 30, 45, 123456789))\n" - " // -> True\n" - " ```\n" -). --spec is_valid_time_of_day(time_of_day()) -> boolean(). -is_valid_time_of_day(Time) -> - {time_of_day, Hours, Minutes, Seconds, Nanoseconds} = Time, - (((((((Hours >= 0) andalso (Hours =< 23)) andalso (Minutes >= 0)) andalso (Minutes - =< 59)) - andalso (Seconds >= 0)) - andalso (Seconds =< 59)) - andalso (Nanoseconds >= 0)) - andalso (Nanoseconds =< 999999999). - --file("src/gleam/time/calendar.gleam", 340). -?DOC( - " Naively compares two dates without any time zone information, returning an\n" - " order.\n" - "\n" - " ## Correctness\n" - "\n" - " This function compares dates without any time zone information, only using\n" - " the rules for the gregorian calendar. This is typically sufficient, but be\n" - " aware that in reality some time zones will change their calendar date\n" - " occasionally. This can result in days being skipped, out of order, or\n" - " happening multiple times.\n" - "\n" - " If you need real-world correct time ordering then use the\n" - " `gleam/time/timestamp` module instead.\n" -). --spec naive_date_compare(date(), date()) -> gleam@order:order(). -naive_date_compare(One, Other) -> - _pipe = gleam@int:compare(erlang:element(2, One), erlang:element(2, Other)), - _pipe@1 = gleam@order:lazy_break_tie( - _pipe, - fun() -> - gleam@int:compare( - month_to_int(erlang:element(3, One)), - month_to_int(erlang:element(3, Other)) - ) - end - ), - gleam@order:lazy_break_tie( - _pipe@1, - fun() -> - gleam@int:compare(erlang:element(4, One), erlang:element(4, Other)) - end - ). diff --git a/build/packages/gleam_time/src/gleam@time@duration.erl b/build/packages/gleam_time/src/gleam@time@duration.erl deleted file mode 100644 index 7ba7ad2..0000000 --- a/build/packages/gleam_time/src/gleam@time@duration.erl +++ /dev/null @@ -1,381 +0,0 @@ --module(gleam@time@duration). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/time/duration.gleam"). --export([approximate/1, compare/2, difference/2, add/2, seconds/1, minutes/1, hours/1, milliseconds/1, nanoseconds/1, to_seconds/1, to_seconds_and_nanoseconds/1, to_iso8601_string/1]). --export_type([duration/0, unit/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --opaque duration() :: {duration, integer(), integer()}. - --type unit() :: nanosecond | - microsecond | - millisecond | - second | - minute | - hour | - day | - week | - month | - year. - --file("src/gleam/time/duration.gleam", 110). -?DOC( - " Ensure the duration is represented with `nanoseconds` being positive and\n" - " less than 1 second.\n" - "\n" - " This function does not change the amount of time that the duratoin refers\n" - " to, it only adjusts the values used to represent the time.\n" -). --spec normalise(duration()) -> duration(). -normalise(Duration) -> - Multiplier = 1000000000, - Nanoseconds = case Multiplier of - 0 -> 0; - Gleam@denominator -> erlang:element(3, Duration) rem Gleam@denominator - end, - Overflow = erlang:element(3, Duration) - Nanoseconds, - Seconds = erlang:element(2, Duration) + (case Multiplier of - 0 -> 0; - Gleam@denominator@1 -> Overflow div Gleam@denominator@1 - end), - case Nanoseconds >= 0 of - true -> - {duration, Seconds, Nanoseconds}; - - false -> - {duration, Seconds - 1, Multiplier + Nanoseconds} - end. - --file("src/gleam/time/duration.gleam", 76). -?DOC( - " Convert a duration to a number of the largest number of a unit, serving as\n" - " a rough description of the duration that a human can understand.\n" - "\n" - " The size used for each unit are described in the documentation for the\n" - " `Unit` type.\n" - "\n" - " ```gleam\n" - " seconds(125)\n" - " |> approximate\n" - " // -> #(2, Minute)\n" - " ```\n" - "\n" - " This function rounds _towards zero_. This means that if a duration is just\n" - " short of 2 days then it will approximate to 1 day.\n" - "\n" - " ```gleam\n" - " hours(47)\n" - " |> approximate\n" - " // -> #(1, Day)\n" - " ```\n" -). --spec approximate(duration()) -> {integer(), unit()}. -approximate(Duration) -> - {duration, S, Ns} = Duration, - Minute = 60, - Hour = Minute * 60, - Day = Hour * 24, - Week = Day * 7, - Year = (Day * 365) + (Hour * 6), - Month = Year div 12, - Microsecond = 1000, - Millisecond = Microsecond * 1000, - case nil of - _ when S < 0 -> - {Amount, Unit} = begin - _pipe = {duration, - S, - Ns}, - _pipe@1 = normalise(_pipe), - approximate(_pipe@1) - end, - {- Amount, Unit}; - - _ when S >= Year -> - {case Year of - 0 -> 0; - Gleam@denominator -> S div Gleam@denominator - end, year}; - - _ when S >= Month -> - {case Month of - 0 -> 0; - Gleam@denominator@1 -> S div Gleam@denominator@1 - end, month}; - - _ when S >= Week -> - {case Week of - 0 -> 0; - Gleam@denominator@2 -> S div Gleam@denominator@2 - end, week}; - - _ when S >= Day -> - {case Day of - 0 -> 0; - Gleam@denominator@3 -> S div Gleam@denominator@3 - end, day}; - - _ when S >= Hour -> - {case Hour of - 0 -> 0; - Gleam@denominator@4 -> S div Gleam@denominator@4 - end, hour}; - - _ when S >= Minute -> - {case Minute of - 0 -> 0; - Gleam@denominator@5 -> S div Gleam@denominator@5 - end, minute}; - - _ when S > 0 -> - {S, second}; - - _ when Ns >= Millisecond -> - {case Millisecond of - 0 -> 0; - Gleam@denominator@6 -> Ns div Gleam@denominator@6 - end, millisecond}; - - _ when Ns >= Microsecond -> - {case Microsecond of - 0 -> 0; - Gleam@denominator@7 -> Ns div Gleam@denominator@7 - end, microsecond}; - - _ -> - {Ns, nanosecond} - end. - --file("src/gleam/time/duration.gleam", 140). -?DOC( - " Compare one duration to another, indicating whether the first spans a\n" - " larger amount of time (and so is greater) or smaller amount of time (and so\n" - " is lesser) than the second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " compare(seconds(1), seconds(2))\n" - " // -> order.Lt\n" - " ```\n" - "\n" - " Whether a duration is negative or positive doesn't matter for comparing\n" - " them, only the amount of time spanned matters.\n" - "\n" - " ```gleam\n" - " compare(seconds(-2), seconds(1))\n" - " // -> order.Gt\n" - " ```\n" -). --spec compare(duration(), duration()) -> gleam@order:order(). -compare(Left, Right) -> - Parts = fun(X) -> case erlang:element(2, X) >= 0 of - true -> - {erlang:element(2, X), erlang:element(3, X)}; - - false -> - {(erlang:element(2, X) * -1) - 1, - 1000000000 - erlang:element(3, X)} - end end, - {Ls, Lns} = Parts(Left), - {Rs, Rns} = Parts(Right), - _pipe = gleam@int:compare(Ls, Rs), - gleam@order:break_tie(_pipe, gleam@int:compare(Lns, Rns)). - --file("src/gleam/time/duration.gleam", 164). -?DOC( - " Calculate the difference between two durations.\n" - "\n" - " This is effectively substracting the first duration from the second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " difference(seconds(1), seconds(5))\n" - " // -> seconds(4)\n" - " ```\n" -). --spec difference(duration(), duration()) -> duration(). -difference(Left, Right) -> - _pipe = {duration, - erlang:element(2, Right) - erlang:element(2, Left), - erlang:element(3, Right) - erlang:element(3, Left)}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 178). -?DOC( - " Add two durations together.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " add(seconds(1), seconds(5))\n" - " // -> seconds(6)\n" - " ```\n" -). --spec add(duration(), duration()) -> duration(). -add(Left, Right) -> - _pipe = {duration, - erlang:element(2, Left) + erlang:element(2, Right), - erlang:element(3, Left) + erlang:element(3, Right)}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 225). --spec nanosecond_digits(integer(), integer(), binary()) -> binary(). -nanosecond_digits(N, Position, Acc) -> - case Position of - 9 -> - Acc; - - _ when (Acc =:= <<""/utf8>>) andalso ((N rem 10) =:= 0) -> - nanosecond_digits(N div 10, Position + 1, Acc); - - _ -> - Acc@1 = <<(erlang:integer_to_binary(N rem 10))/binary, Acc/binary>>, - nanosecond_digits(N div 10, Position + 1, Acc@1) - end. - --file("src/gleam/time/duration.gleam", 239). -?DOC(" Create a duration of a number of seconds.\n"). --spec seconds(integer()) -> duration(). -seconds(Amount) -> - {duration, Amount, 0}. - --file("src/gleam/time/duration.gleam", 244). -?DOC(" Create a duration of a number of minutes.\n"). --spec minutes(integer()) -> duration(). -minutes(Amount) -> - seconds(Amount * 60). - --file("src/gleam/time/duration.gleam", 249). -?DOC(" Create a duration of a number of hours.\n"). --spec hours(integer()) -> duration(). -hours(Amount) -> - seconds((Amount * 60) * 60). - --file("src/gleam/time/duration.gleam", 254). -?DOC(" Create a duration of a number of milliseconds.\n"). --spec milliseconds(integer()) -> duration(). -milliseconds(Amount) -> - Remainder = Amount rem 1000, - Overflow = Amount - Remainder, - Nanoseconds = Remainder * 1000000, - Seconds = Overflow div 1000, - _pipe = {duration, Seconds, Nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 273). -?DOC( - " Create a duration of a number of nanoseconds.\n" - "\n" - " # JavaScript int limitations\n" - "\n" - " Remember that JavaScript can only perfectly represent ints between positive\n" - " and negative 9,007,199,254,740,991! If you use a single call to this\n" - " function to create durations larger than that number of nanoseconds then\n" - " you will likely not get exactly the value you expect. Use `seconds` and\n" - " `milliseconds` as much as possible for large durations.\n" -). --spec nanoseconds(integer()) -> duration(). -nanoseconds(Amount) -> - _pipe = {duration, 0, Amount}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 283). -?DOC( - " Convert the duration to a number of seconds.\n" - "\n" - " There may be some small loss of precision due to `Duration` being\n" - " nanosecond accurate and `Float` not being able to represent this.\n" -). --spec to_seconds(duration()) -> float(). -to_seconds(Duration) -> - Seconds = erlang:float(erlang:element(2, Duration)), - Nanoseconds = erlang:float(erlang:element(3, Duration)), - Seconds + (Nanoseconds / 1000000000.0). - --file("src/gleam/time/duration.gleam", 292). -?DOC( - " Convert the duration to a number of seconds and nanoseconds. There is no\n" - " loss of precision with this conversion on any target.\n" -). --spec to_seconds_and_nanoseconds(duration()) -> {integer(), integer()}. -to_seconds_and_nanoseconds(Duration) -> - {erlang:element(2, Duration), erlang:element(3, Duration)}. - --file("src/gleam/time/duration.gleam", 192). -?DOC( - " Convert the duration to an [ISO8601][1] formatted duration string.\n" - "\n" - " The ISO8601 duration format is ambiguous without context due to months and\n" - " years having different lengths, and because of leap seconds. This function\n" - " encodes the duration as days, hours, and seconds without any leap seconds.\n" - " Be sure to take this into account when using the duration strings.\n" - "\n" - " [1]: https://en.wikipedia.org/wiki/ISO_8601#Durations\n" -). --spec to_iso8601_string(duration()) -> binary(). -to_iso8601_string(Duration) -> - gleam@bool:guard( - Duration =:= {duration, 0, 0}, - <<"PT0S"/utf8>>, - fun() -> - Split = fun(Total, Limit) -> - Amount = case Limit of - 0 -> 0; - Gleam@denominator -> Total rem Gleam@denominator - end, - Remainder = case Limit of - 0 -> 0; - Gleam@denominator@1 -> (Total - Amount) div Gleam@denominator@1 - end, - {Amount, Remainder} - end, - {Seconds, Rest} = Split(erlang:element(2, Duration), 60), - {Minutes, Rest@1} = Split(Rest, 60), - {Hours, Rest@2} = Split(Rest@1, 24), - Days = Rest@2, - Add = fun(Out, Value, Unit) -> case Value of - 0 -> - Out; - - _ -> - <<<>/binary, - Unit/binary>> - end end, - Output = begin - _pipe = <<"P"/utf8>>, - _pipe@1 = Add(_pipe, Days, <<"D"/utf8>>), - _pipe@2 = gleam@string:append(_pipe@1, <<"T"/utf8>>), - _pipe@3 = Add(_pipe@2, Hours, <<"H"/utf8>>), - Add(_pipe@3, Minutes, <<"M"/utf8>>) - end, - case {Seconds, erlang:element(3, Duration)} of - {0, 0} -> - Output; - - {_, 0} -> - <<<>/binary, - "S"/utf8>>; - - {_, _} -> - F = nanosecond_digits( - erlang:element(3, Duration), - 0, - <<""/utf8>> - ), - <<<<<<<>/binary, - "."/utf8>>/binary, - F/binary>>/binary, - "S"/utf8>> - end - end - ). diff --git a/build/packages/gleam_time/src/gleam@time@timestamp.erl b/build/packages/gleam_time/src/gleam@time@timestamp.erl deleted file mode 100644 index 0d7413a..0000000 --- a/build/packages/gleam_time/src/gleam@time@timestamp.erl +++ /dev/null @@ -1,1188 +0,0 @@ --module(gleam@time@timestamp). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/time/timestamp.gleam"). --export([compare/2, system_time/0, difference/2, add/2, to_calendar/2, to_rfc3339/2, from_unix_seconds/1, from_unix_seconds_and_nanoseconds/2, to_unix_seconds/1, to_unix_seconds_and_nanoseconds/1, from_calendar/3, parse_rfc3339/1]). --export_type([timestamp/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Welcome to the timestamp module! This module and its `Timestamp` type are\n" - " what you will be using most commonly when working with time in Gleam.\n" - "\n" - " A timestamp represents a moment in time, represented as an amount of time\n" - " since the calendar time 00:00:00 UTC on 1 January 1970, also known as the\n" - " _Unix epoch_.\n" - "\n" - " # Wall clock time and monotonicity\n" - "\n" - " Time is very complicated, especially on computers! While they generally do\n" - " a good job of keeping track of what the time is, computers can get\n" - " out-of-sync and start to report a time that is too late or too early. Most\n" - " computers use \"network time protocol\" to tell each other what they think\n" - " the time is, and computers that realise they are running too fast or too\n" - " slow will adjust their clock to correct it. When this happens it can seem\n" - " to your program that the current time has changed, and it may have even\n" - " jumped backwards in time!\n" - "\n" - " This measure of time is called _wall clock time_, and it is what people\n" - " commonly think of when they think of time. It is important to be aware that\n" - " it can go backwards, and your program must not rely on it only ever going\n" - " forwards at a steady rate. For example, for tracking what order events happen\n" - " in. \n" - "\n" - " This module uses wall clock time. If your program needs time values to always\n" - " increase you will need a _monotonic_ time instead. It's uncommon that you\n" - " would need monotonic time, one example might be if you're making a\n" - " benchmarking framework.\n" - "\n" - " The exact way that time works will depend on what runtime you use. The\n" - " Erlang documentation on time has a lot of detail about time generally as well\n" - " as how it works on the BEAM, it is worth reading.\n" - " .\n" - "\n" - " # Converting to local calendar time\n" - "\n" - " Timestamps don't take into account time zones, so a moment in time will\n" - " have the same timestamp value regardless of where you are in the world. To\n" - " convert them to local time you will need to know the offset for the time\n" - " zone you wish to use, likely from a time zone database. See the\n" - " `gleam/time/calendar` module for more information.\n" - "\n" -). - --opaque timestamp() :: {timestamp, integer(), integer()}. - --file("src/gleam/time/timestamp.gleam", 119). -?DOC( - " Ensure the time is represented with `nanoseconds` being positive and less\n" - " than 1 second.\n" - "\n" - " This function does not change the time that the timestamp refers to, it\n" - " only adjusts the values used to represent the time.\n" -). --spec normalise(timestamp()) -> timestamp(). -normalise(Timestamp) -> - Multiplier = 1000000000, - Nanoseconds = case Multiplier of - 0 -> 0; - Gleam@denominator -> erlang:element(3, Timestamp) rem Gleam@denominator - end, - Overflow = erlang:element(3, Timestamp) - Nanoseconds, - Seconds = erlang:element(2, Timestamp) + (case Multiplier of - 0 -> 0; - Gleam@denominator@1 -> Overflow div Gleam@denominator@1 - end), - case Nanoseconds >= 0 of - true -> - {timestamp, Seconds, Nanoseconds}; - - false -> - {timestamp, Seconds - 1, Multiplier + Nanoseconds} - end. - --file("src/gleam/time/timestamp.gleam", 141). -?DOC( - " Compare one timestamp to another, indicating whether the first is further\n" - " into the future (greater) or further into the past (lesser) than the\n" - " second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " compare(from_unix_seconds(1), from_unix_seconds(2))\n" - " // -> order.Lt\n" - " ```\n" -). --spec compare(timestamp(), timestamp()) -> gleam@order:order(). -compare(Left, Right) -> - gleam@order:break_tie( - gleam@int:compare(erlang:element(2, Left), erlang:element(2, Right)), - gleam@int:compare(erlang:element(3, Left), erlang:element(3, Right)) - ). - --file("src/gleam/time/timestamp.gleam", 160). -?DOC( - " Get the current system time.\n" - "\n" - " Note this time is not unique or monotonic, it could change at any time or\n" - " even go backwards! The exact behaviour will depend on the runtime used. See\n" - " the module documentation for more information.\n" - "\n" - " On Erlang this uses [`erlang:system_time/1`][1]. On JavaScript this uses\n" - " [`Date.now`][2].\n" - "\n" - " [1]: https://www.erlang.org/doc/apps/erts/erlang#system_time/1\n" - " [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now\n" -). --spec system_time() -> timestamp(). -system_time() -> - {Seconds, Nanoseconds} = gleam_time_ffi:system_time(), - normalise({timestamp, Seconds, Nanoseconds}). - --file("src/gleam/time/timestamp.gleam", 180). -?DOC( - " Calculate the difference between two timestamps.\n" - "\n" - " This is effectively substracting the first timestamp from the second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " difference(from_unix_seconds(1), from_unix_seconds(5))\n" - " // -> duration.seconds(4)\n" - " ```\n" -). --spec difference(timestamp(), timestamp()) -> gleam@time@duration:duration(). -difference(Left, Right) -> - Seconds = gleam@time@duration:seconds( - erlang:element(2, Right) - erlang:element(2, Left) - ), - Nanoseconds = gleam@time@duration:nanoseconds( - erlang:element(3, Right) - erlang:element(3, Left) - ), - gleam@time@duration:add(Seconds, Nanoseconds). - --file("src/gleam/time/timestamp.gleam", 195). -?DOC( - " Add a duration to a timestamp.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " add(from_unix_seconds(1000), duration.seconds(5))\n" - " // -> from_unix_seconds(1005)\n" - " ```\n" -). --spec add(timestamp(), gleam@time@duration:duration()) -> timestamp(). -add(Timestamp, Duration) -> - {Seconds, Nanoseconds} = gleam@time@duration:to_seconds_and_nanoseconds( - Duration - ), - _pipe = {timestamp, - erlang:element(2, Timestamp) + Seconds, - erlang:element(3, Timestamp) + Nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/timestamp.gleam", 262). --spec pad_digit(integer(), integer()) -> binary(). -pad_digit(Digit, Desired_length) -> - _pipe = erlang:integer_to_binary(Digit), - gleam@string:pad_start(_pipe, Desired_length, <<"0"/utf8>>). - --file("src/gleam/time/timestamp.gleam", 308). --spec duration_to_minutes(gleam@time@duration:duration()) -> integer(). -duration_to_minutes(Duration) -> - erlang:round(gleam@time@duration:to_seconds(Duration) / 60.0). - --file("src/gleam/time/timestamp.gleam", 370). --spec modulo(integer(), integer()) -> integer(). -modulo(N, M) -> - case gleam@int:modulo(N, M) of - {ok, N@1} -> - N@1; - - {error, _} -> - 0 - end. - --file("src/gleam/time/timestamp.gleam", 377). --spec floored_div(integer(), float()) -> integer(). -floored_div(Numerator, Denominator) -> - N = case Denominator of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> erlang:float(Numerator) / Gleam@denominator - end, - erlang:round(math:floor(N)). - --file("src/gleam/time/timestamp.gleam", 383). --spec to_civil(integer()) -> {integer(), integer(), integer()}. -to_civil(Minutes) -> - Raw_day = floored_div(Minutes, (60.0 * 24.0)) + 719468, - Era = case Raw_day >= 0 of - true -> - Raw_day div 146097; - - false -> - (Raw_day - 146096) div 146097 - end, - Day_of_era = Raw_day - (Era * 146097), - Year_of_era = (((Day_of_era - (Day_of_era div 1460)) + (Day_of_era div 36524)) - - (Day_of_era div 146096)) - div 365, - Year = Year_of_era + (Era * 400), - Day_of_year = Day_of_era - (((365 * Year_of_era) + (Year_of_era div 4)) - (Year_of_era - div 100)), - Mp = ((5 * Day_of_year) + 2) div 153, - Month = case Mp < 10 of - true -> - Mp + 3; - - false -> - Mp - 9 - end, - Day = (Day_of_year - (((153 * Mp) + 2) div 5)) + 1, - Year@1 = case Month =< 2 of - true -> - Year + 1; - - false -> - Year - end, - {Year@1, Month, Day}. - --file("src/gleam/time/timestamp.gleam", 312). --spec to_calendar_from_offset(timestamp(), integer()) -> {integer(), - integer(), - integer(), - integer(), - integer(), - integer()}. -to_calendar_from_offset(Timestamp, Offset) -> - Total = erlang:element(2, Timestamp) + (Offset * 60), - Seconds = modulo(Total, 60), - Total_minutes = floored_div(Total, 60.0), - Minutes = modulo(Total, 60 * 60) div 60, - Hours = case (60 * 60) of - 0 -> 0; - Gleam@denominator -> modulo(Total, (24 * 60) * 60) div Gleam@denominator - end, - {Year, Month, Day} = to_civil(Total_minutes), - {Year, Month, Day, Hours, Minutes, Seconds}. - --file("src/gleam/time/timestamp.gleam", 281). -?DOC( - " Convert a `Timestamp` to calendar time, suitable for presenting to a human\n" - " to read.\n" - "\n" - " If you want a machine to use the time value then you should not use this\n" - " function and should instead keep it as a timestamp. See the documentation\n" - " for the `gleam/time/calendar` module for more information.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " timestamp.from_unix_seconds(0)\n" - " |> timestamp.to_calendar(calendar.utc_offset)\n" - " // -> #(Date(1970, January, 1), TimeOfDay(0, 0, 0, 0))\n" - " ```\n" -). --spec to_calendar(timestamp(), gleam@time@duration:duration()) -> {gleam@time@calendar:date(), - gleam@time@calendar:time_of_day()}. -to_calendar(Timestamp, Offset) -> - Offset@1 = duration_to_minutes(Offset), - {Year, Month, Day, Hours, Minutes, Seconds} = to_calendar_from_offset( - Timestamp, - Offset@1 - ), - Month@1 = case Month of - 1 -> - january; - - 2 -> - february; - - 3 -> - march; - - 4 -> - april; - - 5 -> - may; - - 6 -> - june; - - 7 -> - july; - - 8 -> - august; - - 9 -> - september; - - 10 -> - october; - - 11 -> - november; - - _ -> - december - end, - Nanoseconds = erlang:element(3, Timestamp), - Date = {date, Year, Month@1, Day}, - Time = {time_of_day, Hours, Minutes, Seconds, Nanoseconds}, - {Date, Time}. - --file("src/gleam/time/timestamp.gleam", 446). --spec do_remove_trailing_zeros(list(integer())) -> list(integer()). -do_remove_trailing_zeros(Reversed_digits) -> - case Reversed_digits of - [] -> - []; - - [Digit | Digits] when Digit =:= 0 -> - do_remove_trailing_zeros(Digits); - - Reversed_digits@1 -> - lists:reverse(Reversed_digits@1) - end. - --file("src/gleam/time/timestamp.gleam", 440). -?DOC(" Given a list of digits, return new list with any trailing zeros removed.\n"). --spec remove_trailing_zeros(list(integer())) -> list(integer()). -remove_trailing_zeros(Digits) -> - Reversed_digits = lists:reverse(Digits), - do_remove_trailing_zeros(Reversed_digits). - --file("src/gleam/time/timestamp.gleam", 461). --spec do_get_zero_padded_digits(integer(), list(integer()), integer()) -> list(integer()). -do_get_zero_padded_digits(Number, Digits, Count) -> - case Number of - Number@1 when (Number@1 =< 0) andalso (Count >= 9) -> - Digits; - - Number@2 when Number@2 =< 0 -> - do_get_zero_padded_digits(Number@2, [0 | Digits], Count + 1); - - Number@3 -> - Digit = Number@3 rem 10, - Number@4 = floored_div(Number@3, 10.0), - do_get_zero_padded_digits(Number@4, [Digit | Digits], Count + 1) - end. - --file("src/gleam/time/timestamp.gleam", 457). -?DOC( - " Returns the list of digits of `number`. If the number of digits is less \n" - " than 9, the result is zero-padded at the front.\n" -). --spec get_zero_padded_digits(integer()) -> list(integer()). -get_zero_padded_digits(Number) -> - do_get_zero_padded_digits(Number, [], 0). - --file("src/gleam/time/timestamp.gleam", 420). -?DOC( - " Converts nanoseconds into a `String` representation of fractional seconds.\n" - " \n" - " Assumes that `nanoseconds < 1_000_000_000`, which will be true for any \n" - " normalised timestamp.\n" -). --spec show_second_fraction(integer()) -> binary(). -show_second_fraction(Nanoseconds) -> - case gleam@int:compare(Nanoseconds, 0) of - lt -> - <<""/utf8>>; - - eq -> - <<""/utf8>>; - - gt -> - Second_fraction_part = begin - _pipe = Nanoseconds, - _pipe@1 = get_zero_padded_digits(_pipe), - _pipe@2 = remove_trailing_zeros(_pipe@1), - _pipe@3 = gleam@list:map( - _pipe@2, - fun erlang:integer_to_binary/1 - ), - gleam@string:join(_pipe@3, <<""/utf8>>) - end, - <<"."/utf8, Second_fraction_part/binary>> - end. - --file("src/gleam/time/timestamp.gleam", 240). -?DOC( - " Convert a timestamp to a RFC 3339 formatted time string, with an offset\n" - " supplied as an additional argument.\n" - "\n" - " The output of this function is also ISO 8601 compatible so long as the\n" - " offset not negative. Offsets have at-most minute precision, so an offset\n" - " with higher precision will be rounded to the nearest minute.\n" - "\n" - " If you are making an API such as a HTTP JSON API you are encouraged to use\n" - " Unix timestamps instead of this format or ISO 8601. Unix timestamps are a\n" - " better choice as they don't contain offset information. Consider:\n" - "\n" - " - UTC offsets are not time zones. This does not and cannot tell us the time\n" - " zone in which the date was recorded. So what are we supposed to do with\n" - " this information?\n" - " - Users typically want dates formatted according to their local time zone.\n" - " What if the provided UTC offset is different from the current user's time\n" - " zone? What are we supposed to do with it then?\n" - " - Despite it being useless (or worse, a source of bugs), the UTC offset\n" - " creates a larger payload to transfer.\n" - "\n" - " They also uses more memory than a unix timestamp. The way they are better\n" - " than Unix timestamp is that it is easier for a human to read them, but\n" - " this is a hinderance that tooling can remedy, and APIs are not primarily\n" - " for humans.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " timestamp.from_unix_seconds_and_nanoseconds(1000, 123_000_000)\n" - " |> to_rfc3339(calendar.utc_offset)\n" - " // -> \"1970-01-01T00:16:40.123Z\"\n" - " ```\n" - "\n" - " ```gleam\n" - " timestamp.from_unix_seconds(1000)\n" - " |> to_rfc3339(duration.seconds(3600))\n" - " // -> \"1970-01-01T01:16:40+01:00\"\n" - " ```\n" -). --spec to_rfc3339(timestamp(), gleam@time@duration:duration()) -> binary(). -to_rfc3339(Timestamp, Offset) -> - Offset@1 = duration_to_minutes(Offset), - {Years, Months, Days, Hours, Minutes, Seconds} = to_calendar_from_offset( - Timestamp, - Offset@1 - ), - Offset_minutes = modulo(Offset@1, 60), - Offset_hours = gleam@int:absolute_value(floored_div(Offset@1, 60.0)), - N2 = fun(_capture) -> pad_digit(_capture, 2) end, - N4 = fun(_capture@1) -> pad_digit(_capture@1, 4) end, - Out = <<""/utf8>>, - Out@1 = <<<<<<<<<>/binary, "-"/utf8>>/binary, - (N2(Months))/binary>>/binary, - "-"/utf8>>/binary, - (N2(Days))/binary>>, - Out@2 = <>, - Out@3 = <<<<<<<<<>/binary, ":"/utf8>>/binary, - (N2(Minutes))/binary>>/binary, - ":"/utf8>>/binary, - (N2(Seconds))/binary>>, - Out@4 = <>, - case gleam@int:compare(Offset@1, 0) of - eq -> - <>; - - gt -> - <<<<<<<>/binary, (N2(Offset_hours))/binary>>/binary, - ":"/utf8>>/binary, - (N2(Offset_minutes))/binary>>; - - lt -> - <<<<<<<>/binary, (N2(Offset_hours))/binary>>/binary, - ":"/utf8>>/binary, - (N2(Offset_minutes))/binary>> - end. - --file("src/gleam/time/timestamp.gleam", 611). --spec is_leap_year(integer()) -> boolean(). -is_leap_year(Year) -> - ((Year rem 4) =:= 0) andalso (((Year rem 100) /= 0) orelse ((Year rem 400) - =:= 0)). - --file("src/gleam/time/timestamp.gleam", 715). --spec parse_sign(bitstring()) -> {ok, {binary(), bitstring()}} | {error, nil}. -parse_sign(Bytes) -> - case Bytes of - <<"+"/utf8, Remaining_bytes/binary>> -> - {ok, {<<"+"/utf8>>, Remaining_bytes}}; - - <<"-"/utf8, Remaining_bytes@1/binary>> -> - {ok, {<<"-"/utf8>>, Remaining_bytes@1}}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 762). -?DOC(" Accept the given value from `bytes` and move past it if found.\n"). --spec accept_byte(bitstring(), integer()) -> {ok, bitstring()} | {error, nil}. -accept_byte(Bytes, Value) -> - case Bytes of - <> when Byte =:= Value -> - {ok, Remaining_bytes}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 780). --spec accept_empty(bitstring()) -> {ok, nil} | {error, nil}. -accept_empty(Bytes) -> - case Bytes of - <<>> -> - {ok, nil}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 840). -?DOC( - " Note: It is the callers responsibility to ensure the inputs are valid.\n" - " \n" - " See https://www.tondering.dk/claus/cal/julperiod.php#formula\n" -). --spec julian_day_from_ymd(integer(), integer(), integer()) -> integer(). -julian_day_from_ymd(Year, Month, Day) -> - Adjustment = (14 - Month) div 12, - Adjusted_year = (Year + 4800) - Adjustment, - Adjusted_month = (Month + (12 * Adjustment)) - 3, - (((((Day + (((153 * Adjusted_month) + 2) div 5)) + (365 * Adjusted_year)) + (Adjusted_year - div 4)) - - (Adjusted_year div 100)) - + (Adjusted_year div 400)) - - 32045. - --file("src/gleam/time/timestamp.gleam", 859). -?DOC( - " Create a timestamp from a number of seconds since 00:00:00 UTC on 1 January\n" - " 1970.\n" -). --spec from_unix_seconds(integer()) -> timestamp(). -from_unix_seconds(Seconds) -> - {timestamp, Seconds, 0}. - --file("src/gleam/time/timestamp.gleam", 874). -?DOC( - " Create a timestamp from a number of seconds and nanoseconds since 00:00:00\n" - " UTC on 1 January 1970.\n" - "\n" - " # JavaScript int limitations\n" - "\n" - " Remember that JavaScript can only perfectly represent ints between positive\n" - " and negative 9,007,199,254,740,991! If you only use the nanosecond field\n" - " then you will almost certainly not get the date value you want due to this\n" - " loss of precision. Always use seconds primarily and then use nanoseconds\n" - " for the final sub-second adjustment.\n" -). --spec from_unix_seconds_and_nanoseconds(integer(), integer()) -> timestamp(). -from_unix_seconds_and_nanoseconds(Seconds, Nanoseconds) -> - _pipe = {timestamp, Seconds, Nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/timestamp.gleam", 888). -?DOC( - " Convert the timestamp to a number of seconds since 00:00:00 UTC on 1\n" - " January 1970.\n" - "\n" - " There may be some small loss of precision due to `Timestamp` being\n" - " nanosecond accurate and `Float` not being able to represent this.\n" -). --spec to_unix_seconds(timestamp()) -> float(). -to_unix_seconds(Timestamp) -> - Seconds = erlang:float(erlang:element(2, Timestamp)), - Nanoseconds = erlang:float(erlang:element(3, Timestamp)), - Seconds + (Nanoseconds / 1000000000.0). - --file("src/gleam/time/timestamp.gleam", 897). -?DOC( - " Convert the timestamp to a number of seconds and nanoseconds since 00:00:00\n" - " UTC on 1 January 1970. There is no loss of precision with this conversion\n" - " on any target.\n" -). --spec to_unix_seconds_and_nanoseconds(timestamp()) -> {integer(), integer()}. -to_unix_seconds_and_nanoseconds(Timestamp) -> - {erlang:element(2, Timestamp), erlang:element(3, Timestamp)}. - --file("src/gleam/time/timestamp.gleam", 723). --spec offset_to_seconds(binary(), integer(), integer()) -> integer(). -offset_to_seconds(Sign, Hours, Minutes) -> - Abs_seconds = (Hours * 3600) + (Minutes * 60), - case Sign of - <<"-"/utf8>> -> - - Abs_seconds; - - _ -> - Abs_seconds - end. - --file("src/gleam/time/timestamp.gleam", 819). -?DOC( - " `julian_seconds_from_parts(year, month, day, hours, minutes, seconds)` \n" - " returns the number of Julian \n" - " seconds represented by the given arguments.\n" - " \n" - " Note: It is the callers responsibility to ensure the inputs are valid.\n" - " \n" - " See https://www.tondering.dk/claus/cal/julperiod.php#formula\n" -). --spec julian_seconds_from_parts( - integer(), - integer(), - integer(), - integer(), - integer(), - integer() -) -> integer(). -julian_seconds_from_parts(Year, Month, Day, Hours, Minutes, Seconds) -> - Julian_day_seconds = julian_day_from_ymd(Year, Month, Day) * 86400, - ((Julian_day_seconds + (Hours * 3600)) + (Minutes * 60)) + Seconds. - --file("src/gleam/time/timestamp.gleam", 662). --spec do_parse_second_fraction_as_nanoseconds(bitstring(), integer(), integer()) -> {ok, - {integer(), bitstring()}} | - {error, any()}. -do_parse_second_fraction_as_nanoseconds(Bytes, Acc, Power) -> - Power@1 = Power div 10, - case Bytes of - <> when ((16#30 =< Byte) andalso (Byte =< 16#39)) andalso (Power@1 < 1) -> - do_parse_second_fraction_as_nanoseconds( - Remaining_bytes, - Acc, - Power@1 - ); - - <> when (16#30 =< Byte@1) andalso (Byte@1 =< 16#39) -> - Digit = Byte@1 - 16#30, - do_parse_second_fraction_as_nanoseconds( - Remaining_bytes@1, - Acc + (Digit * Power@1), - Power@1 - ); - - _ -> - {ok, {Acc, Bytes}} - end. - --file("src/gleam/time/timestamp.gleam", 642). --spec parse_second_fraction_as_nanoseconds(bitstring()) -> {ok, - {integer(), bitstring()}} | - {error, nil}. -parse_second_fraction_as_nanoseconds(Bytes) -> - case Bytes of - <<"."/utf8, Byte, Remaining_bytes/binary>> when (16#30 =< Byte) andalso (Byte =< 16#39) -> - do_parse_second_fraction_as_nanoseconds( - <>, - 0, - 1000000000 - ); - - <<"."/utf8, _/binary>> -> - {error, nil}; - - _ -> - {ok, {0, Bytes}} - end. - --file("src/gleam/time/timestamp.gleam", 741). --spec do_parse_digits(bitstring(), integer(), integer(), integer()) -> {ok, - {integer(), bitstring()}} | - {error, nil}. -do_parse_digits(Bytes, Count, Acc, K) -> - case Bytes of - _ when K >= Count -> - {ok, {Acc, Bytes}}; - - <> when (16#30 =< Byte) andalso (Byte =< 16#39) -> - do_parse_digits( - Remaining_bytes, - Count, - (Acc * 10) + (Byte - 16#30), - K + 1 - ); - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 734). -?DOC(" Parse and return the given number of digits from the given bytes.\n"). --spec parse_digits(bitstring(), integer()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_digits(Bytes, Count) -> - do_parse_digits(Bytes, Count, 0, 0). - --file("src/gleam/time/timestamp.gleam", 573). --spec parse_year(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_year(Bytes) -> - parse_digits(Bytes, 4). - --file("src/gleam/time/timestamp.gleam", 577). --spec parse_month(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_month(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Month, Bytes@1} = _use0, - case (1 =< Month) andalso (Month =< 12) of - true -> - {ok, {Month, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 585). --spec parse_day(bitstring(), integer(), integer()) -> {ok, - {integer(), bitstring()}} | - {error, nil}. -parse_day(Bytes, Year, Month) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Day, Bytes@1} = _use0, - gleam@result:'try'(case Month of - 1 -> - {ok, 31}; - - 3 -> - {ok, 31}; - - 5 -> - {ok, 31}; - - 7 -> - {ok, 31}; - - 8 -> - {ok, 31}; - - 10 -> - {ok, 31}; - - 12 -> - {ok, 31}; - - 4 -> - {ok, 30}; - - 6 -> - {ok, 30}; - - 9 -> - {ok, 30}; - - 11 -> - {ok, 30}; - - 2 -> - case is_leap_year(Year) of - true -> - {ok, 29}; - - false -> - {ok, 28} - end; - - _ -> - {error, nil} - end, fun(Max_day) -> case (1 =< Day) andalso (Day =< Max_day) of - true -> - {ok, {Day, Bytes@1}}; - - false -> - {error, nil} - end end) - end - ). - --file("src/gleam/time/timestamp.gleam", 615). --spec parse_hours(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_hours(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Hours, Bytes@1} = _use0, - case (0 =< Hours) andalso (Hours =< 23) of - true -> - {ok, {Hours, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 623). --spec parse_minutes(bitstring()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_minutes(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Minutes, Bytes@1} = _use0, - case (0 =< Minutes) andalso (Minutes =< 59) of - true -> - {ok, {Minutes, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 631). --spec parse_seconds(bitstring()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_seconds(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Seconds, Bytes@1} = _use0, - case (0 =< Seconds) andalso (Seconds =< 60) of - true -> - {ok, {Seconds, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 704). --spec parse_numeric_offset(bitstring()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_numeric_offset(Bytes) -> - gleam@result:'try'( - parse_sign(Bytes), - fun(_use0) -> - {Sign, Bytes@1} = _use0, - gleam@result:'try'( - parse_hours(Bytes@1), - fun(_use0@1) -> - {Hours, Bytes@2} = _use0@1, - gleam@result:'try'( - accept_byte(Bytes@2, 16#3A), - fun(Bytes@3) -> - gleam@result:'try'( - parse_minutes(Bytes@3), - fun(_use0@2) -> - {Minutes, Bytes@4} = _use0@2, - Offset_seconds = offset_to_seconds( - Sign, - Hours, - Minutes - ), - {ok, {Offset_seconds, Bytes@4}} - end - ) - end - ) - end - ) - end - ). - --file("src/gleam/time/timestamp.gleam", 696). --spec parse_offset(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_offset(Bytes) -> - case Bytes of - <<"Z"/utf8, Remaining_bytes/binary>> -> - {ok, {0, Remaining_bytes}}; - - <<"z"/utf8, Remaining_bytes/binary>> -> - {ok, {0, Remaining_bytes}}; - - _ -> - parse_numeric_offset(Bytes) - end. - --file("src/gleam/time/timestamp.gleam", 769). --spec accept_date_time_separator(bitstring()) -> {ok, bitstring()} | - {error, nil}. -accept_date_time_separator(Bytes) -> - case Bytes of - <> when ((Byte =:= 16#54) orelse (Byte =:= 16#74)) orelse (Byte =:= 16#20) -> - {ok, Remaining_bytes}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 789). -?DOC(" Note: The caller of this function must ensure that all inputs are valid.\n"). --spec from_date_time( - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer() -) -> timestamp(). -from_date_time( - Year, - Month, - Day, - Hours, - Minutes, - Seconds, - Second_fraction_as_nanoseconds, - Offset_seconds -) -> - Julian_seconds = julian_seconds_from_parts( - Year, - Month, - Day, - Hours, - Minutes, - Seconds - ), - Julian_seconds_since_epoch = Julian_seconds - 210866803200, - _pipe = {timestamp, - Julian_seconds_since_epoch - Offset_seconds, - Second_fraction_as_nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/timestamp.gleam", 339). -?DOC( - " Create a `Timestamp` from a human-readable calendar time.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " timestamp.from_calendar(\n" - " date: calendar.Date(2024, calendar.December, 25),\n" - " time: calendar.TimeOfDay(12, 30, 50, 0),\n" - " offset: calendar.utc_offset,\n" - " )\n" - " |> timestamp.to_rfc3339(calendar.utc_offset)\n" - " // -> \"2024-12-25T12:30:50Z\"\n" - " ```\n" -). --spec from_calendar( - gleam@time@calendar:date(), - gleam@time@calendar:time_of_day(), - gleam@time@duration:duration() -) -> timestamp(). -from_calendar(Date, Time, Offset) -> - Month = case erlang:element(3, Date) of - january -> - 1; - - february -> - 2; - - march -> - 3; - - april -> - 4; - - may -> - 5; - - june -> - 6; - - july -> - 7; - - august -> - 8; - - september -> - 9; - - october -> - 10; - - november -> - 11; - - december -> - 12 - end, - from_date_time( - erlang:element(2, Date), - Month, - erlang:element(4, Date), - erlang:element(2, Time), - erlang:element(3, Time), - erlang:element(4, Time), - erlang:element(5, Time), - erlang:round(gleam@time@duration:to_seconds(Offset)) - ). - --file("src/gleam/time/timestamp.gleam", 533). -?DOC( - " Parses an [RFC 3339 formatted time string][spec] into a `Timestamp`.\n" - "\n" - " [spec]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6\n" - " \n" - " # Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(ts) = timestamp.parse_rfc3339(\"1970-01-01T00:00:01Z\")\n" - " timestamp.to_unix_seconds_and_nanoseconds(ts)\n" - " // -> #(1, 0)\n" - " ```\n" - " \n" - " Parsing an invalid timestamp returns an error.\n" - " \n" - " ```gleam\n" - " let assert Error(Nil) = timestamp.parse_rfc3339(\"1995-10-31\")\n" - " ```\n" - "\n" - " ## Time zones\n" - "\n" - " It may at first seem that the RFC 3339 format includes timezone\n" - " information, as it can specify an offset such as `Z` or `+3`, so why does\n" - " this function not return calendar time with a time zone? There are multiple\n" - " reasons:\n" - "\n" - " - RFC 3339's timestamp format is based on calendar time, but it is\n" - " unambigous, so it can be converted into epoch time when being parsed. It\n" - " is always better to internally use epoch time to represent unambiguous\n" - " points in time, so we perform that conversion as a convenience and to\n" - " ensure that programmers with less time experience don't accidentally use\n" - " a less suitable time representation.\n" - "\n" - " - RFC 3339's contains _calendar time offset_ information, not time zone\n" - " information. This is enough to convert it to an unambiguous timestamp,\n" - " but it is not enough information to reliably work with calendar time.\n" - " Without the time zone and the time zone database it's not possible to\n" - " know what time period that offset is valid for, so it cannot be used\n" - " without risk of bugs.\n" - "\n" - " ## Behaviour details\n" - " \n" - " - Follows the grammar specified in section 5.6 Internet Date/Time Format of \n" - " RFC 3339 .\n" - " - The `T` and `Z` characters may alternatively be lower case `t` or `z`, \n" - " respectively.\n" - " - Full dates and full times must be separated by `T` or `t`. A space is also \n" - " permitted.\n" - " - Leap seconds rules are not considered. That is, any timestamp may \n" - " specify digts `00` - `60` for the seconds.\n" - " - Any part of a fractional second that cannot be represented in the \n" - " nanosecond precision is tructated. That is, for the time string, \n" - " `\"1970-01-01T00:00:00.1234567899Z\"`, the fractional second `.1234567899` \n" - " will be represented as `123_456_789` in the `Timestamp`.\n" -). --spec parse_rfc3339(binary()) -> {ok, timestamp()} | {error, nil}. -parse_rfc3339(Input) -> - Bytes = gleam_stdlib:identity(Input), - gleam@result:'try'( - parse_year(Bytes), - fun(_use0) -> - {Year, Bytes@1} = _use0, - gleam@result:'try'( - accept_byte(Bytes@1, 16#2D), - fun(Bytes@2) -> - gleam@result:'try'( - parse_month(Bytes@2), - fun(_use0@1) -> - {Month, Bytes@3} = _use0@1, - gleam@result:'try'( - accept_byte(Bytes@3, 16#2D), - fun(Bytes@4) -> - gleam@result:'try'( - parse_day(Bytes@4, Year, Month), - fun(_use0@2) -> - {Day, Bytes@5} = _use0@2, - gleam@result:'try'( - accept_date_time_separator( - Bytes@5 - ), - fun(Bytes@6) -> - gleam@result:'try'( - parse_hours(Bytes@6), - fun(_use0@3) -> - {Hours, Bytes@7} = _use0@3, - gleam@result:'try'( - accept_byte( - Bytes@7, - 16#3A - ), - fun(Bytes@8) -> - gleam@result:'try'( - parse_minutes( - Bytes@8 - ), - fun( - _use0@4 - ) -> - {Minutes, - Bytes@9} = _use0@4, - gleam@result:'try'( - accept_byte( - Bytes@9, - 16#3A - ), - fun( - Bytes@10 - ) -> - gleam@result:'try'( - parse_seconds( - Bytes@10 - ), - fun( - _use0@5 - ) -> - {Seconds, - Bytes@11} = _use0@5, - gleam@result:'try'( - parse_second_fraction_as_nanoseconds( - Bytes@11 - ), - fun( - _use0@6 - ) -> - {Second_fraction_as_nanoseconds, - Bytes@12} = _use0@6, - gleam@result:'try'( - parse_offset( - Bytes@12 - ), - fun( - _use0@7 - ) -> - {Offset_seconds, - Bytes@13} = _use0@7, - gleam@result:'try'( - accept_empty( - Bytes@13 - ), - fun( - _use0@8 - ) -> - nil = _use0@8, - {ok, - from_date_time( - Year, - Month, - Day, - Hours, - Minutes, - Seconds, - Second_fraction_as_nanoseconds, - Offset_seconds - )} - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ). diff --git a/build/packages/gleam_time/src/gleam_time.app.src b/build/packages/gleam_time/src/gleam_time.app.src deleted file mode 100644 index 1e7cce4..0000000 --- a/build/packages/gleam_time/src/gleam_time.app.src +++ /dev/null @@ -1,12 +0,0 @@ -{application, gleam_time, [ - {vsn, "1.6.0"}, - {applications, [gleam_stdlib]}, - {description, "Work with time in Gleam!"}, - {modules, [gleam@time@calendar, - gleam@time@duration, - gleam@time@timestamp, - gleam_time@@main, - gleam_time_ffi, - gleam_time_test_ffi]}, - {registered, []} -]}. diff --git a/build/packages/gleam_time/src/gleam_time_ffi.erl b/build/packages/gleam_time/src/gleam_time_ffi.erl deleted file mode 100644 index 34d8c88..0000000 --- a/build/packages/gleam_time/src/gleam_time_ffi.erl +++ /dev/null @@ -1,12 +0,0 @@ --module(gleam_time_ffi). --export([system_time/0, local_time_offset_seconds/0]). - -system_time() -> - {0, erlang:system_time(nanosecond)}. - -local_time_offset_seconds() -> - Utc = calendar:universal_time(), - Local = calendar:local_time(), - UtcSeconds = calendar:datetime_to_gregorian_seconds(Utc), - LocalSeconds = calendar:datetime_to_gregorian_seconds(Local), - LocalSeconds - UtcSeconds. diff --git a/build/packages/gleam_time/src/gleam_time_ffi.mjs b/build/packages/gleam_time/src/gleam_time_ffi.mjs deleted file mode 100644 index 27d09aa..0000000 --- a/build/packages/gleam_time/src/gleam_time_ffi.mjs +++ /dev/null @@ -1,11 +0,0 @@ -export function system_time() { - const now = Date.now(); - const milliseconds = now % 1_000; - const nanoseconds = milliseconds * 1000_000; - const seconds = (now - milliseconds) / 1_000; - return [seconds, nanoseconds]; -} - -export function local_time_offset_seconds() { - return new Date().getTimezoneOffset() * -60; -} diff --git a/build/packages/gleeunit/LICENCE b/build/packages/gleeunit/LICENCE deleted file mode 100644 index c7967c3..0000000 --- a/build/packages/gleeunit/LICENCE +++ /dev/null @@ -1,191 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2021, Louis Pilfold . - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/build/packages/gleeunit/README.md b/build/packages/gleeunit/README.md deleted file mode 100644 index 4d81364..0000000 --- a/build/packages/gleeunit/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# gleeunit - -A simple test runner for Gleam, using EUnit on Erlang and a custom runner on JS. - -[![Package Version](https://img.shields.io/hexpm/v/gleeunit)](https://hex.pm/packages/gleeunit) -[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/gleeunit/) - - -```sh -gleam add gleeunit@1 --dev -``` -```gleam -// In test/yourapp_test.gleam -import gleeunit - -pub fn main() { - gleeunit.main() -} -``` - -Now any public function with a name ending in `_test` in the `test` directory -will be found and run as a test. - -```gleam -pub fn some_function_test() { - assert some_function() == "Hello!" -} -``` - -Run the tests by entering `gleam test` in the command line. - -### Deno - -If using the Deno JavaScript runtime, you will need to add the following to your -`gleam.toml`. - -```toml -[javascript.deno] -allow_read = [ - "gleam.toml", - "test", - "build", -] -``` diff --git a/build/packages/gleeunit/gleam.toml b/build/packages/gleeunit/gleam.toml deleted file mode 100644 index c7df0c5..0000000 --- a/build/packages/gleeunit/gleam.toml +++ /dev/null @@ -1,16 +0,0 @@ -name = "gleeunit" -version = "1.9.0" -licences = ["Apache-2.0"] -description = "A simple test runner for Gleam, using EUnit on Erlang" -repository = { type = "github", user = "lpil", repo = "gleeunit" } -links = [{ title = "Sponsor", href = "https://github.com/sponsors/lpil" }] -gleam = ">= 1.13.0" - -[javascript.deno] -allow_read = ["gleam.toml", "test", "build"] - -[dependencies] -gleam_stdlib = ">= 0.60.0 and < 1.0.0" - -[dev-dependencies] -testhelper = { "path" = "./testhelper" } diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Assert.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Assert.hrl deleted file mode 100644 index 9360941..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Assert.hrl +++ /dev/null @@ -1,6 +0,0 @@ --record(assert, { - start :: integer(), - 'end' :: integer(), - expression_start :: integer(), - kind :: gleeunit@internal@gleam_panic:assert_kind() -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_AssertedExpression.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_AssertedExpression.hrl deleted file mode 100644 index 812663c..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_AssertedExpression.hrl +++ /dev/null @@ -1,5 +0,0 @@ --record(asserted_expression, { - start :: integer(), - 'end' :: integer(), - kind :: gleeunit@internal@gleam_panic:expression_kind() -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_BinaryOperator.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_BinaryOperator.hrl deleted file mode 100644 index eee44c9..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_BinaryOperator.hrl +++ /dev/null @@ -1,5 +0,0 @@ --record(binary_operator, { - operator :: binary(), - left :: gleeunit@internal@gleam_panic:asserted_expression(), - right :: gleeunit@internal@gleam_panic:asserted_expression() -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl deleted file mode 100644 index e7ffaa0..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl +++ /dev/null @@ -1 +0,0 @@ --record(expression, {value :: gleam@dynamic:dynamic_()}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_FunctionCall.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_FunctionCall.hrl deleted file mode 100644 index 9d55488..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_FunctionCall.hrl +++ /dev/null @@ -1,3 +0,0 @@ --record(function_call, { - arguments :: list(gleeunit@internal@gleam_panic:asserted_expression()) -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_GleamPanic.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_GleamPanic.hrl deleted file mode 100644 index cf36764..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_GleamPanic.hrl +++ /dev/null @@ -1,8 +0,0 @@ --record(gleam_panic, { - message :: binary(), - file :: binary(), - module :: binary(), - function :: binary(), - line :: integer(), - kind :: gleeunit@internal@gleam_panic:panic_kind() -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_LetAssert.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_LetAssert.hrl deleted file mode 100644 index 11f865e..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_LetAssert.hrl +++ /dev/null @@ -1,7 +0,0 @@ --record(let_assert, { - start :: integer(), - 'end' :: integer(), - pattern_start :: integer(), - pattern_end :: integer(), - value :: gleam@dynamic:dynamic_() -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl deleted file mode 100644 index 2396489..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl +++ /dev/null @@ -1 +0,0 @@ --record(literal, {value :: gleam@dynamic:dynamic_()}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_OtherExpression.hrl b/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_OtherExpression.hrl deleted file mode 100644 index 0424990..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@gleam_panic_OtherExpression.hrl +++ /dev/null @@ -1,3 +0,0 @@ --record(other_expression, { - expression :: gleeunit@internal@gleam_panic:asserted_expression() -}). diff --git a/build/packages/gleeunit/include/gleeunit@internal@reporting_State.hrl b/build/packages/gleeunit/include/gleeunit@internal@reporting_State.hrl deleted file mode 100644 index 575ccce..0000000 --- a/build/packages/gleeunit/include/gleeunit@internal@reporting_State.hrl +++ /dev/null @@ -1 +0,0 @@ --record(state, {passed :: integer(), failed :: integer(), skipped :: integer()}). diff --git a/build/packages/gleeunit/src/gleeunit.app.src b/build/packages/gleeunit/src/gleeunit.app.src deleted file mode 100644 index e72987c..0000000 --- a/build/packages/gleeunit/src/gleeunit.app.src +++ /dev/null @@ -1,16 +0,0 @@ -{application, gleeunit, [ - {vsn, "1.9.0"}, - {applications, [gleam_stdlib]}, - {description, "A simple test runner for Gleam, using EUnit on Erlang"}, - {modules, [erlang_test_module, - gleeunit, - gleeunit@@main, - gleeunit@internal@gleam_panic, - gleeunit@internal@reporting, - gleeunit@should, - gleeunit_ffi, - gleeunit_gleam_panic_ffi, - gleeunit_progress, - gleeunit_test_ffi]}, - {registered, []} -]}. diff --git a/build/packages/gleeunit/src/gleeunit.erl b/build/packages/gleeunit/src/gleeunit.erl deleted file mode 100644 index bcb58b6..0000000 --- a/build/packages/gleeunit/src/gleeunit.erl +++ /dev/null @@ -1,89 +0,0 @@ --module(gleeunit). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit.gleam"). --export([main/0]). --export_type([atom_/0, encoding/0, report_module_name/0, gleeunit_progress_option/0, eunit_option/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type atom_() :: any(). - --type encoding() :: utf8. - --type report_module_name() :: gleeunit_progress. - --type gleeunit_progress_option() :: {colored, boolean()}. - --type eunit_option() :: verbose | - no_tty | - {report, {report_module_name(), list(gleeunit_progress_option())}} | - {scale_timeouts, integer()}. - --file("src/gleeunit.gleam", 42). --spec gleam_to_erlang_module_name(binary()) -> binary(). -gleam_to_erlang_module_name(Path) -> - case gleam_stdlib:string_ends_with(Path, <<".gleam"/utf8>>) of - true -> - _pipe = Path, - _pipe@1 = gleam@string:replace( - _pipe, - <<".gleam"/utf8>>, - <<""/utf8>> - ), - gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"@"/utf8>>); - - false -> - _pipe@2 = Path, - _pipe@3 = gleam@string:split(_pipe@2, <<"/"/utf8>>), - _pipe@4 = gleam@list:last(_pipe@3), - _pipe@5 = gleam@result:unwrap(_pipe@4, Path), - gleam@string:replace(_pipe@5, <<".erl"/utf8>>, <<""/utf8>>) - end. - --file("src/gleeunit.gleam", 18). --spec do_main() -> nil. -do_main() -> - Options = [verbose, - no_tty, - {report, {gleeunit_progress, [{colored, true}]}}, - {scale_timeouts, 10}], - Result = begin - _pipe = gleeunit_ffi:find_files( - <<"**/*.{erl,gleam}"/utf8>>, - <<"test"/utf8>> - ), - _pipe@1 = gleam@list:map(_pipe, fun gleam_to_erlang_module_name/1), - _pipe@2 = gleam@list:map( - _pipe@1, - fun(_capture) -> erlang:binary_to_atom(_capture, utf8) end - ), - gleeunit_ffi:run_eunit(_pipe@2, Options) - end, - Code = case Result of - {ok, _} -> - 0; - - {error, _} -> - 1 - end, - erlang:halt(Code). - --file("src/gleeunit.gleam", 13). -?DOC( - " Find and run all test functions for the current project using Erlang's EUnit\n" - " test framework, or a custom JavaScript test runner.\n" - "\n" - " Any Erlang or Gleam function in the `test` directory with a name ending in\n" - " `_test` is considered a test function and will be run.\n" - "\n" - " A test that panics is considered a failure.\n" -). --spec main() -> nil. -main() -> - do_main(). diff --git a/build/packages/gleeunit/src/gleeunit.gleam b/build/packages/gleeunit/src/gleeunit.gleam deleted file mode 100644 index 7d3155e..0000000 --- a/build/packages/gleeunit/src/gleeunit.gleam +++ /dev/null @@ -1,86 +0,0 @@ -import gleam/list -import gleam/result -import gleam/string - -/// Find and run all test functions for the current project using Erlang's EUnit -/// test framework, or a custom JavaScript test runner. -/// -/// Any Erlang or Gleam function in the `test` directory with a name ending in -/// `_test` is considered a test function and will be run. -/// -/// A test that panics is considered a failure. -/// -pub fn main() -> Nil { - do_main() -} - -@external(javascript, "./gleeunit_ffi.mjs", "main") -fn do_main() -> Nil { - let options = [ - Verbose, - NoTty, - Report(#(GleeunitProgress, [Colored(True)])), - ScaleTimeouts(10), - ] - - let result = - find_files(matching: "**/*.{erl,gleam}", in: "test") - |> list.map(gleam_to_erlang_module_name) - |> list.map(dangerously_convert_string_to_atom(_, Utf8)) - |> run_eunit(options) - - let code = case result { - Ok(_) -> 0 - Error(_) -> 1 - } - halt(code) -} - -@external(erlang, "erlang", "halt") -fn halt(a: Int) -> Nil - -fn gleam_to_erlang_module_name(path: String) -> String { - case string.ends_with(path, ".gleam") { - True -> - path - |> string.replace(".gleam", "") - |> string.replace("/", "@") - - False -> - path - |> string.split("/") - |> list.last - |> result.unwrap(path) - |> string.replace(".erl", "") - } -} - -@external(erlang, "gleeunit_ffi", "find_files") -fn find_files(matching matching: String, in in: String) -> List(String) - -type Atom - -type Encoding { - Utf8 -} - -@external(erlang, "erlang", "binary_to_atom") -fn dangerously_convert_string_to_atom(a: String, b: Encoding) -> Atom - -type ReportModuleName { - GleeunitProgress -} - -type GleeunitProgressOption { - Colored(Bool) -} - -type EunitOption { - Verbose - NoTty - Report(#(ReportModuleName, List(GleeunitProgressOption))) - ScaleTimeouts(Int) -} - -@external(erlang, "gleeunit_ffi", "run_eunit") -fn run_eunit(a: List(Atom), b: List(EunitOption)) -> Result(Nil, a) diff --git a/build/packages/gleeunit/src/gleeunit/internal/gleam_panic.gleam b/build/packages/gleeunit/src/gleeunit/internal/gleam_panic.gleam deleted file mode 100644 index 6a5d309..0000000 --- a/build/packages/gleeunit/src/gleeunit/internal/gleam_panic.gleam +++ /dev/null @@ -1,49 +0,0 @@ -import gleam/dynamic - -pub type GleamPanic { - GleamPanic( - message: String, - file: String, - module: String, - function: String, - line: Int, - kind: PanicKind, - ) -} - -pub type PanicKind { - Todo - Panic - LetAssert( - start: Int, - end: Int, - pattern_start: Int, - pattern_end: Int, - value: dynamic.Dynamic, - ) - Assert(start: Int, end: Int, expression_start: Int, kind: AssertKind) -} - -pub type AssertKind { - BinaryOperator( - operator: String, - left: AssertedExpression, - right: AssertedExpression, - ) - FunctionCall(arguments: List(AssertedExpression)) - OtherExpression(expression: AssertedExpression) -} - -pub type AssertedExpression { - AssertedExpression(start: Int, end: Int, kind: ExpressionKind) -} - -pub type ExpressionKind { - Literal(value: dynamic.Dynamic) - Expression(value: dynamic.Dynamic) - Unevaluated -} - -@external(erlang, "gleeunit_gleam_panic_ffi", "from_dynamic") -@external(javascript, "./gleeunit_gleam_panic_ffi.mjs", "from_dynamic") -pub fn from_dynamic(data: dynamic.Dynamic) -> Result(GleamPanic, Nil) diff --git a/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.erl b/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.erl deleted file mode 100644 index d78f5e5..0000000 --- a/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(gleeunit_gleam_panic_ffi). --export([from_dynamic/1]). - -from_dynamic(#{ - gleam_error := assert, - start := Start, - 'end' := End, - expression_start := EStart -} = E) -> - wrap(E, {assert, Start, End, EStart, assert_kind(E)}); -from_dynamic(#{ - gleam_error := let_assert, - start := Start, - 'end' := End, - pattern_start := PStart, - pattern_end := PEnd, - value := Value -} = E) -> - wrap(E, {let_assert, Start, End, PStart, PEnd, Value}); -from_dynamic(#{gleam_error := panic} = E) -> - wrap(E, panic); -from_dynamic(#{gleam_error := todo} = E) -> - wrap(E, todo); -from_dynamic(_) -> - {error, nil}. - -assert_kind(#{kind := binary_operator, left := L, right := R, operator := O}) -> - {binary_operator, atom_to_binary(O), expression(L), expression(R)}; -assert_kind(#{kind := function_call, arguments := Arguments}) -> - {function_call, lists:map(fun expression/1, Arguments)}; -assert_kind(#{kind := expression, expression := Expression}) -> - {other_expression, expression(Expression)}. - -expression(#{start := S, 'end' := E, kind := literal, value := Value}) -> - {asserted_expression, S, E, {literal, Value}}; -expression(#{start := S, 'end' := E, kind := expression, value := Value}) -> - {asserted_expression, S, E, {expression, Value}}; -expression(#{start := S, 'end' := E, kind := unevaluated}) -> - {asserted_expression, S, E, unevaluated}. - -wrap(#{ - gleam_error := _, - file := File, - message := Message, - module := Module, - function := Function, - line := Line -}, Kind) -> - {ok, {gleam_panic, Message, File, Module, Function, Line, Kind}}. diff --git a/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs b/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs deleted file mode 100644 index 03f6025..0000000 --- a/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import { Result$Ok, Result$Error, List$Empty, List$NonEmpty } from "../../gleam.mjs"; -import { - GleamPanic$GleamPanic, - PanicKind$Todo, - PanicKind$Panic, - PanicKind$LetAssert, - PanicKind$Assert, - AssertKind$BinaryOperator, - AssertKind$FunctionCall, - AssertKind$OtherExpression, - AssertedExpression$AssertedExpression, - ExpressionKind$Literal, - ExpressionKind$Expression, - ExpressionKind$Unevaluated, -} from "./gleam_panic.mjs"; - -export function from_dynamic(error) { - if (!(error instanceof globalThis.Error) || !error.gleam_error) { - return Result$Error(undefined); - } - - if (error.gleam_error === "todo") { - return wrap(error, PanicKind$Todo()); - } - - if (error.gleam_error === "panic") { - return wrap(error, PanicKind$Panic()); - } - - if (error.gleam_error === "let_assert") { - let kind = PanicKind$LetAssert( - error.start, - error.end, - error.pattern_start, - error.pattern_end, - error.value, - ); - return wrap(error, kind); - } - - if (error.gleam_error === "assert") { - let kind = PanicKind$Assert( - error.start, - error.end, - error.expression_start, - assert_kind(error), - ); - return wrap(error, kind); - } - - return Result$Error(undefined); -} - -function assert_kind(error) { - if (error.kind == "binary_operator") { - return AssertKind$BinaryOperator( - error.operator, - expression(error.left), - expression(error.right), - ); - } - - if (error.kind == "function_call") { - let list = List$Empty(); - let i = error.arguments.length; - while (i--) { - list = List$NonEmpty(expression(error.arguments[i]), list); - } - return AssertKind$FunctionCall(list); - } - - return AssertKind$OtherExpression(expression(error.expression)); -} - -function expression(data) { - const expression = AssertedExpression$AssertedExpression(data.start, data.end, undefined); - if (data.kind == "literal") { - expression.kind = ExpressionKind$Literal(data.value); - } else if (data.kind == "expression") { - expression.kind = ExpressionKind$Expression(data.value); - } else { - expression.kind = ExpressionKind$Unevaluated(); - } - return expression; -} - -function wrap(e, kind) { - return Result$Ok( - GleamPanic$GleamPanic(e.message, e.file, e.module, e.function, e.line, kind), - ); -} diff --git a/build/packages/gleeunit/src/gleeunit/internal/reporting.gleam b/build/packages/gleeunit/src/gleeunit/internal/reporting.gleam deleted file mode 100644 index 72f766f..0000000 --- a/build/packages/gleeunit/src/gleeunit/internal/reporting.gleam +++ /dev/null @@ -1,240 +0,0 @@ -import gleam/bit_array -import gleam/dynamic -import gleam/int -import gleam/io -import gleam/list -import gleam/option.{type Option} -import gleam/result -import gleam/string -import gleeunit/internal/gleam_panic.{type GleamPanic} - -pub type State { - State(passed: Int, failed: Int, skipped: Int) -} - -pub fn new_state() -> State { - State(passed: 0, failed: 0, skipped: 0) -} - -pub fn finished(state: State) -> Int { - case state { - State(passed: 0, failed: 0, skipped: 0) -> { - io.println("\nNo tests found!") - 1 - } - State(failed: 0, skipped: 0, ..) -> { - let message = - "\n" <> int.to_string(state.passed) <> " passed, no failures" - io.println(green(message)) - 0 - } - State(skipped: 0, ..) -> { - let message = - "\n" - <> int.to_string(state.passed) - <> " passed, " - <> int.to_string(state.failed) - <> " failures" - io.println(red(message)) - 1 - } - State(failed: 0, ..) -> { - let message = - "\n" - <> int.to_string(state.passed) - <> " passed, 0 failures, " - <> int.to_string(state.skipped) - <> " skipped" - io.println(yellow(message)) - 1 - } - State(..) -> { - let message = - "\n" - <> int.to_string(state.passed) - <> " passed, " - <> int.to_string(state.failed) - <> " failures, " - <> int.to_string(state.skipped) - <> " skipped" - io.println(red(message)) - 1 - } - } -} - -pub fn test_passed(state: State) -> State { - io.print(green(".")) - State(..state, passed: state.passed + 1) -} - -pub fn test_failed( - state: State, - module: String, - function: String, - error: dynamic.Dynamic, -) -> State { - let message = case gleam_panic.from_dynamic(error) { - Ok(error) -> { - let src = option.from_result(read_file(error.file)) - format_gleam_error(error, module, function, src) - } - Error(_) -> format_unknown(module, function, error) - } - - io.print("\n" <> message) - State(..state, failed: state.failed + 1) -} - -pub fn eunit_missing() -> Result(never, Nil) { - let message = bold(red("Error")) <> ": EUnit libraries not found. - -Your Erlang installation seems to be incomplete. If you installed Erlang using -a package manager ensure that you have installed the full Erlang -distribution instead of a stripped-down version. -" - io.print_error(message) - Error(Nil) -} - -fn format_unknown( - module: String, - function: String, - error: dynamic.Dynamic, -) -> String { - string.concat([ - grey(module <> "." <> function) <> "\n", - "An unexpected error occurred:\n", - "\n", - " " <> string.inspect(error) <> "\n", - ]) -} - -fn format_gleam_error( - error: GleamPanic, - module: String, - function: String, - src: Option(BitArray), -) -> String { - let location = grey(error.file <> ":" <> int.to_string(error.line)) - - case error.kind { - gleam_panic.Panic -> { - string.concat([ - bold(red("panic")) <> " " <> location <> "\n", - cyan(" test") <> ": " <> module <> "." <> function <> "\n", - cyan(" info") <> ": " <> error.message <> "\n", - ]) - } - - gleam_panic.Todo -> { - string.concat([ - bold(yellow("todo")) <> " " <> location <> "\n", - cyan(" test") <> ": " <> module <> "." <> function <> "\n", - cyan(" info") <> ": " <> error.message <> "\n", - ]) - } - - gleam_panic.Assert(start:, end:, kind:, ..) -> { - string.concat([ - bold(red("assert")) <> " " <> location <> "\n", - cyan(" test") <> ": " <> module <> "." <> function <> "\n", - code_snippet(src, start, end), - assert_info(kind), - cyan(" info") <> ": " <> error.message <> "\n", - ]) - } - - gleam_panic.LetAssert(start:, end:, value:, ..) -> { - string.concat([ - bold(red("let assert")) <> " " <> location <> "\n", - cyan(" test") <> ": " <> module <> "." <> function <> "\n", - code_snippet(src, start, end), - cyan("value") <> ": " <> string.inspect(value) <> "\n", - cyan(" info") <> ": " <> error.message <> "\n", - ]) - } - } -} - -fn assert_info(kind: gleam_panic.AssertKind) -> String { - case kind { - gleam_panic.BinaryOperator(left:, right:, ..) -> { - string.concat([assert_value(" left", left), assert_value("right", right)]) - } - - gleam_panic.FunctionCall(arguments:) -> { - arguments - |> list.index_map(fn(e, i) { - let number = string.pad_start(int.to_string(i), 5, " ") - assert_value(number, e) - }) - |> string.concat - } - - gleam_panic.OtherExpression(..) -> "" - } -} - -fn assert_value(name: String, value: gleam_panic.AssertedExpression) -> String { - cyan(name) <> ": " <> inspect_value(value) <> "\n" -} - -fn inspect_value(value: gleam_panic.AssertedExpression) -> String { - case value.kind { - gleam_panic.Unevaluated -> grey("unevaluated") - gleam_panic.Literal(..) -> grey("literal") - gleam_panic.Expression(value:) -> string.inspect(value) - } -} - -fn code_snippet(src: Option(BitArray), start: Int, end: Int) -> String { - { - use src <- result.try(option.to_result(src, Nil)) - use snippet <- result.try(bit_array.slice(src, start, end - start)) - use snippet <- result.try(bit_array.to_string(snippet)) - let snippet = cyan(" code") <> ": " <> snippet <> "\n" - Ok(snippet) - } - |> result.unwrap("") -} - -pub fn test_skipped(state: State, module: String, function: String) -> State { - io.print("\n" <> module <> "." <> function <> yellow(" skipped")) - State(..state, skipped: state.skipped + 1) -} - -fn bold(text: String) -> String { - "\u{001b}[1m" <> text <> "\u{001b}[22m" -} - -fn cyan(text: String) -> String { - "\u{001b}[36m" <> text <> "\u{001b}[39m" -} - -fn yellow(text: String) -> String { - "\u{001b}[33m" <> text <> "\u{001b}[39m" -} - -fn green(text: String) -> String { - "\u{001b}[32m" <> text <> "\u{001b}[39m" -} - -fn red(text: String) -> String { - "\u{001b}[31m" <> text <> "\u{001b}[39m" -} - -fn grey(text: String) -> String { - "\u{001b}[90m" <> text <> "\u{001b}[39m" -} - -@external(erlang, "file", "read_file") -fn read_file(path: String) -> Result(BitArray, dynamic.Dynamic) { - case read_file_text(path) { - Ok(text) -> Ok(bit_array.from_string(text)) - Error(e) -> Error(e) - } -} - -@external(javascript, "../../gleeunit_ffi.mjs", "read_file") -fn read_file_text(path: String) -> Result(String, dynamic.Dynamic) diff --git a/build/packages/gleeunit/src/gleeunit/should.gleam b/build/packages/gleeunit/src/gleeunit/should.gleam deleted file mode 100644 index 99cd16c..0000000 --- a/build/packages/gleeunit/src/gleeunit/should.gleam +++ /dev/null @@ -1,72 +0,0 @@ -//// Use the `assert` keyword instead of this module. - -import gleam/option.{type Option, None, Some} -import gleam/string - -pub fn equal(a: t, b: t) -> Nil { - case a == b { - True -> Nil - _ -> - panic as string.concat([ - "\n", - string.inspect(a), - "\nshould equal\n", - string.inspect(b), - ]) - } -} - -pub fn not_equal(a: t, b: t) -> Nil { - case a != b { - True -> Nil - _ -> - panic as string.concat([ - "\n", - string.inspect(a), - "\nshould not equal\n", - string.inspect(b), - ]) - } -} - -pub fn be_ok(a: Result(a, e)) -> a { - case a { - Ok(value) -> value - _ -> panic as string.concat(["\n", string.inspect(a), "\nshould be ok"]) - } -} - -pub fn be_error(a: Result(a, e)) -> e { - case a { - Error(error) -> error - _ -> panic as string.concat(["\n", string.inspect(a), "\nshould be error"]) - } -} - -pub fn be_some(a: Option(a)) -> a { - case a { - Some(value) -> value - _ -> panic as string.concat(["\n", string.inspect(a), "\nshould be some"]) - } -} - -pub fn be_none(a: Option(a)) -> Nil { - case a { - None -> Nil - _ -> panic as string.concat(["\n", string.inspect(a), "\nshould be none"]) - } -} - -pub fn be_true(actual: Bool) -> Nil { - actual - |> equal(True) -} - -pub fn be_false(actual: Bool) -> Nil { - actual - |> equal(False) -} - -pub fn fail() -> Nil { - be_true(False) -} diff --git a/build/packages/gleeunit/src/gleeunit@internal@gleam_panic.erl b/build/packages/gleeunit/src/gleeunit@internal@gleam_panic.erl deleted file mode 100644 index 398ea7d..0000000 --- a/build/packages/gleeunit/src/gleeunit@internal@gleam_panic.erl +++ /dev/null @@ -1,56 +0,0 @@ --module(gleeunit@internal@gleam_panic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/internal/gleam_panic.gleam"). --export([from_dynamic/1]). --export_type([gleam_panic/0, panic_kind/0, assert_kind/0, asserted_expression/0, expression_kind/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(false). - --type gleam_panic() :: {gleam_panic, - binary(), - binary(), - binary(), - binary(), - integer(), - panic_kind()}. - --type panic_kind() :: todo | - panic | - {let_assert, - integer(), - integer(), - integer(), - integer(), - gleam@dynamic:dynamic_()} | - {assert, integer(), integer(), integer(), assert_kind()}. - --type assert_kind() :: {binary_operator, - binary(), - asserted_expression(), - asserted_expression()} | - {function_call, list(asserted_expression())} | - {other_expression, asserted_expression()}. - --type asserted_expression() :: {asserted_expression, - integer(), - integer(), - expression_kind()}. - --type expression_kind() :: {literal, gleam@dynamic:dynamic_()} | - {expression, gleam@dynamic:dynamic_()} | - unevaluated. - --file("src/gleeunit/internal/gleam_panic.gleam", 49). -?DOC(false). --spec from_dynamic(gleam@dynamic:dynamic_()) -> {ok, gleam_panic()} | - {error, nil}. -from_dynamic(Data) -> - gleeunit_gleam_panic_ffi:from_dynamic(Data). diff --git a/build/packages/gleeunit/src/gleeunit@internal@reporting.erl b/build/packages/gleeunit/src/gleeunit@internal@reporting.erl deleted file mode 100644 index 8c37c79..0000000 --- a/build/packages/gleeunit/src/gleeunit@internal@reporting.erl +++ /dev/null @@ -1,343 +0,0 @@ --module(gleeunit@internal@reporting). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/internal/reporting.gleam"). --export([new_state/0, test_skipped/3, test_passed/1, finished/1, eunit_missing/0, test_failed/4]). --export_type([state/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(false). - --type state() :: {state, integer(), integer(), integer()}. - --file("src/gleeunit/internal/reporting.gleam", 15). -?DOC(false). --spec new_state() -> state(). -new_state() -> - {state, 0, 0, 0}. - --file("src/gleeunit/internal/reporting.gleam", 207). -?DOC(false). --spec bold(binary()) -> binary(). -bold(Text) -> - <<<<"\x{001b}[1m"/utf8, Text/binary>>/binary, "\x{001b}[22m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 211). -?DOC(false). --spec cyan(binary()) -> binary(). -cyan(Text) -> - <<<<"\x{001b}[36m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 191). -?DOC(false). --spec code_snippet(gleam@option:option(bitstring()), integer(), integer()) -> binary(). -code_snippet(Src, Start, End) -> - _pipe = begin - gleam@result:'try'( - gleam@option:to_result(Src, nil), - fun(Src@1) -> - gleam@result:'try'( - gleam_stdlib:bit_array_slice(Src@1, Start, End - Start), - fun(Snippet) -> - gleam@result:'try'( - gleam@bit_array:to_string(Snippet), - fun(Snippet@1) -> - Snippet@2 = <<<<<<(cyan(<<" code"/utf8>>))/binary, - ": "/utf8>>/binary, - Snippet@1/binary>>/binary, - "\n"/utf8>>, - {ok, Snippet@2} - end - ) - end - ) - end - ) - end, - gleam@result:unwrap(_pipe, <<""/utf8>>). - --file("src/gleeunit/internal/reporting.gleam", 215). -?DOC(false). --spec yellow(binary()) -> binary(). -yellow(Text) -> - <<<<"\x{001b}[33m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 202). -?DOC(false). --spec test_skipped(state(), binary(), binary()) -> state(). -test_skipped(State, Module, Function) -> - gleam_stdlib:print( - <<<<<<<<"\n"/utf8, Module/binary>>/binary, "."/utf8>>/binary, - Function/binary>>/binary, - (yellow(<<" skipped"/utf8>>))/binary>> - ), - {state, - erlang:element(2, State), - erlang:element(3, State), - erlang:element(4, State) + 1}. - --file("src/gleeunit/internal/reporting.gleam", 219). -?DOC(false). --spec green(binary()) -> binary(). -green(Text) -> - <<<<"\x{001b}[32m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 66). -?DOC(false). --spec test_passed(state()) -> state(). -test_passed(State) -> - gleam_stdlib:print(green(<<"."/utf8>>)), - {state, - erlang:element(2, State) + 1, - erlang:element(3, State), - erlang:element(4, State)}. - --file("src/gleeunit/internal/reporting.gleam", 223). -?DOC(false). --spec red(binary()) -> binary(). -red(Text) -> - <<<<"\x{001b}[31m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 19). -?DOC(false). --spec finished(state()) -> integer(). -finished(State) -> - case State of - {state, 0, 0, 0} -> - gleam_stdlib:println(<<"\nNo tests found!"/utf8>>), - 1; - - {state, _, 0, 0} -> - Message = <<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, no failures"/utf8>>, - gleam_stdlib:println(green(Message)), - 0; - - {state, _, _, 0} -> - Message@1 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures"/utf8>>, - gleam_stdlib:println(red(Message@1)), - 1; - - {state, _, 0, _} -> - Message@2 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, 0 failures, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(4, State)))/binary>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(yellow(Message@2)), - 1; - - {state, _, _, _} -> - Message@3 = <<<<<<<<<<<<"\n"/utf8, - (erlang:integer_to_binary( - erlang:element(2, State) - ))/binary>>/binary, - " passed, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(4, State)))/binary>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(red(Message@3)), - 1 - end. - --file("src/gleeunit/internal/reporting.gleam", 89). -?DOC(false). --spec eunit_missing() -> {ok, any()} | {error, nil}. -eunit_missing() -> - Message = <<(bold(red(<<"Error"/utf8>>)))/binary, - ": EUnit libraries not found. - -Your Erlang installation seems to be incomplete. If you installed Erlang using -a package manager ensure that you have installed the full Erlang -distribution instead of a stripped-down version. -"/utf8>>, - gleam_stdlib:print_error(Message), - {error, nil}. - --file("src/gleeunit/internal/reporting.gleam", 227). -?DOC(false). --spec grey(binary()) -> binary(). -grey(Text) -> - <<<<"\x{001b}[90m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 100). -?DOC(false). --spec format_unknown(binary(), binary(), gleam@dynamic:dynamic_()) -> binary(). -format_unknown(Module, Function, Error) -> - erlang:list_to_binary( - [<<(grey(<<<>/binary, Function/binary>>))/binary, - "\n"/utf8>>, - <<"An unexpected error occurred:\n"/utf8>>, - <<"\n"/utf8>>, - <<<<" "/utf8, (gleam@string:inspect(Error))/binary>>/binary, - "\n"/utf8>>] - ). - --file("src/gleeunit/internal/reporting.gleam", 183). -?DOC(false). --spec inspect_value(gleeunit@internal@gleam_panic:asserted_expression()) -> binary(). -inspect_value(Value) -> - case erlang:element(4, Value) of - unevaluated -> - grey(<<"unevaluated"/utf8>>); - - {literal, _} -> - grey(<<"literal"/utf8>>); - - {expression, Value@1} -> - gleam@string:inspect(Value@1) - end. - --file("src/gleeunit/internal/reporting.gleam", 179). -?DOC(false). --spec assert_value( - binary(), - gleeunit@internal@gleam_panic:asserted_expression() -) -> binary(). -assert_value(Name, Value) -> - <<<<<<(cyan(Name))/binary, ": "/utf8>>/binary, - (inspect_value(Value))/binary>>/binary, - "\n"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 160). -?DOC(false). --spec assert_info(gleeunit@internal@gleam_panic:assert_kind()) -> binary(). -assert_info(Kind) -> - case Kind of - {binary_operator, _, Left, Right} -> - erlang:list_to_binary( - [assert_value(<<" left"/utf8>>, Left), - assert_value(<<"right"/utf8>>, Right)] - ); - - {function_call, Arguments} -> - _pipe = Arguments, - _pipe@1 = gleam@list:index_map( - _pipe, - fun(E, I) -> - Number = gleam@string:pad_start( - erlang:integer_to_binary(I), - 5, - <<" "/utf8>> - ), - assert_value(Number, E) - end - ), - erlang:list_to_binary(_pipe@1); - - {other_expression, _} -> - <<""/utf8>> - end. - --file("src/gleeunit/internal/reporting.gleam", 113). -?DOC(false). --spec format_gleam_error( - gleeunit@internal@gleam_panic:gleam_panic(), - binary(), - binary(), - gleam@option:option(bitstring()) -) -> binary(). -format_gleam_error(Error, Module, Function, Src) -> - Location = grey( - <<<<(erlang:element(3, Error))/binary, ":"/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(6, Error)))/binary>> - ), - case erlang:element(7, Error) of - panic -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"panic"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - todo -> - erlang:list_to_binary( - [<<<<<<(bold(yellow(<<"todo"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - {assert, Start, End, _, Kind} -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"assert"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - code_snippet(Src, Start, End), - assert_info(Kind), - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - {let_assert, Start@1, End@1, _, _, Value} -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"let assert"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - code_snippet(Src, Start@1, End@1), - <<<<<<(cyan(<<"value"/utf8>>))/binary, ": "/utf8>>/binary, - (gleam@string:inspect(Value))/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ) - end. - --file("src/gleeunit/internal/reporting.gleam", 71). -?DOC(false). --spec test_failed(state(), binary(), binary(), gleam@dynamic:dynamic_()) -> state(). -test_failed(State, Module, Function, Error) -> - Message = case gleeunit_gleam_panic_ffi:from_dynamic(Error) of - {ok, Error@1} -> - Src = gleam@option:from_result( - file:read_file(erlang:element(3, Error@1)) - ), - format_gleam_error(Error@1, Module, Function, Src); - - {error, _} -> - format_unknown(Module, Function, Error) - end, - gleam_stdlib:print(<<"\n"/utf8, Message/binary>>), - {state, - erlang:element(2, State), - erlang:element(3, State) + 1, - erlang:element(4, State)}. diff --git a/build/packages/gleeunit/src/gleeunit@should.erl b/build/packages/gleeunit/src/gleeunit@should.erl deleted file mode 100644 index 81048de..0000000 --- a/build/packages/gleeunit/src/gleeunit@should.erl +++ /dev/null @@ -1,153 +0,0 @@ --module(gleeunit@should). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/should.gleam"). --export([equal/2, not_equal/2, be_ok/1, be_error/1, be_some/1, be_none/1, be_true/1, be_false/1, fail/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(" Use the `assert` keyword instead of this module.\n"). - --file("src/gleeunit/should.gleam", 6). --spec equal(DOF, DOF) -> nil. -equal(A, B) -> - case A =:= B of - true -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould equal\n"/utf8>>, - gleam@string:inspect(B)] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"equal"/utf8>>, - line => 10}) - end. - --file("src/gleeunit/should.gleam", 19). --spec not_equal(DOG, DOG) -> nil. -not_equal(A, B) -> - case A /= B of - true -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould not equal\n"/utf8>>, - gleam@string:inspect(B)] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"not_equal"/utf8>>, - line => 23}) - end. - --file("src/gleeunit/should.gleam", 32). --spec be_ok({ok, DOH} | {error, any()}) -> DOH. -be_ok(A) -> - case A of - {ok, Value} -> - Value; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be ok"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_ok"/utf8>>, - line => 35}) - end. - --file("src/gleeunit/should.gleam", 39). --spec be_error({ok, any()} | {error, DOM}) -> DOM. -be_error(A) -> - case A of - {error, Error} -> - Error; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be error"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_error"/utf8>>, - line => 42}) - end. - --file("src/gleeunit/should.gleam", 46). --spec be_some(gleam@option:option(DOP)) -> DOP. -be_some(A) -> - case A of - {some, Value} -> - Value; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be some"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_some"/utf8>>, - line => 49}) - end. - --file("src/gleeunit/should.gleam", 53). --spec be_none(gleam@option:option(any())) -> nil. -be_none(A) -> - case A of - none -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be none"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_none"/utf8>>, - line => 56}) - end. - --file("src/gleeunit/should.gleam", 60). --spec be_true(boolean()) -> nil. -be_true(Actual) -> - _pipe = Actual, - equal(_pipe, true). - --file("src/gleeunit/should.gleam", 65). --spec be_false(boolean()) -> nil. -be_false(Actual) -> - _pipe = Actual, - equal(_pipe, false). - --file("src/gleeunit/should.gleam", 70). --spec fail() -> nil. -fail() -> - be_true(false). diff --git a/build/packages/gleeunit/src/gleeunit_ffi.erl b/build/packages/gleeunit/src/gleeunit_ffi.erl deleted file mode 100644 index 05c7490..0000000 --- a/build/packages/gleeunit/src/gleeunit_ffi.erl +++ /dev/null @@ -1,21 +0,0 @@ --module(gleeunit_ffi). - --export([find_files/2, run_eunit/2]). - -find_files(Pattern, In) -> - Results = filelib:wildcard(binary_to_list(Pattern), binary_to_list(In)), - lists:map(fun list_to_binary/1, Results). - -run_eunit(Tests, Options) -> - case code:which(eunit) of - non_existing -> - gleeunit@internal@reporting:eunit_missing(); - - _ -> - case eunit:test(Tests, Options) of - ok -> {ok, nil}; - error -> {error, nil}; - {error, Term} -> {error, Term} - end - end. - diff --git a/build/packages/gleeunit/src/gleeunit_ffi.mjs b/build/packages/gleeunit/src/gleeunit_ffi.mjs deleted file mode 100644 index 7bdc071..0000000 --- a/build/packages/gleeunit/src/gleeunit_ffi.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import { readFileSync } from "node:fs"; -import { Result$Ok, Result$Error } from "./gleam.mjs"; -import * as reporting from "./gleeunit/internal/reporting.mjs"; - -export function read_file(path) { - try { - return Result$Ok(readFileSync(path)); - } catch { - return Result$Error(undefined); - } -} - -async function* gleamFiles(directory) { - for (let entry of await read_dir(directory)) { - let path = join_path(directory, entry); - if (path.endsWith(".gleam")) { - yield path; - } else { - try { - yield* gleamFiles(path); - } catch (error) { - // Could not read directory, assume it's a file - } - } - } -} - -async function readRootPackageName() { - let toml = await async_read_file("gleam.toml", "utf-8"); - for (let line of toml.split("\n")) { - let matches = line.match(/\s*name\s*=\s*"([a-z][a-z0-9_]*)"/); // Match regexp in compiler-cli/src/new.rs in validate_name() - if (matches) return matches[1]; - } - throw new Error("Could not determine package name from gleam.toml"); -} - -export async function main() { - let state = reporting.new_state(); - - let packageName = await readRootPackageName(); - let dist = `../${packageName}/`; - - for await (let path of await gleamFiles("test")) { - let js_path = path.slice("test/".length).replace(".gleam", ".mjs"); - let module = await import(join_path(dist, js_path)); - for (let fnName of Object.keys(module)) { - if (!fnName.endsWith("_test")) continue; - try { - await module[fnName](); - state = reporting.test_passed(state); - } catch (error) { - let moduleName = js_path.slice(0, -4); - state = reporting.test_failed(state, moduleName, fnName, error); - } - } - } - - const status = reporting.finished(state); - exit(status); -} - -export function crash(message) { - throw new Error(message); -} - -function exit(code) { - if (globalThis.Deno) { - Deno.exit(code); - } else { - process.exit(code); - } -} - -async function read_dir(path) { - if (globalThis.Deno) { - let items = []; - for await (let item of Deno.readDir(path, { withFileTypes: true })) { - items.push(item.name); - } - return items; - } else { - let { readdir } = await import("node:fs/promises"); - return readdir(path); - } -} - -function join_path(a, b) { - if (a.endsWith("/")) return a + b; - return a + "/" + b; -} - -async function async_read_file(path) { - if (globalThis.Deno) { - return Deno.readTextFile(path); - } else { - let { readFile } = await import("node:fs/promises"); - let contents = await readFile(path); - return contents.toString(); - } -} diff --git a/build/packages/gleeunit/src/gleeunit_progress.erl b/build/packages/gleeunit/src/gleeunit_progress.erl deleted file mode 100644 index e6576a5..0000000 --- a/build/packages/gleeunit/src/gleeunit_progress.erl +++ /dev/null @@ -1,72 +0,0 @@ -%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters - --module(gleeunit_progress). --define(NOTEST, true). - -%% eunit_listener callbacks --export([ - init/1, handle_begin/3, handle_end/3, handle_cancel/3, terminate/2, - start/0, start/1 -]). - --define(reporting, gleeunit@internal@reporting). - -start() -> - start([]). - -start(Options) -> - eunit_listener:start(?MODULE, Options). - -init(_Options) -> - ?reporting:new_state(). - -handle_begin(_test_or_group, _data, State) -> - State. - -handle_end(group, _data, State) -> - State; -handle_end(test, Data, State) -> - {AtomModule, AtomFunction, _Arity} = proplists:get_value(source, Data), - Module = erlang:atom_to_binary(AtomModule), - Function = erlang:atom_to_binary(AtomFunction), - - % EUnit swallows stdout, so print it to make debugging easier. - case proplists:get_value(output, Data) of - undefined -> ok; - <<>> -> ok; - Out -> gleam@io:print(Out) - end, - - case proplists:get_value(status, Data) of - ok -> - ?reporting:test_passed(State); - {skipped, _Reason} -> - ?reporting:test_skipped(State, Module, Function); - {error, {_, Exception, _Stack}} -> - ?reporting:test_failed(State, Module, Function, Exception) - end. - - -handle_cancel(_test_or_group, Data, State) -> - ?reporting:test_failed(State, <<"gleeunit">>, <<"main">>, Data). - -terminate({ok, _Data}, State) -> - ?reporting:finished(State), - ok; -terminate({error, Reason}, State) -> - ?reporting:finished(State), - io:fwrite(" -Eunit failed: - -~80p - -This is probably a bug in gleeunit. Please report it. -", [Reason]), - sync_end(error). - -sync_end(Result) -> - receive - {stop, Reference, ReplyTo} -> - ReplyTo ! {result, Reference, Result}, - ok - end. diff --git a/build/packages/packages.toml b/build/packages/packages.toml deleted file mode 100644 index 6098d78..0000000 --- a/build/packages/packages.toml +++ /dev/null @@ -1,7 +0,0 @@ -[packages] -gleam_stdlib = "0.65.0" -gleam_community_colour = "2.0.2" -gleam_json = "3.1.0" -gleeunit = "1.9.0" -paint = "1.0.0" -gleam_time = "1.6.0" diff --git a/build/packages/paint/LICENSE.txt b/build/packages/paint/LICENSE.txt deleted file mode 100644 index 40cce2a..0000000 --- a/build/packages/paint/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Eli Adelhult - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/build/packages/paint/README.md b/build/packages/paint/README.md deleted file mode 100644 index d762383..0000000 --- a/build/packages/paint/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Paint -**Make 2D drawings, animations, and games using Gleam and the HTML Canvas!** - -[![Package Version](https://img.shields.io/hexpm/v/paint)](https://hex.pm/packages/paint) -[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/paint/) - -Paint is a tiny embedded domain specific language (inspired by [Gloss](https://hackage.haskell.org/package/gloss)). -Make pictures out of basic shapes then style, transform, and combine them using the provided functions. - -![Frame 3(2)](https://github.com/user-attachments/assets/a8b83b58-990a-432a-9034-deebc4d210a6) - -```gleam -import paint as p -import paint/canvas - -fn main() { - let my_picture = p.combine([ - p.circle(30.0), - p.circle(20.0) |> p.fill(p.colour_rgb(0, 200, 200)), - p.rectangle(50.0, 30.0) |> p.rotate(p.angle_deg(30.0)), - p.text("Hello world", 10) |> p.translate_y(-35.0), - ]) - - canvas.display(fn(_: canvas.Config) { my_picture }, "#canvas_id") -} -``` - -**Want to learn more? Read the [docs](https://hexdocs.pm/paint) or browse the [visual examples](https://adelhult.github.io/paint/).** - -## Logo -Lucy is borrowed from the [Gleam branding page](https://gleam.run/branding/) and the brush is made by [Delapouite (game icons)](https://game-icons.net/1x1/delapouite/paint-brush.html). - -## Changelog -API additions and breaking changes can be found in the file `CHANGELOG.md`. diff --git a/build/packages/paint/gleam.toml b/build/packages/paint/gleam.toml deleted file mode 100644 index d912cdd..0000000 --- a/build/packages/paint/gleam.toml +++ /dev/null @@ -1,23 +0,0 @@ -name = "paint" -version = "1.0.0" -target = "javascript" - -# Fill out these fields if you intend to generate HTML documentation or publish -# your project to the Hex package manager. -# -description = "Make 2D drawings, animations, and games (HTML Canvas)" -licences = ["MIT"] -repository = { type = "github", user = "adelhult", repo = "paint" } -links = [ - { title = "Visual examples", href = "https://adelhult.github.io/paint/" }, -] -dev-dependencies = { gleeunit = ">= 1.6.1 and < 2.0.0" } -# -# For a full reference of all the available options, you can have a look at -# https://gleam.run/writing-gleam/gleam-toml/. - - -[dependencies] -gleam_stdlib = ">= 0.58.0 and < 2.0.0" -gleam_community_colour = ">= 2.0.0 and < 3.0.0" -gleam_json = ">= 3.0.2 and < 4.0.0" diff --git a/build/packages/paint/src/impl_canvas_bindings.mjs b/build/packages/paint/src/impl_canvas_bindings.mjs deleted file mode 100644 index 5fed16a..0000000 --- a/build/packages/paint/src/impl_canvas_bindings.mjs +++ /dev/null @@ -1,271 +0,0 @@ -import { Ok, Error } from "./gleam.mjs"; - -class PaintCanvas extends HTMLElement { - // Open an issue if you are in need of any other attributes :) - static observedAttributes = ["width", "height", "style", "picture"]; - - constructor() { - super(); - // Create a canvas - this.canvas = document.createElement("canvas"); - const style = document.createElement("style"); - style.textContent = ` - :host { - display: inline-block; - } - `; - this.shadow = this.attachShadow({ mode: "open" }); - this.shadow.appendChild(style); - this.shadow.appendChild(this.canvas); - this.ctx = this.canvas.getContext("2d"); - } - - attributeChangedCallback(name, _oldValue, newValue) { - if (name === "picture") { - this.picture = newValue; - return; - } else if (name === "width") { - this.width = newValue; - } else if (name === "height") { - this.height = newValue; - } - } - - drawPicture() { - if (!this.pictureString) { - return; - } - - this.ctx.reset(); - const display = - window.PAINT_STATE[ - "display_on_rendering_context_with_default_drawing_state" - ]; - - display(this.pictureString, this.ctx); - } - - set picture(value) { - this.pictureString = value; - this.drawPicture(); - } - - set width(value) { - this.canvas.width = value; - this.drawPicture(); - } - - set height(value) { - this.canvas.height = value; - this.drawPicture(); - } - - get width() { - return this.canvas.width; - } - - get height() { - return this.canvas.height; - } -} - -export function define_web_component() { - window.customElements.define("paint-canvas", PaintCanvas); -} - -export function get_rendering_context(selector) { - // TODO: Handle the case where the canvas element is not found. - return document.querySelector(selector).getContext("2d"); -} - -export function setup_request_animation_frame(callback) { - window.requestAnimationFrame((time) => { - callback(time); - }); -} - -export function setup_input_handler(event_name, callback) { - window.addEventListener(event_name, callback); -} - -export function get_key_code(event) { - return event.keyCode; -} - -export function set_global(state, id) { - if (typeof window.PAINT_STATE == "undefined") { - window.PAINT_STATE = {}; - } - window.PAINT_STATE[id] = state; -} - -export function get_global(id) { - if (!window.PAINT_STATE) { - return new Error(undefined); - } - if (!(id in window.PAINT_STATE)) { - return new Error(undefined); - } - return new Ok(window.PAINT_STATE[id]); -} - -export function get_width(ctx) { - return ctx.canvas.clientWidth; -} - -export function get_height(ctx) { - return ctx.canvas.clientHeight; -} - -// Based on https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas -export function mouse_pos(ctx, event) { - // Calculate the scaling of the canvas vs its content - const rect = ctx.canvas.getBoundingClientRect(); - const scaleX = ctx.canvas.width / rect.width; - const scaleY = ctx.canvas.height / rect.height; - - return [ - (event.clientX - rect.left) * scaleX, - (event.clientY - rect.top) * scaleY, - ]; -} - -// if check_pressed is true, the function will return true if the button was pressed -// if check_pressed is false, the function will return true if the button was released -export function check_mouse_button( - event, - previous_event, - button_index, - check_pressed, -) { - let previous_buttons = previous_event?.buttons ?? 0; - let current_buttons = event.buttons; - - // ~001 && - // 011 - // ----- - // 010 found the newly pressed! - // - // 011 && - // ~001 - // ----- - // 010 found the newly released! - if (check_pressed) { - previous_buttons = ~previous_buttons; - } else { - current_buttons = ~current_buttons; - } - - let button = previous_buttons & current_buttons & (1 << button_index); - return !!button; -} - -export function reset(ctx) { - ctx.reset(); -} - -export function arc(ctx, radius, start, end, fill, stroke) { - ctx.beginPath(); - ctx.arc(0, 0, radius, start, end); - if (fill) { - ctx.fill(); - } - if (stroke) { - ctx.stroke(); - } -} - -export function polygon(ctx, points, closed, fill, stroke) { - ctx.beginPath(); - ctx.moveTo(0, 0); - let started = false; - for (const point of points) { - let x = point[0]; - let y = point[1]; - if (started) { - ctx.lineTo(x, y); - } else { - ctx.moveTo(x, y); - started = true; - } - } - - if (closed) { - ctx.closePath(); - } - - if (fill && closed) { - ctx.fill(); - } - - if (stroke) { - ctx.stroke(); - } -} - -export function text(ctx, text, style) { - ctx.font = style; - ctx.fillText(text, 0, 0); -} - -export function save(ctx) { - ctx.save(); -} - -export function restore(ctx) { - ctx.restore(); -} - -export function set_fill_colour(ctx, css_colour) { - ctx.fillStyle = css_colour; -} - -export function set_stroke_color(ctx, css_color) { - ctx.strokeStyle = css_color; -} - -export function set_line_width(ctx, width) { - ctx.lineWidth = width; -} - -export function translate(ctx, x, y) { - ctx.translate(x, y); -} - -export function scale(ctx, x, y) { - ctx.scale(x, y); -} - -export function rotate(ctx, radians) { - ctx.rotate(radians); -} - -export function reset_transform(ctx) { - ctx.resetTransform(); -} - -export function draw_image(ctx, image, width_px, height_px) { - ctx.drawImage(image, 0, 0, width_px, height_px); -} - -export function image_from_query(selector) { - return document.querySelector(selector); -} - -export function image_from_src(src) { - const image = new Image(); - image.src = src; - return image; -} - -export function on_image_load(image, callback) { - if (image.complete) { - callback(); - } else { - image.addEventListener("load", callback); - } -} - -export function set_image_smoothing_enabled(ctx, value) { - ctx.imageSmoothingEnabled = value; -} diff --git a/build/packages/paint/src/numbers_ffi.mjs b/build/packages/paint/src/numbers_ffi.mjs deleted file mode 100644 index 0e6e6d3..0000000 --- a/build/packages/paint/src/numbers_ffi.mjs +++ /dev/null @@ -1,3 +0,0 @@ -export function pi() { - return Math.PI; -} diff --git a/build/packages/paint/src/paint.gleam b/build/packages/paint/src/paint.gleam deleted file mode 100644 index 6729228..0000000 --- a/build/packages/paint/src/paint.gleam +++ /dev/null @@ -1,201 +0,0 @@ -//// This module contains the main `Picture` type as well as the -//// function you can use to construct, modify and combine pictures. - -import gleam/result -import gleam_community/colour -import paint/internal/types as internal_implementation - -/// A 2D picture. This is the type which this entire library revolves around. -/// -///> [!NOTE] -///> Unless you intend to author a new backend you should **consider this type opaque and never use any of its constructors**. -///> Instead, make use of the many utility functions defined in this module (`circle`, `combine`, `fill`, etc.) -pub type Picture = - internal_implementation.Picture - -/// A reference to an image (i.e. a texture), not to be confused with the `Picture` type. -/// To create an image, see the image functions in the `canvas` back-end. -pub type Image = - internal_implementation.Image - -/// An angle in clock-wise direction. -/// See: `angle_rad` and `angle_deg`. -pub type Angle = - internal_implementation.Angle - -/// Create an angle expressed in radians -pub fn angle_rad(radians: Float) -> Angle { - internal_implementation.Radians(radians) -} - -/// Create an angle expressed in degrees -pub fn angle_deg(degrees: Float) -> Angle { - internal_implementation.Radians(degrees *. pi() /. 180.0) -} - -/// A rexport of the Colour type from [gleam_community/colour](https://hexdocs.pm/gleam_community_colour/). -/// Paint also includes the functions `colour_hex` and `colour_rgb` to -/// easily construct Colours, but feel free to import the `gleam_community/colour` module -/// and use the many utility that are provided from there. -pub type Colour = - colour.Colour - -/// A utility around [colour.from_rgb_hex_string](https://hexdocs.pm/gleam_community_colour/gleam_community/colour.html#from_rgb_hex_string) -/// (from `gleam_community/colour`) that **panics** on an invalid hex code. -pub fn colour_hex(string: String) -> Colour { - result.lazy_unwrap(colour.from_rgb_hex_string(string), fn() { - panic as "Failed to parse hex code" - }) -} - -/// A utility around [colour.from_rgb255](https://hexdocs.pm/gleam_community_colour/gleam_community/colour.html#from_rgb255) -/// (from `gleam_community/colour`) that **panics** if the values are outside of the allowed range. -pub fn colour_rgb(red: Int, green: Int, blue: Int) -> Colour { - result.lazy_unwrap(colour.from_rgb255(red, green, blue), fn() { - panic as "The value was not inside of the valid range [0-255]" - }) -} - -pub type Vec2 = - #(Float, Float) - -/// A blank picture -pub fn blank() -> Picture { - internal_implementation.Blank -} - -/// A circle with some given radius -pub fn circle(radius: Float) -> Picture { - internal_implementation.Arc( - radius, - start: internal_implementation.Radians(0.0), - end: internal_implementation.Radians(2.0 *. pi()), - ) -} - -/// An arc with some radius going from some -/// starting angle to some other angle in clock-wise direction -pub fn arc(radius: Float, start: Angle, end: Angle) -> Picture { - internal_implementation.Arc(radius, start: start, end: end) -} - -/// A polygon consisting of a list of 2d points -pub fn polygon(points: List(#(Float, Float))) -> Picture { - internal_implementation.Polygon(points, True) -} - -/// Lines (same as a polygon but not a closed shape) -pub fn lines(points: List(#(Float, Float))) -> Picture { - internal_implementation.Polygon(points, False) -} - -/// A rectangle with some given width and height -pub fn rectangle(width: Float, height: Float) -> Picture { - polygon([#(0.0, 0.0), #(width, 0.0), #(width, height), #(0.0, height)]) -} - -/// A square -pub fn square(length: Float) -> Picture { - rectangle(length, length) -} - -/// Draw an image such as a PNG, JPEG or an SVG. See the `canvas` back-end for more details on how to load images. -pub fn image(image: Image, width_px width_px, height_px height_px) -> Picture { - // TODO: add a function that allows us to draw only part of an image, flip, and if we want smooth scaling or not - internal_implementation.ImageRef(image, width_px:, height_px:) -} - -/// Set image scaling to be smooth (this is the default behaviour) -pub fn image_scaling_smooth(picture: Picture) -> Picture { - internal_implementation.ImageScalingBehaviour( - picture, - internal_implementation.ScalingSmooth, - ) -} - -/// Disable smooth image scaling, suitable for pixel art. -pub fn image_scaling_pixelated(picture: Picture) -> Picture { - internal_implementation.ImageScalingBehaviour( - picture, - internal_implementation.ScalingPixelated, - ) -} - -/// Text with some given font size -pub fn text(text: String, px font_size: Int) -> Picture { - internal_implementation.Text( - text, - style: internal_implementation.FontProperties(font_size, "sans-serif"), - ) - // TODO: expose more styling options (font and text alignment) -} - -/// Translate a picture in horizontal and vertical direction -pub fn translate_xy(picture: Picture, x: Float, y: Float) -> Picture { - internal_implementation.Translate(picture, #(x, y)) -} - -/// Translate a picture in the horizontal direction -pub fn translate_x(picture: Picture, x: Float) -> Picture { - translate_xy(picture, x, 0.0) -} - -/// Translate a picture in the vertical direction -pub fn translate_y(picture: Picture, y: Float) -> Picture { - translate_xy(picture, 0.0, y) -} - -/// Scale the picture in the horizontal direction -pub fn scale_x(picture: Picture, factor: Float) -> Picture { - internal_implementation.Scale(picture, #(factor, 1.0)) -} - -/// Scale the picture in the vertical direction -pub fn scale_y(picture: Picture, factor: Float) -> Picture { - internal_implementation.Scale(picture, #(1.0, factor)) -} - -/// Scale the picture uniformly in horizontal and vertical direction -pub fn scale_uniform(picture: Picture, factor: Float) -> Picture { - internal_implementation.Scale(picture, #(factor, factor)) -} - -/// Rotate the picture in a clock-wise direction -pub fn rotate(picture: Picture, angle: Angle) -> Picture { - internal_implementation.Rotate(picture, angle) -} - -/// Fill a picture with some given colour, see `Colour`. -pub fn fill(picture: Picture, colour: Colour) -> Picture { - internal_implementation.Fill(picture, colour) -} - -/// Set a solid stroke with some given colour and width -pub fn stroke(picture: Picture, colour: Colour, width width: Float) -> Picture { - internal_implementation.Stroke( - picture, - internal_implementation.SolidStroke(colour, width), - ) -} - -/// Remove the stroke of the given picture -pub fn stroke_none(picture: Picture) -> Picture { - internal_implementation.Stroke(picture, internal_implementation.NoStroke) -} - -/// Concatenate two pictures -pub fn concat(picture: Picture, another_picture: Picture) -> Picture { - combine([picture, another_picture]) -} - -/// Combine multiple pictures into one -pub fn combine(pictures: List(Picture)) -> Picture { - internal_implementation.Combine(pictures) -} - -// Internal utility function to get Pi π -@external(erlang, "math", "pi") -@external(javascript, "./numbers_ffi.mjs", "pi") -fn pi() -> Float { - 3.1415926 -} diff --git a/build/packages/paint/src/paint/canvas.gleam b/build/packages/paint/src/paint/canvas.gleam deleted file mode 100644 index 061c102..0000000 --- a/build/packages/paint/src/paint/canvas.gleam +++ /dev/null @@ -1,461 +0,0 @@ -//// A HTML canvas backend that can be used for displaying -//// your `Picture`s. There are three different ways of doing so: -//// - `display` (provide a picture and a CSS selector to some canvas element) -//// - `define_web_component` (an alternative to `display` using custom web components, useful if you are using a web framework like Lustre) -//// - `interact` (allows you to make animations and interactive programs) - -import gleam/int -import gleam/option.{type Option, None, Some} -import gleam_community/colour -import paint.{translate_xy} -import paint/encode -import paint/event.{type Event} -import paint/internal/impl_canvas -import paint/internal/types.{ - type Image, type Picture, Arc, Blank, Combine, Fill, FontProperties, Image, - NoStroke, Polygon, Radians, Rotate, Scale, SolidStroke, Stroke, Text, - Translate, -} - -/// The configuration of the "canvas" -pub type Config { - Config(width: Float, height: Float) -} - -/// Create a reference to an image using a CSS query selector. For example: -/// ``` -/// fn kitten() { -/// canvas.image_from_query("#kitten") -/// } -/// // In the HTML file: -/// // -/// ``` -/// -/// > [!WARNING] -/// > **Important**: Make sure the image has loaded before trying to draw a pictures referencing it. -/// > You can do this using `canvas.wait_until_loaded` function. -pub fn image_from_query(selector: String) -> Image { - let id = "image-selector-" <> selector - case impl_canvas.get_global(id) { - // Re-use the cached image if we can - Ok(_) -> { - Nil - } - Error(Nil) -> { - let image = impl_canvas.image_from_query(selector) - impl_canvas.set_global(image, id) - } - } - Image(id) -} - -/// Create a reference to an image using a source path. -/// ``` -/// fn my_logo_image() { -/// canvas.image_from_src("./priv/static/logo.svg") -/// } -/// ``` -/// -/// > [!WARNING] -/// > **Important**: Make sure the image has loaded before trying to draw a pictures referencing it. -/// > You can do this using `canvas.wait_until_loaded` function. -pub fn image_from_src(src: String) -> Image { - let id = "image-src-" <> src - case impl_canvas.get_global(id) { - // Re-use the cached image if we can - Ok(_) -> { - Nil - } - Error(Nil) -> { - let image = impl_canvas.image_from_src(src) - impl_canvas.set_global(image, id) - } - } - Image(id) -} - -/// Wait until a list of images have all been loaded, for example: -/// ``` -/// fn lucy() { -/// canvas.image_from_query("#lucy") -/// } -/// -/// fn cat() { -/// canvas.image_from_src("./path/to/kitten.png") -/// } -/// -/// pub fn main() { -/// use <- canvas.wait_until_loaded([lucy(), kitten()]) -/// // It is now safe to draw Pictures containing the images lucy and kitten :) -/// } -/// ``` -pub fn wait_until_loaded(images: List(Image), on_loaded: fn() -> Nil) -> Nil { - case images { - [] -> on_loaded() - [image, ..rest] -> { - let Image(id:) = image - let assert Ok(js_image) = impl_canvas.get_global(id) - impl_canvas.on_image_load(js_image, fn() { - wait_until_loaded(rest, on_loaded) - }) - } - } -} - -/// Display a picture on a HTML canvas element -/// (specified by some [CSS Selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)). -/// ``` -/// canvas.display(fn (_: canvas.Config) { circle(50.0) }, "#mycanvas") -/// ``` -pub fn display(init: fn(Config) -> Picture, selector: String) { - let ctx = impl_canvas.get_rendering_context(selector) - impl_canvas.reset(ctx) - let picture = - init(Config(impl_canvas.get_width(ctx), impl_canvas.get_height(ctx))) - display_on_rendering_context(picture, ctx, default_drawing_state) -} - -/// Additional state used when drawing -/// (note that the fill and stroke color as well as the stroke width -/// is stored inside of the context) -type DrawingState { - DrawingState(fill: Bool, stroke: Bool) -} - -const default_drawing_state = DrawingState(fill: False, stroke: True) - -fn display_on_rendering_context( - picture: Picture, - ctx: impl_canvas.RenderingContext2D, - state: DrawingState, -) { - case picture { - Blank -> Nil - - Text(text, properties) -> { - let FontProperties(size_px, font_family) = properties - impl_canvas.save(ctx) - impl_canvas.text( - ctx, - text, - int.to_string(size_px) <> "px " <> font_family, - ) - impl_canvas.restore(ctx) - } - - Polygon(points, closed) -> { - impl_canvas.polygon(ctx, points, closed, state.fill, state.stroke) - } - - Arc(radius, start, end) -> { - let Radians(start_radians) = start - let Radians(end_radians) = end - impl_canvas.arc( - ctx, - radius, - start_radians, - end_radians, - state.fill, - state.stroke, - ) - } - - Fill(p, colour) -> { - impl_canvas.save(ctx) - impl_canvas.set_fill_colour(ctx, colour.to_css_rgba_string(colour)) - display_on_rendering_context(p, ctx, DrawingState(..state, fill: True)) - impl_canvas.restore(ctx) - } - - Stroke(p, stroke) -> { - case stroke { - NoStroke -> - display_on_rendering_context( - p, - ctx, - DrawingState(..state, stroke: False), - ) - SolidStroke(color, width) -> { - impl_canvas.save(ctx) - impl_canvas.set_stroke_color(ctx, colour.to_css_rgba_string(color)) - impl_canvas.set_line_width(ctx, width) - display_on_rendering_context( - p, - ctx, - DrawingState(..state, stroke: True), - ) - impl_canvas.restore(ctx) - } - } - } - - Translate(p, vec) -> { - let #(x, y) = vec - impl_canvas.save(ctx) - impl_canvas.translate(ctx, x, y) - display_on_rendering_context(p, ctx, state) - impl_canvas.restore(ctx) - } - - Scale(p, vec) -> { - let #(x, y) = vec - impl_canvas.save(ctx) - impl_canvas.scale(ctx, x, y) - display_on_rendering_context(p, ctx, state) - impl_canvas.restore(ctx) - } - - Rotate(p, angle) -> { - let Radians(rad) = angle - impl_canvas.save(ctx) - impl_canvas.rotate(ctx, rad) - display_on_rendering_context(p, ctx, state) - impl_canvas.restore(ctx) - } - - Combine(pictures) -> { - case pictures { - [] -> Nil - [p, ..ps] -> { - display_on_rendering_context(p, ctx, state) - display_on_rendering_context(Combine(ps), ctx, state) - } - } - } - types.ImageRef(Image(id:), width_px:, height_px:) -> { - // TODO: log an error if this fails? - let assert Ok(image) = impl_canvas.get_global(id) - impl_canvas.draw_image(ctx, image, width_px, height_px) - } - types.ImageScalingBehaviour(p, behaviour) -> { - impl_canvas.save(ctx) - impl_canvas.set_image_smoothing_enabled(ctx, case behaviour { - types.ScalingPixelated -> False - types.ScalingSmooth -> True - }) - display_on_rendering_context(p, ctx, state) - impl_canvas.restore(ctx) - } - } -} - -/// Animations, interactive applications and tiny games can be built using the -/// `interact` function. It roughly follows the [Elm architecture](https://guide.elm-lang.org/architecture/). -/// Here is a short example: -/// ``` -/// type State = -/// Int -/// -/// fn init(_: canvas.Config) -> State { -/// 0 -/// } -/// -/// fn update(state: State, event: event.Event) -> State { -/// case event { -/// event.Tick(_) -> state + 1 -/// _ -> state -/// } -/// } -/// -/// fn view(state: State) -> Picture { -/// paint.circle(int.to_float(state)) -/// } -/// -/// fn main() { -/// interact(init, update, view, "#mycanvas") -/// } -/// ``` -pub fn interact( - init: fn(Config) -> state, - update: fn(state, Event) -> state, - view: fn(state) -> Picture, - selector: String, -) { - let ctx = impl_canvas.get_rendering_context(selector) - let initial_state = - init(Config(impl_canvas.get_width(ctx), impl_canvas.get_height(ctx))) - - impl_canvas.set_global(initial_state, selector) - - // Handle keyboard input - let create_key_handler = fn(event_name, constructor) { - impl_canvas.setup_input_handler( - event_name, - fn(event: impl_canvas.KeyboardEvent) { - let key = parse_key_code(impl_canvas.get_key_code(event)) - case key { - Some(key) -> { - let assert Ok(old_state) = impl_canvas.get_global(selector) - let new_state = update(old_state, constructor(key)) - impl_canvas.set_global(new_state, selector) - } - None -> Nil - } - }, - ) - } - create_key_handler("keydown", event.KeyboardPressed) - create_key_handler("keyup", event.KeyboardRelased) - - // Handle mouse movement - impl_canvas.setup_input_handler( - "mousemove", - fn(event: impl_canvas.MouseEvent) { - let #(x, y) = impl_canvas.mouse_pos(ctx, event) - let assert Ok(old_state) = impl_canvas.get_global(selector) - let new_state = update(old_state, event.MouseMoved(x, y)) - impl_canvas.set_global(new_state, selector) - Nil - }, - ) - - // Handle mouse buttons - let create_mouse_button_handler = fn(event_name, constructor, check_pressed) { - impl_canvas.setup_input_handler( - event_name, - fn(event: impl_canvas.MouseEvent) { - // Read the previous state of the mouse - let previous_event_id = "PAINT_PREVIOUS_MOUSE_INPUT_FOR_" <> selector - let previous_event = impl_canvas.get_global(previous_event_id) - // Save this state - impl_canvas.set_global(event, previous_event_id) - - // A utility to check which buttons was just pressed/released - let check_button = fn(i) { - impl_canvas.check_mouse_button( - event, - previous_event, - i, - check_pressed, - ) - } - - let trigger_update = fn(button) { - let assert Ok(old_state) = impl_canvas.get_global(selector) - let new_state = update(old_state, constructor(button)) - impl_canvas.set_global(new_state, selector) - } - - // Note: it is rather rare, but it seems that multiple buttons - // can be pressed in the very same MouseEvent, so we may need to - // trigger multiple events at once. - case check_button(0) { - True -> trigger_update(event.MouseButtonLeft) - False -> Nil - } - case check_button(1) { - True -> trigger_update(event.MouseButtonRight) - False -> Nil - } - case check_button(2) { - True -> trigger_update(event.MouseButtonMiddle) - False -> Nil - } - - Nil - }, - ) - } - create_mouse_button_handler("mousedown", event.MousePressed, True) - create_mouse_button_handler("mouseup", event.MouseReleased, False) - - impl_canvas.setup_request_animation_frame(get_tick_func( - ctx, - view, - update, - selector, - )) -} - -fn parse_key_code(key_code: Int) -> Option(event.Key) { - case key_code { - 32 -> Some(event.KeySpace) - 37 -> Some(event.KeyLeftArrow) - 38 -> Some(event.KeyUpArrow) - 39 -> Some(event.KeyRightArrow) - 40 -> Some(event.KeyDownArrow) - 87 -> Some(event.KeyW) - 65 -> Some(event.KeyA) - 83 -> Some(event.KeyS) - 68 -> Some(event.KeyD) - 90 -> Some(event.KeyZ) - 88 -> Some(event.KeyX) - 67 -> Some(event.KeyC) - 18 -> Some(event.KeyEnter) - 27 -> Some(event.KeyEscape) - 8 -> Some(event.KeyBackspace) - _ -> None - } -} - -// Gleam does not have recursive let bindings, so I need -// to do this workaround... -fn get_tick_func(ctx, view, update, selector) { - fn(time) { - let assert Ok(current_state) = impl_canvas.get_global(selector) - - // Trigger a tick event before drawing - let new_state = update(current_state, event.Tick(time)) - impl_canvas.set_global(new_state, selector) - - // Create the picture - let picture = view(new_state) - - // Render the picture on the canvas - impl_canvas.reset(ctx) - display_on_rendering_context(picture, ctx, default_drawing_state) - impl_canvas.setup_request_animation_frame( - // call myself - get_tick_func(ctx, view, update, selector), - ) - } -} - -/// If you are using [Lustre](https://github.com/lustre-labs/lustre) or some other framework to build -/// your web application you may prefer to use the [web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) API -/// and the `define_web_component` function. -/// ``` -/// // Call this function once to register a custom HTML element -/// canvas.define_web_component() -/// // You can then display your picture by setting the "picture" -/// // property or attribute on the element. -/// -/// // In Lustre it would look something like this: -/// fn canvas(picture: paint.Picture, attributes: List(attribute.Attribute(a))) { -/// element.element( -/// "paint-canvas", -/// [attribute.attribute("picture", encode.to_string(picture)), ..attributes], -/// [], -/// ) -///} -/// ``` -/// A more detailed example for using this API can be found in the `demos/with_lustre` directory. -pub fn define_web_component() -> Nil { - impl_canvas.define_web_component() - // somewhat of an ugly hack, but the setter for the web component will need to call this - // when the picture property changes. Therefore we - // bind this function to the window object so we can access it from the JS side of things. - // - // However, we should be careful of changing this. It is not part of the public API but it seems like - // [Tiramisu](https://hexdocs.pm/tiramisu/index.html) might makes use of it. - impl_canvas.set_global( - fn(encoded_picture, ctx) { - let assert Ok(picture) = encode.from_string(encoded_picture) - as "Invalid picture provided to web component" - display_on_rendering_context(picture, ctx, default_drawing_state) - }, - "display_on_rendering_context_with_default_drawing_state", - ) -} - -/// Utility to set the origin in the center of the canvas -pub fn center(picture: Picture) -> fn(Config) -> Picture { - fn(config) { - let Config(width, height) = config - picture |> translate_xy(width *. 0.5, height *. 0.5) - } -} diff --git a/build/packages/paint/src/paint/encode.gleam b/build/packages/paint/src/paint/encode.gleam deleted file mode 100644 index 96aea01..0000000 --- a/build/packages/paint/src/paint/encode.gleam +++ /dev/null @@ -1,260 +0,0 @@ -import gleam/dynamic/decode.{type Decoder} -import gleam/json.{type Json} -import gleam_community/colour -import paint.{type Picture} -import paint/internal/types.{ - type Angle, type FontProperties, type StrokeProperties, FontProperties, - NoStroke, Radians, SolidStroke, -} - -/// Serialize a `Picture` to a string. -/// -/// Note, serializing an `Image` texture will only store an ID referencing the image. This means that if you deserialize a Picture containing -/// references to images, you are responsible for making sure all images are loaded before drawing the picture. -/// More advanced APIs to support use cases such as these are planned for a future release. -/// -/// Also, if you wish to store the serialized data, remember that the library currently makes no stability guarantee that -/// the data can be deserialized by *future* versions of the library. -pub fn to_string(picture: Picture) -> String { - let version = "paint:unstable" - json.object([ - #("version", json.string(version)), - #("picture", picture_to_json(picture)), - ]) - |> json.to_string -} - -/// Attempt to deserialize a `Picture` -pub fn from_string(string: String) { - let decoder = { - use picture <- decode.field("picture", decode_picture()) - decode.success(picture) - } - json.parse(string, decoder) -} - -fn decode_angle() { - use radians <- decode.field("radians", decode.float) - decode.success(Radians(radians)) -} - -fn decode_picture() -> Decoder(Picture) { - use <- decode.recursive - use ty <- decode.field("type", decode.string) - - case ty { - "arc" -> { - use radius <- decode.field("radius", decode.float) - use start <- decode.field("start", decode_angle()) - use end <- decode.field("end", decode_angle()) - decode.success(types.Arc(radius, start:, end:)) - } - "blank" -> decode.success(types.Blank) - "combine" -> { - use pictures <- decode.field( - "pictures", - decode.list(of: decode_picture()), - ) - decode.success(types.Combine(pictures)) - } - "fill" -> { - use picture <- decode.field("picture", decode_picture()) - use colour <- decode.field("colour", colour.decoder()) - decode.success(types.Fill(picture, colour)) - } - "polygon" -> { - use points <- decode.field("points", decode.list(of: decode_vec2())) - use closed <- decode.field("closed", decode.bool) - decode.success(types.Polygon(points, closed)) - } - "rotate" -> { - use angle <- decode.field("angle", decode_angle()) - use picture <- decode.field("picture", decode_picture()) - decode.success(types.Rotate(picture, angle)) - } - "scale" -> { - use x <- decode.field("x", decode.float) - use y <- decode.field("y", decode.float) - use picture <- decode.field("picture", decode_picture()) - decode.success(types.Scale(picture, #(x, y))) - } - "stroke" -> { - use stroke <- decode.field("stroke", decode_stroke()) - use picture <- decode.field("picture", decode_picture()) - decode.success(types.Stroke(picture, stroke)) - } - "text" -> { - use text <- decode.field("text", decode.string) - use style <- decode.field("style", decode_font()) - decode.success(types.Text(text, style)) - } - "translate" -> { - use x <- decode.field("x", decode.float) - use y <- decode.field("y", decode.float) - use picture <- decode.field("picture", decode_picture()) - decode.success(types.Translate(picture, #(x, y))) - } - "image" -> { - use id <- decode.field("id", decode.string) - use width_px <- decode.field("width_px", decode.int) - use height_px <- decode.field("height_px", decode.int) - decode.success(types.ImageRef(types.Image(id:), width_px:, height_px:)) - } - "image_scaling_behaviour" -> { - use behaviour <- decode.field("behaviour", decode.string) - use picture <- decode.field("picture", decode_picture()) - case behaviour { - "smooth" -> - decode.success(types.ImageScalingBehaviour( - picture, - types.ScalingSmooth, - )) - "pixelated" -> - decode.success(types.ImageScalingBehaviour( - picture, - types.ScalingPixelated, - )) - _ -> decode.failure(types.Blank, "Picture") - } - } - _ -> decode.failure(types.Blank, "Picture") - } -} - -fn decode_font() -> Decoder(FontProperties) { - use size_px <- decode.field("sizePx", decode.int) - use font_family <- decode.field("fontFamily", decode.string) - decode.success(FontProperties(size_px:, font_family:)) -} - -fn decode_stroke() -> Decoder(StrokeProperties) { - use stroke_type <- decode.field("type", decode.string) - case stroke_type { - "noStroke" -> decode.success(NoStroke) - "solidStroke" -> { - use colour <- decode.field("colour", colour.decoder()) - use thickness <- decode.field("thickness", decode.float) - decode.success(SolidStroke(colour, thickness)) - } - _ -> decode.failure(NoStroke, "StrokeProperties") - } -} - -fn decode_vec2() -> Decoder(#(Float, Float)) { - use x <- decode.field("x", decode.float) - use y <- decode.field("y", decode.float) - decode.success(#(x, y)) -} - -fn picture_to_json(picture: Picture) -> Json { - case picture { - types.Arc(radius:, start:, end:) -> - json.object([ - #("type", json.string("arc")), - #("radius", json.float(radius)), - #("start", angle_to_json(start)), - #("end", angle_to_json(end)), - ]) - types.Blank -> json.object([#("type", json.string("blank"))]) - types.Combine(from) -> - json.object([ - #("type", json.string("combine")), - #("pictures", json.array(from:, of: picture_to_json)), - ]) - types.Fill(picture, colour) -> - json.object([ - #("type", json.string("fill")), - #("colour", colour.encode(colour)), - #("picture", picture_to_json(picture)), - ]) - types.Polygon(points, closed:) -> - json.object([ - #("type", json.string("polygon")), - #( - "points", - json.array(from: points, of: fn(point) { - let #(x, y) = point - json.object([#("x", json.float(x)), #("y", json.float(y))]) - }), - ), - #("closed", json.bool(closed)), - ]) - types.Rotate(picture, angle) -> - json.object([ - #("type", json.string("rotate")), - #("angle", angle_to_json(angle)), - #("picture", picture_to_json(picture)), - ]) - types.Scale(picture, #(x, y)) -> - json.object([ - #("type", json.string("scale")), - #("x", json.float(x)), - #("y", json.float(y)), - #("picture", picture_to_json(picture)), - ]) - types.Stroke(picture, stroke) -> - json.object([ - #("type", json.string("stroke")), - #("stroke", stroke_to_json(stroke)), - #("picture", picture_to_json(picture)), - ]) - types.Text(text:, style:) -> - json.object([ - #("type", json.string("text")), - #("text", json.string(text)), - #("style", font_to_json(style)), - ]) - types.Translate(picture, #(x, y)) -> - json.object([ - #("type", json.string("translate")), - #("x", json.float(x)), - #("y", json.float(y)), - #("picture", picture_to_json(picture)), - ]) - types.ImageRef(types.Image(id:), width_px:, height_px:) -> { - json.object([ - #("type", json.string("image")), - #("id", json.string(id)), - #("width_px", json.int(width_px)), - #("height_px", json.int(height_px)), - ]) - } - types.ImageScalingBehaviour(picture, behaviour) -> - json.object([ - #("type", json.string("image_scaling_behaviour")), - #( - "behaviour", - json.string(case behaviour { - types.ScalingPixelated -> "pixelated" - types.ScalingSmooth -> "smooth" - }), - ), - #("picture", picture_to_json(picture)), - ]) - } -} - -fn font_to_json(font: FontProperties) -> Json { - let FontProperties(size_px:, font_family:) = font - json.object([ - #("sizePx", json.int(size_px)), - #("fontFamily", json.string(font_family)), - ]) -} - -fn stroke_to_json(stroke: StrokeProperties) -> Json { - case stroke { - NoStroke -> json.object([#("type", json.string("noStroke"))]) - SolidStroke(colour, thickness) -> - json.object([ - #("type", json.string("solidStroke")), - #("colour", colour.encode(colour)), - #("thickness", json.float(thickness)), - ]) - } -} - -fn angle_to_json(angle: Angle) -> Json { - let Radians(rad) = angle - json.object([#("radians", json.float(rad))]) -} diff --git a/build/packages/paint/src/paint/event.gleam b/build/packages/paint/src/paint/event.gleam deleted file mode 100644 index 08298de..0000000 --- a/build/packages/paint/src/paint/event.gleam +++ /dev/null @@ -1,50 +0,0 @@ -//// This module contains events that can be triggered when -//// building interactive applications. -//// -//// See `paint/canvas` and the `canvas.interact` function for a -//// practical example of how this is used. - -pub type Event { - /// Triggered before drawing. Contains the number of milliseconds elapsed. - Tick(Float) - /// Triggered when a key is pressed - KeyboardPressed(Key) - /// Triggered when a key is released - KeyboardRelased(Key) - /// Triggered when the mouse is moved. Contains - /// the `x` and `y` value for the mouse position. - MouseMoved(Float, Float) - /// Triggered when a mouse button is pressed - MousePressed(MouseButton) - /// Triggered when a mouse button is released. - /// - /// Note, on the web you might encounter issues where the - /// release event for the right mouse button is not triggered - /// because of the context menu. - MouseReleased(MouseButton) -} - -pub type Key { - KeyLeftArrow - KeyRightArrow - KeyUpArrow - KeyDownArrow - KeySpace - KeyW - KeyA - KeyS - KeyD - KeyZ - KeyX - KeyC - KeyEnter - KeyEscape - KeyBackspace -} - -pub type MouseButton { - MouseButtonLeft - MouseButtonRight - /// The scroll wheel button - MouseButtonMiddle -} diff --git a/build/packages/paint/src/paint/internal/impl_canvas.gleam b/build/packages/paint/src/paint/internal/impl_canvas.gleam deleted file mode 100644 index 2b94e9a..0000000 --- a/build/packages/paint/src/paint/internal/impl_canvas.gleam +++ /dev/null @@ -1,118 +0,0 @@ -pub type RenderingContext2D - -@external(javascript, "./../../impl_canvas_bindings.mjs", "define_web_component") -pub fn define_web_component() -> Nil - -// TODO: forward the timestamp from the callback -@external(javascript, "./../../impl_canvas_bindings.mjs", "setup_request_animation_frame") -pub fn setup_request_animation_frame(callback: fn(Float) -> Nil) -> Nil - -@external(javascript, "./../../impl_canvas_bindings.mjs", "get_rendering_context") -pub fn get_rendering_context(selector: String) -> RenderingContext2D - -@external(javascript, "../../impl_canvas_bindings.mjs", "setup_input_handler") -pub fn setup_input_handler(event: String, callback: fn(event) -> Nil) -> Nil - -pub type KeyboardEvent - -@external(javascript, "./../../impl_canvas_bindings.mjs", "get_key_code") -pub fn get_key_code(event: KeyboardEvent) -> Int - -pub type MouseEvent - -@external(javascript, "./../../impl_canvas_bindings.mjs", "mouse_pos") -pub fn mouse_pos(ctx: RenderingContext2D, event: MouseEvent) -> #(Float, Float) - -@external(javascript, "./../../impl_canvas_bindings.mjs", "check_mouse_button") -pub fn check_mouse_button( - event: MouseEvent, - previous_event: Result(MouseEvent, Nil), - button_index: Int, - check_pressed check_pressed: Bool, -) -> Bool - -@external(javascript, "../../impl_canvas_bindings.mjs", "get_width") -pub fn get_width(ctx: RenderingContext2D) -> Float - -@external(javascript, "../../impl_canvas_bindings.mjs", "get_height") -pub fn get_height(ctx: RenderingContext2D) -> Float - -@external(javascript, "../../impl_canvas_bindings.mjs", "set_global") -pub fn set_global(state: state, id: String) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "get_global") -pub fn get_global(id: String) -> Result(state, Nil) - -@external(javascript, "../../impl_canvas_bindings.mjs", "reset") -pub fn reset(ctx: RenderingContext2D) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "save") -pub fn save(ctx: RenderingContext2D) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "restore") -pub fn restore(ctx: RenderingContext2D) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "translate") -pub fn translate(ctx: RenderingContext2D, x: Float, y: Float) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "scale") -pub fn scale(ctx: RenderingContext2D, x: Float, y: Float) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "rotate") -pub fn rotate(ctx: RenderingContext2D, radians: Float) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "reset_transform") -pub fn reset_transform(ctx: RenderingContext2D) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "set_fill_colour") -pub fn set_fill_colour(ctx: RenderingContext2D, css_colour: String) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "set_stroke_color") -pub fn set_stroke_color(ctx: RenderingContext2D, css_color: String) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "set_line_width") -pub fn set_line_width(ctx: RenderingContext2D, width: Float) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "set_image_smoothing_enabled") -pub fn set_image_smoothing_enabled(ctx: RenderingContext2D, value: Bool) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "arc") -pub fn arc( - ctx: RenderingContext2D, - radius: Float, - start: Float, - end: Float, - fill: Bool, - stroke: Bool, -) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "polygon") -pub fn polygon( - ctx: RenderingContext2D, - points: List(#(Float, Float)), - closed: Bool, - fill: Bool, - stroke: Bool, -) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "text") -pub fn text(ctx: RenderingContext2D, text: String, style: String) -> Nil - -pub type JsImage - -@external(javascript, "../../impl_canvas_bindings.mjs", "draw_image") -pub fn draw_image( - ctx: RenderingContext2D, - image: JsImage, - width_px: Int, - height_px: Int, -) -> Nil - -@external(javascript, "../../impl_canvas_bindings.mjs", "image_from_query") -pub fn image_from_query(selector: String) -> JsImage - -@external(javascript, "../../impl_canvas_bindings.mjs", "image_from_src") -pub fn image_from_src(src: String) -> JsImage - -@external(javascript, "../../impl_canvas_bindings.mjs", "on_image_load") -pub fn on_image_load(image: JsImage, callback: fn() -> Nil) -> Nil diff --git a/build/packages/paint/src/paint/internal/types.gleam b/build/packages/paint/src/paint/internal/types.gleam deleted file mode 100644 index 4cd6b5c..0000000 --- a/build/packages/paint/src/paint/internal/types.gleam +++ /dev/null @@ -1,48 +0,0 @@ -import gleam_community/colour.{type Colour} - -pub type Picture { - // Shapes - Blank - Polygon(List(Vec2), closed: Bool) - Arc(radius: Float, start: Angle, end: Angle) - Text(text: String, style: FontProperties) - ImageRef(Image, width_px: Int, height_px: Int) - // Styling - // TODO: font - Fill(Picture, Colour) - Stroke(Picture, StrokeProperties) - ImageScalingBehaviour(Picture, ImageScalingBehaviour) - // Transform - Translate(Picture, Vec2) - Scale(Picture, Vec2) - Rotate(Picture, Angle) - // Combine - Combine(List(Picture)) -} - -// The ID for an image -// Invariant: the image object is assumed to already be created and stored somewhere (like the PAINT_STATE for the canvas backend) -pub type Image { - Image(id: String) -} - -pub type ImageScalingBehaviour { - ScalingSmooth - ScalingPixelated -} - -pub type StrokeProperties { - NoStroke - SolidStroke(Colour, Float) -} - -pub type FontProperties { - FontProperties(size_px: Int, font_family: String) -} - -pub type Angle { - Radians(Float) -} - -pub type Vec2 = - #(Float, Float) diff --git a/demo.gif b/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..d48bf5be6149ba722d05fabdc4bf4ffdc1f6a766 GIT binary patch literal 359063 zcmZ?wbh9u|Ji+3`{G9;=OqjGCnatFf6?B+Yt(lFTS*?88oy<85SU9cJB$Xv3#l)mErKF^lq?IhB zO&DdA(q*E#WEG`kRV3xKq!r|36jfyuwV9PP-bPR2? z3=(sJ}N3Oq7$R%R?H$tj+i)4w%mRc3BUZGLrIQS<7e zMe4%r!>?#pe*!#gK5cTFzn=|9x7du`u}&3)_o`X}F=aB=s7U;uH86i-G<-m-v3+w>F9<-KR3SnyYcgxO~*HG z-uiL#^RJsr^T7X|KcDY<@OIbJ z1-tiu-2HObo`a9}+*yD4=)uFsA04^-`pDDz;}<8KxG?|Jg$<|Aoj!MY_l3(7u0NcA z{r=VKch}#%f9Ur8+js6ic=UAMlXq*MzS;8Z?fz$P9zTD3_QmTZZ@z7Q^JUH3ue;xV zdGq$es&_w@z5jLO{nzs!zkdAmW%cL3o4)`1^8L?)zyJRK|Ifg{p!lEL&ow02*)hP? zNY8+o5hV1Jg_W7%KZ6b^bAYl51IK@c;2#c2OBNh#<`CA3Ik92k;dTLKuQ?tY7ai@E zFwVMjV&mfD{R+-qGM<~3oSdu?yej78rlqH+8zi5a^HQjTL*AtL)t!@@m!F^S(99+4 zwPnS{#U7KjVs{C1TwWfq*lVuW)>T(mM{Lfzdur?I>+2H^cgcEhTXS=B#^qJ9r?;)W zy}jV^skz?U*WKM+@%h!=)7#hI-`~K@E$6di!^6WJ!rF0Xc5Hlne1fv~JfEGLo}Qjz zoPF=i&dtxyFL3Ub^WC-O<>eK@tK-h@+WPwXhUC-pe0OhqdwWOm>w9N+Z-0OPKr^?z z-<};GAD@`49e-}m&d<*;EcTx7w|Cdq*Ecq2-#@o^_xJY?4tM{T_useY=jRufSI3{< zxA*t=506jJ_us$o@9!UnTlr*?50mSW$xa*}RRn#*GE?hZTpU@&Vv-zPMO-)>uT2RS zb4#14Irrz1(5#@DX|qEQ{(Lqw{Myby>9sAB`E0-J2=>!2aY<~M9cSx#bXr`KXGXl! zkAlNIS}PQsmS|llU>0x^U=b2@xbq=niKdIyVP3nGUm=U{!6Xm zT0HI5s-P84tFo4?nZ+fvX5K5S?6v!DWv+2{NeJY!{qy7To6UbdEasI>YHD@YubL)& zPBoV2l(?Yf1%*TGPwEaF-1&5xHM2l>(vg)r9#4AR$SPLxz;V~&uxybXkCtWYvHz>v zkhfcWuk`voUv5R`as5;}x}M|3Kkf}jcs8G&c#!>k^!vT9?k#w~Q9;^;Mf8+S_NS9i zUof^Th!zxdJ9*aWHJ^&#Q`IB9AB!CF_eylkE zRBYqC(cv!7#+}yH7fdb$3cvlhR#0>Ddl%e;|1sXfRbB6oxblb z+5FBayA#~}U$$tj`Glk*i)9W)p88LZyy-W~4Cz*LEqP~Bq^~~v%z0JwJFYC}%5UFp z;)`zicucNv&PP{%<1Gg3_sVfR`R?qn!XfXFZq2@+`01huv?l zPOtm>{`<6F+vf%{IJ#S&yClphnBqgUxsbBX5Sz;?^@OT9x*EU=j*= z!2JDHv`fo{^_@EpaQCe^%Jo0m!zDu?St$EPBeQ}-WA)sAb(JR#oPjHx#C8d^87*1J zTiCJfx@JrJ<4=kLtr&qIOr9K90fHnf?aQM@b0NF<}6bH?67Y#tqxrt}mv`yW{&YHXk|rDefVXU$X5?2(rj z?o&A!FwN5^P(YD+?jlvkNFBw*Nt2j)m0HYN9!JiXIJ9t^!_KssiyDd*7w(Up+0 zF1YsBlV#TTf1a(Mba~E|FG)(>BCMiQ4n_X#IKs1{V8XA3j?(9L9TSt8zSJzkN%B^} zF?A-^Q|xXFc_+MZ^)Yp1*P0T<5xam{_Cf-S4o8z%L)6X5iv-vlw=5E0E5IU_l_lVk z=s1;QMy!5u*Vv@=!)lTBIzP@YG zqji;cvz>lv=^x;lCe?CxO$`6)h+|gY+T=TQ9Qo63ZvDS)>xMbLITrTa;ig?;ic5|z z%rxwdy0gw~V|VVGkLPivTN! z5)y|kbhHk9U@$!urY5}ZL#y$ghvMZw#1-W}vU~A(pIaDl^u~#T?%F#KB`%j9Gu?N+ zH+fQW)SHTRwrNHNO+6PC_rE(L=kc-Y{;E_y>z@(<+X{>4zFy3g_2_@(!-(~QYL-hi z3ObjtGBzoE2)9hvOy>4jAupGAGrj(dPRoVTFe|H$({ak`sf}yQHm^?9&DIaUeq!6Pt&=A6K2H5FHCK0G&c?vCuT(ehy1t=} zVP}VqQO13#t6uj^Cm*bRo3-htN8pY|g*zX0s`hN>j+?c4iptFAzRe~wH%=XANN;E{ zIC4Gm-3~YHb&3vt`x!YxKD;>jV`Be=A_xAOZ|+v>3VTa5&WTJnV_GU(!yzqT!Dad1 z!o_ONR}VowAt7G#qwE|#Vv06jn5#M5CiO4O%L=y^Ev;x|TT-KasZRg7_4N(s?R9u! z4mdJyI=0O#$8Vj8!rTqE%gcHi^-31WA9<5$e|b0y22_f}@hab7*C`fZJR_3KiH zhRa{L?i9+#K9^M6-9G!@mlglN-E~xQYF;>%zvRm!fy5nInwbK3kIrr6YG~UTk-j1H zSnsFQ^RKi-BQ8|*)<5Eo&S>KQ_j*lSPNKKRj+O&|1Np4htWo%X*8NmXL6MZlJ^5uG zji-bC^6#AAqwAEwctGj{+n)Z|_r76k0CuU80 zFuD83vE}>z-)mo3^X#(i`HxNezAW#pNnofHzw!R&x7bI2`5WwCzBMoYsd%BL*~b3Y z<>~d;#OtLD>KnpUCI@F+Y~q`~fi=)U;G1*CO9hUrDr!>}7gjZ}wTPuNe^i;(79=52 z)BD|VW)q9?1rFYDp1;DX9tSEG9y1DKWnI77V^%@jvIC3>K?x2G>^0Ylavh_11=u!j zDE|39@o)oo=>i6kfCdXkC;1QTua}p&W~8liNOoS%tjE~m=6C;C+M1cZQw6 zL~EXV*lxRzi&O^raMW|7YWTH-TTcg2V8$_sWojIqX3b3z+p@=qy{1Fk3v9->o29DZl3$ z_b(;Sl4$~YZQlErH}6m*pl&UEfo0JK-qQs&MJLKx68wxGFdIAQ3128HvS?R2 zRxkA+?{0ecjuqW|ELt6&mF$1Pc+jH9Ke?yq2lwF#J+_B?G#pE}&*tgrVt{L733Ru1in*H)wQkIWA`I(9_G%d;CXo?F!bL z=H=hY*|MhcR9Ey|dce-uz$o?KAXOu9l7I1}-7_Z19P3?oVA7}WwFWEO({I$7R!+8@ zStfUIvhah+#~G#+TTIc7)Z;CfVl;EgiS1J?R!;tSLV5O*e5K>6RTsFmpF36=FgBNS zE;{BAn8cza5G(Ieo!3;S?a$ic|e7c44yAfmb2d=3ni$ge*7bvjuZ(vMXAv8&|WufJ)87pTB zG%(KnIdkF3sVAnlE$f{1AVO%h=geuGQ`SfNZR$)~&{?{;bN2F?vl4Hn#V+#F;c(!6 z&Od(w1Mf4w`Uf3cAp(Ne6J%C+St@X3&aAHazmi>k`ljm1u&!3m` zov$-7zFNS1tBCFl#M*oDaq)eOA*cP^XxlbQbk%gz~V)U0@N92hKi&Q=Os zQ+;7p_Nm0vx7M7untGcn`Et}+jmEVnxYpgiwf5YqwYRm_UXfzDrnPdiR3l&c$~Q-u z@}KFfoxt#iW0L5XKoND0z7I{TV)?w^5`KA1f1;@o_+T-IItPonr;`Kg+5kQtjU|CW zUTbDBFZrIZGHZf^L)G1tVoOY!8M)T3v*cO9z_Glc{-G9cM*+hh_GwCio7Dezuj^a2 zN$2&Zmr|RJrB{e1ZhkXsv-a&xmESkn-JbGkma=kt^+Xl#Kp|GAg2qdhj9Sliq%#e7 zpUTWI$k*H&l$~T>vu&csgH`e+nG3GztY5%<*VWVXg$@f#bNRM;d1A(6O%sy^q$ zZROCN>BwT@uwsh=@5LR<44;MNiLUbvn`L^9$-!E%L3>9_^}-NMo?{ClyRy@Iyczql zg(m)9+8n*(V%E;--J9R;+BtXk7Bi=2waeU{>8mAw>b%^*ZpXmVoL<$Q#KOL8o0$U3 z|EoGXW_#rp6s(czI#;w!N15f{H2%&RyQ{x#=v%S-rYK*kEQkEU?&-US!!&xM?*{hw|<%+$>cLnQh@* zr!G`?8;AX`+M{s9=;OC-pG5iAUf{Zw(6Q_RbDee3mxRm-J3XS87Tyxz>$=SSce7Z? zbcXr~^S?(Q(KF*IbztDzu>ZZbwbPpJFWE5(~RA;dc2 zL7|XN{LclvRSOoeE3$0Vh;NWg&|0PGw19p45{t8ocoG+!%JkmbY?HoN=itq&Tn%AC zdrcZ^-yC0SFyrhZ-t+^t>4{;&4>%^AIXP3Cw=sc%?*U`)9l;AaXJ`AIy;^hj=AN@M z7tdbiIrmcQ+%29{=1!`K3)mH8_?|A{-CMw!*>G&VGi&CA;IBUH!AEN&8rYX^IK0l@hXZi}V4F1+*M?29?;Itv&c zuQ{ds@!}MLOUi#Ysn%Ya_C`SK>?Pg*YuD(nJ*#o{oUxEvW0}TQE>@ir?sG~s9NwP! zb%=TEW8F)pzEdxKxO95PWyOhCqjML<=3a`I zz09k4E&1%#xVNEJch9X_v61tO1?QBF;)nAU1-&P;h^IYe>~pxBJ$KTz90sm}YbqD7 z*RQ?Wc(=7V_D0^^OJ&n;m(2oYXz?4-aXTM_vEs>ch=5n z*R{S{d-qA~z1w&1uF}2xNmnw2ouTjm&&dzmZ)5MIIGp_b`z~kT{qM2Mf4{x+_wP|P z#Rosu-e;Ycv%lcMf7|;)a+32`vmJEc<+=A@j~aKl0K=QvcjN;fiqCr}^)C7FfrtNi zAIT{`l8AdGy^d9r?}4!0<6^-bya}uu9e5R9Jz5gUvj4>nqj>^meUGj79X&F)&FfF=yZ=WXU zJ@e*^iO}OpKlfOF*|S8uXQ6e^8yQ)iEMlB^fcMGi#~XVY%l-+5|6`Q;aJ~NjyGM<7 zFZ%X8ubuZob>EBJzUNcqW^TI7P~E^gA?{JmgNKR&ER)~WPoMX4_PU32`4~S)y{a^O zbt8d?CFj+=f8|r{URN5fh>YaEmawbHj%VeChY}B%7SsuCt7F@-?zPRi*ZcV1tg_RH z^Ln#W@44HJ*XA#o5`11?TPLns**!Ob_ZY)lxo{tQV5-|D;m) zMuYE@Nd8Bo|NBK6v!6x3dwc%FQ#ro^!}!mUb)PS+duAQ~LGIz_0=_RrdS3(%d^W!S zCI8^f<_FK$_uajez`k!UV~^amHL_oq`h5+1&k!O1dFHmSLGRy&)_;wB|0PRa%*mif z_yg0e@ziZ0(<;k-Z=D%U>ds3(WEqneC`^5QO3?EtZ z&ax|%Pi*~R&R`&S;RnP1`xEqky41h>)b!I)o@3(uDIM#7EL$%;$@7is`iFb?9$(li zv@)K1_5BBH-{1cjyKefrU%K%>RzCQ3ulCmgeX+*h;o7}lc>nPju4eFhCv^BdllI>y zXM6v!Gn6`<`*SGtPe$D3Oa6c7{+IuAPhRwbG2=PEA7^{tOp*DvbbjVGi+`$l{}Swf znr{4e^xnTq|NhBNx?Aa!UM+^PEoxSkH?4E`MY+gGKXD! zcst<%7W%q1W1uBEcbru42(8A6>;eXEZY3c$DyLMzWhpjzr`M4_+qm zJD)aaN!o4}beH9S{qeY@Mv0G`l(L1C+tuep5A%(H2-j}y1)mw^8+!l7TB&(C?$ zB6acKoJNbl&c- z-=YgP3MIAiSM5%gOmN*pl1n_xakyAi1E!Co@il^f#1lv^}m;#+nv?uIx^%ykObQ=Wc&1o=gs( z7xu+u!GW%TH8Z#QJ=$#2S$1+(z1^>uSJ%j$Xxz~6Q~hFTef4+w_3?GJ-)@)hKV4P* z`O%bvU-UMXi{Gl!`^WL@{N3Nbf1b1aGduq83h@JfI^WlFrz9}Tc1XT8Y^**c%(wK? zBvsqqcZJb~^Zv6ax*mKG@xfg(Bw>z)2P3B!f6G=uMYhA=9VCtgv>CVX2&6q=e7^Bq z!(r$6_f{&hYadKtvWiK}T;<*V+NhN7g-wYQix4^F8B}##h9_^9!d1P0bd0ziS z+De_w1?*BG=R`Fp9MyF?(cS%fqQuD=GSbst_e7bniQjzedZD$jM|Dk-{NEq$>~R~J z$~VuD-EGX{a-^3@>#_0)3k#389ET@}`lM`-;8buF3YzrOafy;Xr$<0r&=kX-`11^n z>wL?ei`NPCGynPO_H4=|mgOdHTCJN;h3(rkQGiE+HO|31nvH$>!r=QFy_G&GYWj8J z3I}EL1Xl{2a^jOY9A?P+f6JLPyUV%OlhjPpx1T<9#Gm>*ZD7vyMKzC@7roP1z;WU^_wAnn9d1_= zvpzSlYdm0mC;72X-~z)lA(z1Jq$@Sjw=&#+n<-3)Gg+*%SHZnkJ#fackYyX44rOn! z=uA=Bq7(mT;$@lk1+(m)EVI13Eb_(-)%k~ttQ@B%i*;7bSnQ;*^1+e%${q~ z&%K!!xn!od#xjr9PqthNcNPy5>7BYdbt-d2W?SfvW1;Iboen*dV`vL@$eJW)d0LdG z;oOJ7(uOBm*JD55x*E`UXnn(9%~Mi;#gHvSRG z64jyC-tjD$)yL<^(bUS9Zp$5Yan{i-E9N%tiP*jW9M?szg{rxkl?AuhXN0VrrJ7gR z`&&Zs#urBGfEKgvD#19GLph0Sq z_n~cG_1)k1jx#8-ikfP~m3B?s*T)hqE2J;*oZJ6*k@u+V@u`yzHe$4; z&bg7jBEV$vQI{yDhPAv7I|4%Y^|5V|=?d}Obei>t5$hqIB*Te66(g=~QgOZU%=~!8 zsp@CNg{=<+6!$dB;5}MnXhH@`;fK% z#RC@pio>%13Od|l9tpFH3+nh4_N2!=Hr!$%X!fsgLi?WzS@Ft~zI8=Ymd8BRPOm&2 z`>$xm@t9}E%PY_3))mir9`oG#dFA=qf5i*fV_!I{S6%F_D_No*`_enT>hj!wB`e%x zUj;9(y1KTmbWM8f>*(iI*Z2M_-OwKUCRx4u=GnTkEz4uyW~W!*zWc9i$MM*A#mlSj zzO5_Y^E~!__4DfcfB%&qV2}IItX}hwx4zNeUx{tl}HBZ#zf1XaS`#kr5%?tPVUzeBHeO+5$`zAg9_wDC(-}nBn z{m>r&=dpVI&$IP)UzW%JeVtza`|kg`AIIbWeO_Mw_icUspXc%ae?PDP|M!1A1CIlv zj02O71G9|-i;n|qj00Pa1AC1FM~?&N90#s74%~Yjc+NQR-f`f2XQP|8X+laW<53Hqvo6wsAJ` zaW;){{%@A!Y+mDR(c^46$JuI)v-KWln={U~cbx6sINSemcHnVwlyPy=adEbBaq)3+ zjd5|yadEG4@#t~!oa5rP#>IP&i_aMs-#adTZ(RKUxCHRH2Fkbw>9_{lxQ6(+hQ_#t z<+z5|xJLB2M$U1KTH_kM$2I1RYwR7@xHqoxe_RuI+!AHnl62gXZQN3P+)`uQ(sJC= zYuqw=+%o65Wvy|`-s6^Y#x3`bTizSD{6B65Jnn@u?nOH8#WwCGKJKM4?qxad79Wq+7>~9bkM2s#a@aT%&8C9>n*&ud|@vUU{PT3zWlm%OON-~E6nm1 zUfcid(KylQynuaY&*|(NOsn>sKDU@D)x*0gpe;;;{csM8)CTW^cWe|EG#5CWuIXq| zT+n24p>2x}t7yTQ<45-Fv0*89@XqCE-W9?a#ryxcFK2FVu{mVob0oxP%aV4t4U7+E&Yk4;-S@_O%OCG+CFjmG zd%v7>de@e7r-VjH?Sq-zt4i;OEX0;Wo zzrV3jTygI28UG93UQ53CGs*@q=>{;{2C(=Bu*L?k(ajZ39Jo14Uy4#c~71YXc>E110AMO05l)-Ww=$Hc<9% zpxoO)`M-e*yg`bxK}xzo%Ca{@{y+N9DgS6HLY3~ivIUA&VH%RYo zkpABw1Kwam*E%gP9+5?U9uMHv_8gr&z z59sO^$!IX%z?ySnW%35LkcejS1q}bQMZ=qAm&z;>Lq|syC+mRhC*Xk?jUkR72z+p|<3X8{!oW z4XoFi?nX*!$;|)Tw0^;yE(zW670t2>80NHIPfU#pS{1&|gE=~)Kg*IW<^#*@qqn+t zT`PPVCD|1=-}XE2IBU^sI$M)W|~6y7^xo!skwFwbyZ-!P%FKir5g{w+9^OE5?kY>Qpd+W*{K&|T3`VaLahGxpWInQ7ag9!Gy&iKm^rz!=m@vYZ{(&E4Qnu}L3>PIkptzb<{V9Pkr zmbrkf{itC0iYE30w?#Z=NUxhZ?`fC*g4TL1?nS(;v-dLmF9^N=HTQny?Iv>tmZ*j# z@nuOeE0e96+u|p*St&3GeP|HsxUM%%RKxRz0Y~)P-p~`2mua*!vz3=^fKzsg6#)WU_x8l+4x%?tS&2tRKaE`(7<|t;ltGiwhrcy z8w-0X`d9V6WpkhK+wa=Wd(D53vH8_K{kCJ$6^~nN9CE3VLaaM-+3Y`_){x;Sf9|p1 z!|O7oZF*^0vG3M56i)VR)q0Wk{@KTu5;4qt%uxrPD6SXE{Lrj__-1I|?dd1q2_DFn zzEP;Le(wJ>W(l%4niEbuaekK@u!4!n<8lAIj6ROedCMYx>3x1)5G!hNy=zvZamG8Y z?H}F=u=%WL5?5$soyL+eA-eZOvNZ>T(1Bv3>&3@jWIxZnX`c|Wi0R$KgRCJlSo{m# zY47Lom|oIVtL>f7=XN;XOW~{TWpNqLwv+|Qs>hQvJH8yA_BK?VOX)=8>lG`GU2Fa; zm)v9c-2Ygfi$%jD+2XkOr3-g7%D-<^$iMM#+v}9)+CD!RSI&Bw-u`XA#pf@)&EXke zvh8~=e)=LIp2u{f;W+DeBdajJh3p~ zc6O+}*Lapv`ky0`qvgN$iYBW7Bl%~oN=c$V6PTD7;`tXOG#}@wjC)r!zb$Bc_vQ;s z%n|wD_-0?tGYC* z)ACOD{ppDwENSfbPc5rDbt2Iq?d7crZ68j&$jW87cvVyGuDDj~&igE_;aZOwg- z%ndAg?Dr@4{yD+%(|84IRzz)BA?ttLf|{r29^`(gak0>yRLccWC+TzVwP(obWccuxIc)*=pQ_KgH^g$_NLKEYI zifaY`j&G>`rNpSF!4m#}@6LU3KZa)U3yr!A9UezEs4}O0Sa2|L+7gQk4<0V;v)#5q zQn>Ad(y<=#rL0;G2NSszJ$feSWPVaPHAO3YQ_jmzs%K^xrC(Z;`C0AU9INtAZ(e>@ zzp%imT}U_Ui^ioTUek?oUwzRGS>lveQ}Lql5Hq{agMwS7Z)P0ZAl@$PeXK{qB;)d= z#;X-)L>2U{r_EV-r00QQchdL1($LfcZ2a;$9GzMJe;7PE(j{)3_vVM;lM|EFgV*K! z+?1?jwkm3=!@+~yrgIAZN}2VncS~HgzfQC)>ajuMv9h;OX|vbHUD?%W>s-RnbXd&J zKv+NTkHx1ar=}a{zx!kP<%P|}A07v99%fy$;GoK_*56~Z7E!}Hw_B#34srLJ| zJ-m!OeCZui^8VZX`}6Dj=lAdb+c$jYe0Z4WdSbgMr_YtfQ&r2hepfKq?-3!@vYWS= zQ}{sTghK_4RX-Fv6uT^xI#p*?EDHAE$#CWhi(SCTDqyjJS!UszO>udmuXZeU+jC_j z1B-aY1*b#}sY;beo?1IqCi_~=oYJKu^+J-xdW~VHc0%KE<>}UZ|Czl+SuCD3@+sR^ zs?Ew=wNq_&?yktlDaKngBzpKAJ}^l%9B7K3UK^(2qhxKva7iF-U!}&PPOV)Ui+inB zDmBW-OrP5m-TQ38{F#f)e6*qj7!Eprv9!`!xpY>Q)~c0yZ7p4_Mc)>cg)N%o<2vis zs=&-Se-u$eW z^*gt24PVC_=bJ}Qw5VUPk$$^2-s>X+n?NeJ-rldbs`dB%bmC;$`7~(5VU;U?4(V;# z?-9%~fnRW?{$XD0KL$s5-7S~18(2N;G<_{}Cp~l16vG2EtXyo2PO8qX`Lt;5zW=uv zBvwQie>gVF>+=bY=D5>Zrz~IZF+Ok0Z1G^Vh`^$}KEvXZE5-O(ra3LNv;J#xCD5Dq zCa;Xml>_3-Q*ug{oxkGPz$|TMYkD(vcCFbhb56tNt8y+6ILuiK->TQBblB$Ks(iiI z{Jt&o!ARyp0cC^T%OvY89(8KJQ&=9#BJhpJ;=8To)2Y#U`hq$27aD};1|-j0#`o_K zx8Bm(b-!L7Te0ugtN4#aJo+mq1U4{>R3tP%nf`j8_4~cnURRw(51jSBXfw;qN~37Q zLRZnC21QrVR1f=F$$~3|w%@M*p4cIOcd}qJ*8u@A-6t_4q^X24mZ@dvT zzoL=jgC+x$Kt)5klg1&zNd_(a7Kt3kuQVy>2sG){DDotqkXRMs%08(hdb-8YHo*&g zO!F=tU~SSkqA0Yn!}$t>P^-xdr>y~PelxIsUYq{ z8g7Pat9#OX!X##D95vmvu{W=#Qy}C(qln1^o~;UV`c$5@GhaB@EkC1?KSK3{qtK=a z&K4?4f|e)DjW$i}Ye{;hkkYBDbZ%gTjM>2|wjDPX$g2nqtRrM`7DU zagM2Kf;=xCPx#Lyc`E4ArfJ)zB+9G}b5E*ab&~2~eA~46ShUdQ8OK86RctRbs8yVk z5U64?kp0l0Xt=TS_#QR0&6#Fed?y93Oqkv3aIl$4<3RV5&CAR#uRK?}sHav=!|?&z zbWb0V#yO6^7&LCKJYW0CILT$g<7d+ZxNSZ?^^SV5Nc^P9={ln=3;C{!@!CFM@+wH4 z`kawfa)*Qp?~~69<^F1T__MMI?$GBuvmqm*q@sb(%7tBrN7E-+>$3UNpqY_}6>@?O zdirNAU_CrXGoV>3L|IUAk*xr$=^Re!$R7`bqfLyhJ4$yZLe;g@1*8cIp?@H&S2B)QMB&8rB_sPR<~$! z_q8*HZA|(N&Wf)TA{BeT?l`qqudG$-Vwa@@p&$q0rW7c_)w912{UFAuG@R|p##ybx3)fu!X z>pbKP-f>85pFx}Pnuol_I}XeJGw5*Ec_jFM@{S{Fc7|QSYaWSi-f>i~&afw0=dtAF z9mmY}8TJ*gc`W;R$8o!Vh7+1~o+t|MJmF?%G->jhC#uFfPx{pvOAYps$0DCblg9q8HaVA8BX4LCe6-x*5x(NOgHa5n^$K%=dsRn%gZ~@mF+X0_j%28 z+s`}C*ZnhIz^wbiQFzydHan9=!fRi+8t=N;S7)+BS@)%9@UBbK_L(d*Ui;Fwc-Q55 z|4ddm>%Iz{yz9y`JJVIcYhQ(K-gR|do#~on-Pe(qcU{}I&vae!+Sjq4cU|B2&vZkx z?wds6-8YWenQfZ9_D!ns?wjZ8%(g7neVZA)`_{F6X4^KeeVbdn`~U5G|IBtA)_qqv zdH0=XcILY-uYFg#dH3CSb>@2>>%OnNy!+m_edhZwRbx-t&OX z-r^8+AueCN#Svw_kDbAL9*OO@IA*-=V{h@E$8!HIPB`m*nmBpS6E%CwQ^D&#P2Ifb zsb0P1nPk1sGcWIXX13q*T=BZkb3gBSZuj5vLbKkNg~EGZxY=7>n!N7IQsccZ{pzi* zEY|zFGI;N+u>DroHn01-ws`OBxc^o+4(ol}IC<}zG<)k?m)CvUx_R&0yn5?9kM+Lq zyu9~a*?#MLpVxig`+4vCy8qS>nDu`g6yEot&EDpb@cJJ|jrV=*tG9WgtpD?5@V-ye z?DyL|GhYAmZ1KL&^ZwhsaMu5Iaq_+|%j|7m1+V{gb@RTj>*{UaBM5? z{T~@`^BlgFaxpGVZN0ZPCZDuvytpbc)mt&)wbrys=PYLR_1jdf&3tBTNM83qW5I+g z&mWyv={)mb!lHwc(Kq@yna$R0+7R11!{I^B4Ys5UJJf{&9d|j(Bwem!l=l0hzuZ(m zWAm3;7TZ5JJ5?-a*w8L%`tV45__3JugjWJ)f#H|9~;$r zJ-L5W#ypRKF>2m}pD$ZHj>T0^Ke(xl>EqWgp#fhx3z>QMEN!_I^!RJIn3tG^(t`$O zuE}0G{3U788RE7T!Csyxw=ZZ-tG&?B_PX%Iz0~6cMmLya);&yfuPVY4fJ#@AnDLT$AAfhJTzvF2`qCl42$+YU@ z5-UQ3bbmfz7I1L5u_&-w?q(BT^qY^Jy4kvu&#by8lElCgbN2rMjf~!%H&}GD{cb%o z-0;>QI;OH{=43y)j0aBq>30;p46+i9c}*w(U3yC|>d5s&0-N>3rgldkaq2bP3S^{H3V0n+C?492waD#C1vwGRzn3iDz}*Iaj;2;bRkL;;Rcs zq$eI(G;Ni{|E(XF96nLx%AoN5_Z$Hoi*Ia(lb5d9H2buHaJTy0fIB(y7hml$JU-bj z*^`G++!Ms8Gnhm#n+eaq_Czyk8HC zBnmX|E$H65gnNEL@UJDTbMq`8+2=br?q7SmHIYB-+_|*3+m5d_y)N~EyR34n*@c!_ zdqVi0Iv&-w?U66J-CJJI;Oyr6WtUP&?GD@jXLg)8=NfuT{2o{Gk1xEv=bstRD7gFc z`G1Lp`~U4&dEY_eZT0*fIVF2ZPi8^(0tPml1m+EI-#7kV-JM|MyV9{$cCvDFkQLID12il+oX*>$|(VX21}Y91(Z!SLlVWePM&MQ<|ih1 z#fy7ik-N>OehuBI&djVrGoGSAl_L*XHU2zc5Aji(!2D~GSi%i`cc%iijGiT|Q6JhO z=B(}2Z01zrPiSD>!@#$}f~{=9lf&yO6FQciQTEAcnm#q=0q=^RDLU>=7Dh4)82B0v zFnchxNB?Q{J-ou1;Z+%90^8?_%8G}0m1a&>b5W95A0p+mbqiIBRkg|qsPMQ2jGp2U?2Ff>(6vT==Y4mvE!VO@X2@>;ENlj6#g zo!>-SY`W;N%7y_$(v{GI3f3Ro$Jv_ z4jl|(b0QXSHhV1l;3qC}{r`p6icgtuv5Hj&DtoxB*S_c=;SzY+zv0_+7#K( zi5^>2QQP6!wR4iW$l+y;TkjO#uxxUXWi`B5%3=8R%Z%cr?L-+~?&uiqsgg>EwRrj{Cr5t?=`x{y)R0NjA)ld>>}n0<%_$o6wP|3$t5q3Z@>F_LMbQv}5zu4|lj0G-OmY3V$l{ zsIGQnV-{)Pw6HrCtg9&Psw>eiaB~`K+k@ku=jj#mG(5|3*w&W%;*-MR7y9~rio6C& z3QP?ZFM=xr+ruk+SG&}3oRpc|mJ&7T|Nfi>h7~p!7_=+053ubtko@z2EAfgxg9-zK zVvUzWHCM`B7Rfg4Ed~r9ZWx~BcT{GNVrW<#Xt6s}noa-2hOp1(iGc{ncJan=-%2$XFf6{`KT!whix_7O52!i!v~BOlY_v($OF^ zd83o#KPJ9kmju@;2d(B<%^CCf^c@Z#?US!!jw@W+(9GDemXXV*fk`T(L2kxGo;An% z%a{VSwU!*neZdvHr)tvyA)ARjTl@Sa>LMICv^EHR^JF`{GNHMA(xoPgnDBM)+rF=0 z-pEi=t-zYWwtQCl0`XyI4FBzCeLY? zm`5yrcbLsKOk$fCq-1v^o7L#=3DbniO{h~SQA8Q(z z#SXAI?0EFfli%y1M$*p;@5KV#AN2CGd4*Is4ze42I0kX(|B^j$PW&rP-}Y5(&t=G-`tJ_${kkZ?Mz_U^o-d^(P`Uq)#mU#fdvfK301#TO9dJ0#X2$! z4odA|$hAplJgqKN(IPngDWhNp>%tG>+9#UUxHssZkec>^`OdROo(Q+I>P-v6E4&pr zcMCLJ`CL}X-lDir_Sge(=ZS zqxn{-pM1=^oFRwpq1%zi6=EyGN(~t18fPnCjQ&+zU47I%Y*`b_!uHG)?fL&p^y@x2 z{tsaCc+uLD!Q!}GX#O+K)Eynur_{2U3axo)$oHXfdIpP%b6iV-S>=z;UJ0+4qTQP; zy0`2|)-w^fKB;AShVY~kHsj%shWnd3F@^oS4ybYDdq>9o!2i_)q_o(Ol8x zR=}*~$mDydV(pEr+a4bK6}V?4u;)0ir3UmptLRHzz#1CBnxMe??nmFd8-27D827TuIePRsb^!Xz(RX|+mkODi?hG|j-{jHT)X-}_kUYH~s zp~gKovVYD(=5Lkr@2-^Cx>IQT%lWJeGs_H^CTPxNTh-rfI45dU@sUnF;O(J>zL$gC-YYO|km!`>2mWXsoyI*1OJ~01F z63-e=-}>~$QB~8o9Acccf^F-Cy!`?k^G-^htz0(UL(Ww&<}W*Y(1Xd*8|Rjsns;V% zc$@mf=V6my?Oe)aA-qh|^-@v7 zrMj$UWJL7LwlX|ptY_##>6x*0axgNra0s@*PdgB5y%3<-beNq_tA@j|X(Q;g17D$& zijSJT`3-CvzD(S-?Cfl<%q@Q&9BgWxVGw*nqI2_#i;FF7K7F~cNHbuDafjSoFVV#U zqH@(%iYlijiVN|Z9PwGm%z1KE#$~CLmzxesMqk*V8f}*89MLLGmbT+;zAm}Z z)85QT49R}e)%x>c+l0LndW8G@iPt}JUfmZ}-^{k5U2<#u=E;}E+D@P6g)1i zZEhMoJ!vcd|1rz4gLfC$)p-9?f5PUzRNl$%T%SNk7ynvzUbgjru5UzA!={)rhDyQ*OK68EU$n|n%`9x>CoGTB!4gP)!2~oPl ze#B4AV$<1Hi8PHK?NXi>3j;n!s<`k;zkQP6Z*O{)DPWnW=tFz`ZK}$>rfTLr6>~fu zGO%{n&Y0)IwR8HRPJhwNL)-}hi#n8^-u-%Tnzzx;VCKF8=F};tDyMPD=nF^$Phz$G zvba-&X=xI-Rn5nCjUx`5&n!C0&~$(~U@M1=K;%}3&N(GXD;BEz#JpUXY5wEEVP3~W z->0xk&2Ts*lcKX^vs@jHu-#_IAYW@cILNO2TclrU@MvO@=$ju*=rl`U$v zI~ejpZpxKKFO05SST)n&Fwf_1lOmoC2U&G5TuEDR!>Ijc!vo(+AEP;OE1$1)G1|&F zv*ierw%LsnUfH=f>W)ipXQ_GZ*x{}A_2Bx0=Q`IFz1mfDoKND2w&B7yrBxY5o8w;R z_Z~hWcz{jhN!GPV=6|lbs6W@6v#xCe!=s~oDo1<{aj)4`rEhxmUG(i^5`2@p#26C< z8c*a-`{T$QeMD*XsgkT6XLRROT=LZEG|K8ZXT$&dj4}_4LKye%Mc1y!$7|&BTn=27 zEpbfZvCrA7*RQpirRPX2IKV13vta!}jbC7=mqEWM>NK z{3&%axGLxOd`e5Y><@z(Jpv3Ya%T)aO`7okE1O|!)l~K<T6KDQF6vxp_Af|odC}Fu+0NLd_5K|Ep7rdpFdx)7(bsz(#ORo?^N*o zNn|N3OJJ6IuER9g? z<>p|#aEQaC;PjDJNBITI#Wa%K{8J?~k{lQ=++>*V)~o2IRTVfRMP$LQ7+J5HG995U z3pnRDxNTK9v{Sz1Ds%i@HE-`lf(3`3@R+!!Y3oiGN>pJMo3~+l%vSgC=d3y<38q?Z zab1fh{yQjEB)R5Q)~ET&2YihMKSqkm&1Q;i4P7G~$=RGB)Tm#xXyvS(FCDJ0+IH)| zPmB28m^-$IvnEcRa+Nv0;%HCKslE4Km`vH-*_EQr#4=as=%%eFu3t^zzIx?D!Itiy zsdk!4b5H298cb1Go)+1z_<%!MfNh6&=GQ2%u00ys28B%;AD)I>P0cQ_S$)Fb-^8`E zfB10s^Uf7eIi=dYucfzYLFQJQ&Ta7xOoAOJmKJF&(hW#(68pWjv)YunRx9s5A`KPt5Kd^nl+qAt0o=l3LRuq<^ zcByEevNNOI_XhR}4uV$>h&gTA8oyBM9Aj6*^PcIPT$(ltNxN&GxLlK%k(iVAuW)4RG#Ec3F>#qhrH5cMKCvn9xIyY_}ryyL?87M5d<6)#c^>c3tQ^emOgIe5x-v2Qc0fQiq9Wm{4t zT%_s*8kh_ie7RbVE5A=N2M4oc}y`svQ#@zsTWqQ|^B z+(ma80=AyL$s!iEea+!dTu1D8G%zz76fkmcIdJ8dOtH7kg$7#(zwyZ6?$ONUPU zlsX{5?#jX}^^i~5@BhZNPC5q|lOlzybuX=+5s<)MsKKI>wR*uVBs%G!MGhUz1)#v_wB1v(^L zzE%k;p0QOc-EKXTp^+=*$MV;HF>1Fs=O1qRaESlKy|W)S+^CRW!tklIo`FSXL$j&R zp>syZY$}2-|7`qmT$JIOLy>Q-km8JcjuYD%IA;W~M|@D4w~5{FZD?Mn{05tMYK~3s zb3dq_$Ug9H&H5(!go!;bFKJqzmOt^|peK;Mr2DD-qfg8D<@iN1*41$qd}z`BHFc}m z!H){-RvdCr`0da&! z+glVngf>j!TD+B!>0-Ue!Jt0(auEj(@06Cu|F1RhY2?f_PYns{oT?$v_`yox1AirJ zn@%f>*@xILhVrkMpy zGh4vCXwtMrMl3liwbMRME6|)8>^XHgD~mTHL%o9d#2f8e)49SQ*zGzfV)bBJVdRX~ z$f5BLT3s}pX8J(3UT=`!a<;Li9sL;gk z0;l(u%EQyRbR%ckM9z6UbGG|NcU8&a7KS3>ht@?07&sI%mYB@H8YvoXq9{_%wn89% zQKi711`g#7X}N0FpEMVI=@c_KVlHpMsLpJWYmsyPh$BmryRg?nQLhCCDbuxIFg8!H zF*}iO`@~KpfKkb6kxJAeu_{sR7h+orWFk)F*GYOUI6T=jYtF=r;`^E=m`|~rcyrRh zVt*5>C9Q0df+CD!<`He`vy~4xE~}gw&^3F7;FNfWF5zjq2RIjr8!+eHTpAa(#N>m} zrfEihp4upWwO_Gv*`8LZ8kyJEjQ6zI&THRGJ*|7*1{tIXBLy6+!F%mP-6 zRJFKnTvIk$m?}|D|gN6ZeMd&<)j&8#uBz9N)QtbM;KV z(;H5RZ4~166ycWSt=_moF-?kF=HQi$UmUAGNC_bNeQOzRF;+9wqxAb&Tc7N3e9R`G z#Gwp3<&KvrP_gN7d%t|h4}m6?#h_E}qEw0&KW67QNUocq=(6A5^hoZn>5*1(VrPiI?J zy%N}}d($9cL96WH&b-q_sO7DeucFh1{Slo4j781LC;Bzr&_tMS%(em+~@ZL1q2%Si+K zFUL3wmv@QCReR0Ntl8tRR^H^p(aK{>rr$F-v?Pc_csZ+RoUex9LIK`;hN2;oHdOq~2q=!RFgMpODm)`#}mvS*Eb*?r>n@6bKNQ&$myOeL>9D8i_@X7avaI z5T0nsal_?SVfeyUgUAPt+`1+o*;F@Pxx^{K_hqV6{TjiI$r83rKa@+lr~Yv2)hLRL zFaNRi#*)eMGaQ=4TaGyK7~e=JzOGkb)4=Fsk*9H_FY`;qnHh?F#Xd&!40hb-Im*e% zA|SG>^5Nt_zf5kE(*e$Bla6<&@v7U;kyugRto5DEaK4h%qKsoZ{xcn)X?E(%+@<>4 z44x}&G-!Tqa>ax>tK`rhqaN*00fk6z%Q!U_?o~pQ&n#TGPs_(>p#jJIkRVIWrBkNl z?D8?1uP1gloxN#M>n4A*?3Q0D9hnLZl;6+zAEGU#RiN{bY08W=DZSHivM zm3ekNcZ|wffA(8eKC14jlWw^Sa;x47KJ?pV(kZi` zflVqw?$7H+!Do$Z$C~HKxt(ga<k`MZSwfWLiB;*^5onhwd*__sG)XZ%%peVJW8 zB29nignz#l&VKT5M!mEngP-$`UzzXfX8mmWwdMPq$$#FvAD+<6prdZfEGMA-??h`IzBpYfI*MT28uW;{REm5PbTMRyo5Kec!$ zdZj|~_y4>_HccMPf;%WXKM=1e%J;Hm9!O0QwD%&Q5yEuG#n z9frIccn#G%W}V zyhgDIhquLc)~FJ-UU$P=_C2ON-80@Wh#X1e>z{O@{>V9I-V4n~j(l;S{pXSVAqG|@ zi-%pAoXtvy17Y?ARZNS0dCqUbfR z@d#rOLzUnLC!IBk|JQV!U`!S7h||^2m~!Ok680$$JxQxl&&GQk=4W*{VEeF{(KVu3 ze5#Gdr6b#SHP#ub&#yTt=EB&^AGoppT8Px;M~@l*?))&7O|tFf6Z7UYD`RzQ#d&Ox z9j0gMsO4A`zBoBgd@`GbqsV-#R3BDL2mUKp78h>uw7ULsvI5T`u_`Mz`RbKI$vcx` ze=$9k{~$8A*@IbFS>ZtDysC4vbB?F_7_PG3ToqKA<}#^~rJ2cNLnH4IMTx4WmqGOl zt{uF&rPJ(WqxUS6OSvk`*2Qe?ycjf*!{X0E;fh&e3XY1bOgRTuwr^ePRgtvN{EAXS zar2s3-$@sJjuTTi`*kgD5h4W}R0 zhpZ$PIO+;CadEF<`dhJpv-t1Z7Z*%>;{P;>D{uB_sZZpIdEm6IjCob~Rs)6~0Z%80 zU(^kbDqxFR5VrO6q*m1@2iRPeEZUVN;-S!efWhd%BMGm)xAw3Z@dSx#+8hWL+@d4W z{^#6V@g2X<*atbbF>@3%COl{{J;imx>r>NzUe*W)1{uSn5}&U}lxD1A-!t2?r(=3C z2iuyC?jQX*dJIhb3m8}rG;pn#T{20{OpKG+p^4)Nqg40C&Gl1xy0orTXsP_vaD8xe zy_mqGoyx`W3gyciIA63;qJewBguxB$IW|CRZ$o58Yb^mHLM=c)7 z&1>GtpP1K?^!a<|Ifu%F|4KEK3^*I7mn5(>J*mAHxY|1^B?5SMwH}0;9KFL$H2-2TyU{)_m};`Ue&2OFqpf1dNtpH2A3V&U5Zxv5|)moIwzTIk1Z1mlCa6zD6DxvMQ%Zc!w%+9 z0j?bv`~}skzKb`TG4k+jjm@~kqgBkQ$>9f6f&kY#m*OA)(;M|U5{-{= zrz#XxmsMuYaL#gU$cv~Ja9}DZ;67f^F2vrs`e>Buw}7e5LIqpQvR^RgcC>C2XW#H3 z!&9QpK%&!PA_v=s^8XXWY{UiETC_SPFmL1#-n*G?(Tk29Cwk7#5Wb|q&bXnxA;O}` zqUXp8W}kyaA`TpON2@A-^c*-=pDUL5tfKF>nV)ZI^uZ2+8!Or_9v2aOz%nnP+pV$Y zXM3NJMCPB0q&*+{H#KnP2rzR@@T@KCeV<`*@i^o4%M9fU)N>g#b=$aiH*l|H;NEb6 zbD;oNX8=cC0DCC|dujk%XaH-_2WEQ%CiV@JxEC<|3}Td>nmTjFgqg?v{4U4@{!bH` zbcB0`0;tcamC4|=lflJv3daHlkC&6Uj~CpzGR5z@iPMDUMQMVZnHDD*g#{G~jHe6l zSKw|uz?^n%lFvzB{tHu5ellcqPV3q>E&F7Vf0J^c=2Vucg71HbC0x%~JVW??Gl%N~ z8{g+y7Y-NcUKhU;G{Z2FS;Hkk{bOGgqp+<4XV2ov9R^HMA<7q=XKbG|Q~n}Tfg$s} zmov>4FxxdaF_#LjjhLLoI&t3@4#NP;t(Qb}8D=fioMjg<+o@o7%Z|34J7*V65sv%f zQut7D-xPzW5`W{y8M}7QK6P?-sO9v1mbNE93Q0ZS&{K(AP{2C%GsB-I%YdtM)@F!a z7PjX7FJPG5F0^TaFNc6+x<|*ooAb{7oRd9Si_xh+uDM_Qqc{77kk>cozI*AKn`mLV zp!k16R@J524PUq$6&%=Z&gZ$+=l)Ub{{@CbcV5}{Dp5n8HIbGVgeUXfnm_HKs(d1& zZ$pUFlB5LzEH^Ff7hYZXzC!YK`_$@&%#z}TDbH+b0(<|QTx9-LPmkFvzJTj%=KOv& z?xG1U(dq%(s}|qiDOFZtIl)qzZC4(L71Mup$!ANJgjUKp6tprLxm`&xXi)K3$En=e zx%6zMj0;1!+f^9})g>Wii`I3Td1fu^s+7@b>1k0YHkJxDeI;k$Zi^2c5b%h&VO)p^O}jPJ|lM&7c-n@tYv6K z=_oR{GVC;LKE|u)Apq+r8q28^IkU9$D>$BGSOlIR^yW%D_;7LibOZYv4KqL!gc7YQ z7+xN1^5-^)U-qGK^NPU5<}pzh9y~hAEyS;JWRBzK6<1e_H@^AvVBt}@=raMDNuLx} zwDa4wB*dQHmJqZ~?w`S7H{D31h=MqW1qF<1p(=v6xy-y;jvZ%qfB&9(k2i<+Ff*a|xY|C{&8M7&C!yk^fe zfzOJG3Om*xHuVm*cA9&S@kpZE+wh;CR>(GA=S%fvZ7IK5 zBe8YARUhB4Kk@fdgwaBShXX)_M52|K|j zAaiq`z#Lbu`K5)YZaQ&Czxl{zcsgNnkKwA7$GS~ABp4X0%`UVl*TqRyWlT6O@t^s$ zlnL8c$Gn}jB0??lTP_@yY&mksXI^RJtr^LO{wVdTD$jZ4xN2|a@vMaj`=pi_oUAx> zBra|4)!Y_cmO?hwZ4R4#Vi#JmEivgg>274VS`qbdOMF!Ii{#@wijH%yx8z#Lu74?0 zeclZp=iZGcCLLdBQYLaBchALN%PzB9^KCk7^ljfPjhO{HjgGS%JH0t{&*&8At>{g) z>Cs7H+0e+g>16i(En?xbKW;sKNA;vsg2BcX@obGCZj&Q*tE4uW^D~3z3mv(gUEa(N z6Jd5Zkz{`RccPJ6d97aZajwawmFH~^IWW9As{O(~q`rLX+2qGPMyF16$$l?9{3Ee} zNj&5Kf^7>NBA%O>7qnXjT-&d*?%iFPb$2!~#j+}Xz0zdv!13^#*pVO4{%gj%Fz}U# zZWUZIJ&)z7f~f%KwQF)mET6yWb6{XO&y=?7<_oF%YpR0pG5V78Mb~rKG{w}K=Z(oj?er2MfRRr@ZrLj%Qw>3*G4-OJh1)I z9%b@x^_zKX588iRRd4hA-Tp7N4`p_p_#?2?eBV!A&R@G_e?PdyE{<$j)9g)^pl5kMcL$6sX#ryZY=LbK{aB12&JNB(X$DwUc9w>`( zG-*_c?-xIpFHs~hFXVrk^I@J_9}Ij2jxslfOn&jPiI?%l>91Wg9JYxZtL6RSq{BCD z=adq^M9JUm8g|dOh%Gtak$rJ4yVL^qw3=1jzA|lvf0&Ok@GZ&trY*-cv0QZRgAMHS zBYN&0nlAMJ50gmU3TKTNMFBM-mHg`0(f_{fuv;B7F=?@;@2PpyCrv%s$jBDaz;xgM zXZD{arTq;`PY$`dn#e6Rn6k-%SwBq1Vi8LRyG8@E!iNU-21e0U6Hgcf1-1&!n=om) z^(n8IO>VXVhl9;mcV0TPoPqbtTPBHs7SkTZiJN*Ax{O_(Y5(OAiafT^q^C2@>lORC z=`jl!>u0zbsT?v;Jho=)FKaJ8nJ@n*`Bbf%mKd}Arp$)M1q=`PyB#|=JrQ6y&i++;Z`g_edowmJTs?-CTbxBcBl4W|r&7^w>_9tkFr-NEVVU)^@s zO-hrxV{^h_-iu9KG5&MRBReNIIds|>rcE%~tE%^B1GA9D*Ey1+%Van4u zW{J`ptA@=BN-s@WG9^fUhJ(Pr2EX2-bs8%?BV4DbwKDF>)@XJ0^onK@mK8|SbFZBn zsAS#Ky<`%@!p{t$Ssg<5-}+ZCn!&wdQTyUc|LqP787er;Qk!{x@{VshfOw>(dKvOzKM zjlzYWp?lSQ`<7ny$n0(84&ZE7y3_hVzwKbByv6HCfx!807jBNZu=YYhYwtNY1QwG)>kMF#hJDttXYf<3((>vmAoVb-G8pSLML%J*c7#Ix> zsH{2I{X>eS@6ZATkLZAVf1kFn@@E~CjC;89+rB)B#)JmF@}13|0nOsyO+7M&zjxoB zmCr1wz|y<8=CQ%M>q0>n-g*Zub?7N@2^YI?P;S*~sqboQ|JSfuTyE3+;GHewynIH2 zvur{luiq0fW?qRSW;<(ktoi$R$}ta?MhhEhyC@cWgPVuFWw~uKS(5TiYdg7BHu^S4 zROb6IxQLdlY~*lhl8*m-H?EwkT{d2Ho!Cyr@Tdjtp4vb1PHkd-kx<;o(NUtXbZd#8 zA_F6(m%6BkSLyBx2TIdQwm0nRSZ=YKp>wI&?&?)EE>kf@Bj8n|VES*x0;yV)9qW^asF?LLSDCc!k zG)jV@nvLmo*Pf%ydIbud8-MpFFJR*HNjM~X!{>#&l(OWR6|9EOoMJwj3N>-O)Svb5 zW21DcOK&6(Yx0v5pL@BP#bY<0o~tgjV5jKbr}yTbsGG{o*tp>79^)7D+2a`6gWo(_ zk@xJyvFF!joLr`sqfoN&mSId=eZm5LkyEE?G#DDi8yqLDyrF;nX6}R|ncsJ;lV(#p zQM7-RKcAv`gw12o4@{a2Okzprt;-GLJu*d-82J*;-##nzYeCF{JNyL)_znbcgiA0> zeE9o-dw$=fEyo4Lb1vk@2OU`Eem=oY?nU&@?py`~pF^Ta+i!o6*89`7zQ)~Z?(e(qC+h?s#(z8FqukKQ;tzPn&UW1V)A7~AtYUJ0(1 z2e|()D7aAE__N$XFT*{~C6d2^@&5!S=LVrA!VSz8P4|>)ceXRw2e2*Nz^$Whw=E=N zO1aQ)(L%lt{Hha#jte)LJ!m#aEZFJJl<2(Y~rpW<~&;vVfQP%!yK-IZ`ht zn(a)~|DWV5enH$w(DX-0v54WMCBfC%SCsceh-~`c$tvI)*f`m0=j6LWQ`0UoSv{Ei z%(Rz@GgA=Mi%r*^A$Yiim2H7{^}@+nO7e;mnKTWUb26Dhy*q*F&JQLto`{k(oMgEn zXu5Eonc%c_KjLFAG8r#mZjqc`$SJ5O(a^PW#ubZ>D-n}a4WzbSkgq*y#I%9o&Lt)@ z2bb=fGwn5}I9PW7Z}4#uC_nv~$txszt_pWf0Yl)H$-yOV3x0-~I(lyJ=>5I1!$*SS z{ue261LhLT*_$(kHCQq`1i9mG2F^IZyoAj-OmohHNDf;=u9H!c*YE;NY}NKX}< zeZg{$`$XHQ|Ee>uENGY5XtZ`ELwmXZea$%$h1N@dx_h}~if;_w!)Yb%FtzmNyo)!* zmIzxg2{P`iPI4j-mPLk97lk*)^C62vhS(uP6(IFrwnqHF_#G^H3p5qkVgt=zU zWos%K*543ynX>S~PFt;n;K@4`A4CW|J~5l)gTbcEMO$7-e%xteJ7E@=^THVd%x5Kg zO>WJfRXAHtVZoUNQo_3my${b_w0VK!tjMhwWwTip3T4$ui!Vx_G+*`ClHN!~nO6&i zcLkSSm_2FB{Fqw{zFjnXa&l3B3g?-b3yzm8i`c5VG}6!V6tBv*rU$7DfBu|Pq}98| zUBD%4iAR^r;VJVr>{u!#wZh`T#|5#T3n~tCmmOd*)Dm^jTGEpx?0M0@r6IU&*PLBf z#Q#?;npq{RdQ(_mf%96Zj5o8@h96l>k*mTSr$n#hSl7Vae_+nOmyBIft2bqd)IIT2 z`M~s}gF!iHncpj~{ZS$g2J(UiwNI~!TL~=Rw`+~N;|)1ua1%M!WvgYk)b zor=}sj9+V86dT%JGMCI;6W+P*;m#QsIM?SKT<|4o{oBg*KdjdO+O>Ykt@U9C*E9T{ z_upy*WA{q7>J9g1ZD6^*lxMdX_wNnifs2J+&wn1ZQ6PJ|gto+~T^nVz6HX&{`erbc zFg{~EiPGug5XN-}R-+q_6z5NHrw@Jymis?$P2pu{XInt;z?y07&b9O>XjLfa4y>xe z6_;oEK<~inRB5)Wt%BTv_34gR82ApXC{-sG?VH=Pz;|G&-mVY)$C=6fQTNWS24-%# zJsWhVne~})a!sDD@4UaB(|eweWv+H-=N909~Clf+l3z=2U*t7fo=>5{~Zm%6hp}HL&aDvN>h1UM^qIruAyY zl4)75R<2mK>eZ?>+g`m|z2Vq@t=DU|T+4dBcE__-uh;GQ_UiTe18mxFHXISlezWm} z+Uhr(&X~P^v-yIX_S-F2!m{6Py^*&1?Y28*uitKe(5C%v$CGKaew))+!H``vn z+x_8~_WM0wu4TX9`{UW__xt{Qd;NYt1G~hP*>7vMC$5ir@uXv2YzOe`Wcx@m{C z1PfoB2#VHX;g&J~;Hq;&rMSo7kW4anZ7Ed+JkMSt)dc_vuOSM^?O$(lws z@h@wNULNB1`oq53Il0H+9y=UHqmnw7E+@?_{ROLbKoWHw;8;p8&# zlKSny&G4Z;caDA|r_3?K0>LiRJr5e?6z1}aII$?)X{eJ;zWMk6ECF_}D~Fn|Y&d2( zZ3dTx&H7Ypn}stuW-u`C6KH!S+-5ku%Bb=6>ql$`&#he^z2}*d@x*Aw#}hj%KZ#%Z;LIp8!P)0skoVp>PxU9O z?@m6jh|ju!;fB%#+qanxQ`giymAcL0nS1Dicn(Jcvk>Q&Y(LG}x4$gm>3#UW%cEXN+cRTFzTmP)(E ztM|J1C@=_oaFA7$3S?MX(5n08sYkNL&NQ>&CB|Y?+s`AbY?8R+EO40(ZaKSDto^-j1M|s|rDQ}u2duGdA z(Gj|{K>v+d(cQ!u6%sXD3d*Ek-Q_L5VdAnts$uqru9rz+%KIm<9XlJ31YKybU}2U%2yYUl9?+_<(;t|m$P#O^}Z3#S8C)ahI}5|OlI|E_yt z5;M=wR6BF9!z|e=!S~2l(=FN(R%e2jFBFTh}+4!-Xt8$eb0eAK;HSm&pRA<^>+27 zm^44+D$I)bzAWLxE*V|t)i+rmC2&WS{n=))K}3n{nwy!b**KJ8l1N(fRq&q0W%UYt}B7q)*+q&kH@i zAnMD$ZQlA_yLU}G%5?ZRt0kMX&Q9~`u~J&i?5BU&ePa!rB6Hnx`3VD=PZfLqGw%(O zaPaEXVcDJbPpkf01ox$YXj-U$74o$J1TLgVMT!uAGRz4ZTAtv|4*Nw0(X&NRV- zb@P6F5fWt6_;Y|WhGFjdi_fg}{v>I~7+yAHbm7nRhQg8Xr zd@!GfXG4RN!Q_pt&vGQ^%{Xz*TJ=xxMX^|M7x545rRL@-?t!6Ysgc`Kk1r57Z_aai zD}x9FTeMj|n_$)d1LYeOSida`;z^ce&=4(fH{>-aKk~rB;%G?DvoryQ^rAH059tE? zFVy`nNN3!@Ah>~Liv#bThDMf!jZBI>9UqwQO=rqs4^ciLlB#B9>%cj`ygZ^LqjOtE z@3#!L#<=hU45x1?CWX-DIs0CtV1hI-0P-YZ11gN^61^X7=8 z=DB8RxcXc#V_W&Hf%Rbs(}5W811ua57^E9=4;t_Wx3@9>-(G%rLpGO#k1C65VTFiq zM4sgG3QmjQi6^paZZPZ@%V9nk86LpE@qvN=LzD6qh8Bh__2(Un)C6kMIajtb$^~0Z ztLSu9OcoPh`9F>4*o97a)7-0NSvR-kiXE%1GL8^0VC;HfVLYR8b3|9C0n@T?{MU|j zdper>Ok+Fxz^VIs#D$R3cWTuizgdWV<3CoA@MsC6^n{v%#XVexsU|=8j~{50RuITP z(d%w#EOQ_we?v#bjfm>>0*-cjkLFgkK=Ty=>UZAd~^L^z~nb z$h{Y48xQydX=LqZC{l7SD!kmmTgfB-)G;!-{BlQq)pCLT;x$tLKky$u9wfh0$nt`r zpaDm}TTiQ-fc5p_qT-3KfAE(U2OF;xT&m97xPd`p!en^?SKFJynok%7KQLt%a78ya zxVH-UN_zWq)-nlNmKL{Z9*p$+!Z0=5KXRq;Ni{2Z2S)1+Y;_G>I}UKGPixaPOp+*! zm9=27JXvL9IbE&MLfe^9#uV3x6W|;oPWtO!f%krOw%};0W zGt6XDU~ORF7PFkqlGZQLIa7FHZ9+xQ(#bOp{1kLbVAgDyCAWCiYELHp{|8t~8@P^L zNZ!~H(=XAoZRfnJrLhYXSe3u<>rI|(ov2}#zRHC9dkF?fMlh5ta_SOJ*|_NE&ACT77q9*Sn&d81@4l+B^ukR6^=-=* zoAVT2ZIjy89l1+rp`yCogGKtk7_1FAm)rRrdV+h%c<9bi5qYPSBr zX=JgK@Roy1?{v;G*u^qAU|E3HT#i*yO;OElUEB+Haj#3@TsQ$V*_^U~HB^CBxgnKp z!;0js=|#U*s5Q!Ib+OnLERlC+^cLW%-L*1c`r-}6MXjf}LE|1DI2s?Y=LE2=wqp9S z9W-{qwIJgWOZuu8wTW!)TUH5e(-LV*VqUbEQE&s>+Q)TuUbEAxV)r+2PYYm=IdrZzW>aFiS;&^Uj0mH^L|LHO4j`U}oRI z(ABnf^@^^)yKK+@=s9}CXi{nA4D$`@fg6+!jTc=`IkO;3W@A+7hgB>L>5{u`?`+=K zXkw`OzhJYj0khcy=4ou36ty?0I&M;Sw26^qnfqb2xFOFr6^2Jo*2})$$g~tZnh~&- zXY-}hQZ;t%Etzh-m+~ZrNKC0aB zvJk$^5N0sxMOH??0CTriwbg~qk=k4SxNcYez4mvQiQWT_%L}FmU2NiduwH;`dz<&B zj@N6iZk*Z}#;v7YwXz{&Z>xQM(a!0!cb0fbA3Dh>_n2u?0`JKL!Sezf>hyT>0I5@7&&dPg_JvS%6o7t=O!u|G2>Z1`g$d z4$iP$Z?w0(JFQ_NuN~P@7B?+2*ekUrsptR$pO^nB?L)=hhYSig$O$u6PuTQLIxfO@^i9t*TDBcpF21XijWK!YUcWuN z17cHkqI4)${-#Oa!{b-BP0oTjSiv*G;x(KY^df@iuBMxtlg(V)2 znVIVy5+8LUIN{ogWv7qFY%+}bag$~40k^2u*wO+b1JKldClpm^&c|cbY*ZHII`)~o;7R4qF*xVE#SCv zpk_w^d!wm)i|AqFIj55t_sKgm6*6#?DzJ7wt8J4xbwVev>kZ>-%f+JImQ{b&UiA@| z`fT|B!usmVD-_>U-Jc`2EYgH&0?-t3-72EOW zqEzh}C0%iq*h^}*hcs+2ZQgZBN>Bi?RJxC$it#ez7NQ12l3kVEY`SC+7lI3^o~T!h z-!{i{Gh{Gij->FC^E0er7lMn_YfbIkvJ!kD_|zR+vQDgoTnN7O>Z;hoU9#TW)*M(L ze-?ZpxZjqryPylf-?{E6eEaI|>FauN8)})ky&V+z2 z1b-j2Zx-l6a30=fIp3<1$Cp+Fd%x=p+xq%?XC!l*@9uB+R@>#izW4TeLh8K(&6CgS z?lBQmI{IA5|J~0Y`!)XeDX07G{T1*e;-14L6%C$}*AEWg{@?S6Lw5h?=To-|p5M3E z6Fj`)zJDKRc%`QN{Qmt%Ojzyhv_Y@7EFPYP)cBCaRV^`+#B~8y_h#w3Qlx1fTSg!Q?jhEA%1x*|>1s@u@ z%sC8SY`)Xy!Xls*@w<`z$)wp${EN$0>$y1uSg&IjiwIb^vuRy+zUzai=sa%SGuiKW z&fL@f;B4OUx{*z8#Nqj?doLj=u>y!7ni5kCEp^Kku#kpVTEBz8Lu4@+-R-i{dG>lRV64 z?jGj2yji>4i)-ZY%3aIl#nM*F59FspCe?6S)heUNlOn zFxuz%G)viBmeyYq*v{^dU%K{oeD5!FW(GgMhMSkApRIB*+UV*AVJBRjYA{i@7!4)&yft84u4!TQ5LU~}a2#tgG{ujM-zW+TuToFN|%woSI!W zFHy7Ae7fXghaksW`I9b(yc468E-qcb*wXO)jnJaY%b1*{$^;si<;1Qm6biL5vCaz0 z)N)v6^>sI1c z8CtDz+%Zw%yTjPmo85k`BL65{-HTa}$6^`VrJv%5qu4hxNU+@faq7mgw0wy=g9dwh zh6|^n%)BzU-jp}n9no1KmcL2Cnc+{Q)x!U?zHK>qQi46?^es!jCtD8~q>5_1+OKe9 z+lC#YeR-9qufB=~EA}^fg5fi-Ai#2)5!99&j!fr}E><+OIty5r@bW%LEMzdwcF_*Ne z&D@Xf3N*4_n;e~Q-!(BYp@|)|enMnJTXaXD;w6t3%Zo1`?zs|S&MF??3rfUA5Su$rX{AaTL(Q>Y@@M)*bVLtYV1K&*+ zG;-=Fie1~W!I2||?a{R`lbp7*+b^Bk!gl1K*bRZ?xr&n#&2na*uldHnsgcOLRyIXK z$aG7g;M|Ps0wpn4$D&NCW7r>^JIy-(0h@ly$IMQl1&efZiyXXtrIhX@w8_tC5O!hg z&6G&qC$71k`M~ot##fr8^yEskRuyFPKbdu9k6Q2S^T%8QysEBBbiOq-t~6M!`dFOv zA*1Iu z`Esy``$%7j;@6cE6D63%=5eU-_s?AN6?Mk}{Lwg7VsR(~XPHn8e)U{lTQW?ptn4SxV2vxDJDJe{8d}vk%(#`|MkB zt;ymDQ_nGl$DY=c%#E5v4v4U|im+{9JnG5wDlq=cmD69@Jhtyxsad$rp(&z+)q7FK6d?W&uxXKjh{O6_bTbfbELO& zGxDs_f3mx5Pr@SBH=HI11&_?w{8Zn5V*Cdt@f{p$PS3I{e%toPG+Fn&;JjRL(RKsp zl!Ug8Th|58neoZ3-8Q+u$Kwc}$a)LuhI!9-zdwEcz9?hI^PY6e-sk`I zdl;*4%kF>hO6&j=2LlJsIlKFZCb-JR75pwvH2=N0++ydx4_tFoZU1ax$tnt9Q4V0$ zc~;8dn8soj$n_xOOhMlJ>ro=lxS}@Xd`XJ_Aui!?fGK@3W4b}fM6)zs)~xUZhUjGs z`V1V4O6r&oa!+gESXaQa&5en70oy?b-WO#8Kiv|iDX`9MuU;^{u||M4 za;L$fz_g% z@&5w*O)tb;GISlyOBP*;U`pi4`Ow49l6`wZDZ3(%gEN!f0sTw|?!t&-nT@9XADHF7 z@CzFEUU?C>TD7pwRAAYY9{vfQQXkk4J+EO|Xui9EYmx$ITuUiOMaiKD?A#ytFYK`R zzrg3q3ek?M3==o-o|w?j{EUm^2~)fS=gM$%F2UlH7kF$Zmnbo2r8F>fnG4JboS3{Z zhPT1kf+Lpgf1tzZ53ZLLytoa6xR*|1VdRlk_;J=Gx)?is`^7$!M zd>Gj0C~)r)i0OPewYziH`R!9zdkVItbNV)(mV74O}}4X3V@E zZml8UHeK+Pn!uE)^I{fi+9fc*{mK8dseK6tBUb{$?wxbLo231zOcj_a=-9&XthJrl zYe8b-g14P!S8vYbGnmnuFr$NW-f_)&e>*GB3q)}lge?`FEH_J3K~anS)x6Bdj6A1i z@_kqkWWc%ZLQ=cOoK+_mxk(8gn?A>WLr`W(;QqkHL4l$ZlvwN(<|3cs)s{vjicVl!WW_b3=GaUZHtq#0njgNL-)*`q z*X!jPkUF^#P8^w!fE!KRXzfBUfYoYDM zjDE{0b-yAd)0VYsaxeJ6(HOv<62RJ<#o(xx67!59_E~Dc36s#Je$%Q})*CLLmBd_H zwY-pln>TccYFcoir~A6;Tyq|bP&Io}G*VJ36~IuU>e4wcAEX zyG9nf4J)54Via`Xc(;Ah{{!6p0W3TMDO+!)@)xY%jlSkAvoj7LqAA8M_0aa?C7 zIQQ`IA5K1g=9j^4^3y@j!R ztFz;V2Tb1eW>Y0T@=OSA=ih9R*1he?s%`sziL1Js>N#-KXe8E2EdF1ztzx%imG#nk z$Jsu{jOWsL-J=BCzqGez?`W@<>g*QH*jUT1JoUKRoD;{n%LF3NJBLlH-Z^9T&RN-_ zvuVj3)qF#`I8sh>-*}5vd}ZYQuNW^sCFeaK2RFA;S1Xlg}o=avQibI>L(|JcORYpaPI@{!%j9li@bM zOM4_80+x$xU@3UOo|-QWt0Sa?OlNIfeSLNG&N^A| zu#AX}sh3x^R&INKYkNWXwx^j!>+bFre}3u6>Fw*C_qzY(lIz)^`|xmwuaw`Jhz~c9 zP52wu>m!+ea^_Uy&%A4PZhqe7;#4me8+M{sQY+*FgAxnp%j-d%cLY8z-1b()yyd{X zxgi|9x5acSemqF5;F4ckseNA4#q}*Gug#VZ7aS@+iWpDe7Ts&}nU_z-?#2HbpPo;i zr*OGj{J#NnNA{d$nP+B9j4uCv%qe2S{or%)cK`pyd~U6JwK4s^x66|SOu5^xnjLQZ zF3Wa=CF0AY^Q{tb9{$SW84eE$%v6>O2|8R*aH=>`YcYpkP)_V9ul$}#4}1RY-PF=9 zUpHa4$1>dr>BfVR<+9znTw<*3O&6RW_k4+Y+#xDpJIe&Ag^3 zb^ZsR;7hLh@SwW$kf+m*KNu<|uJCbRpk{-F~=Y>dTSv-5Xma$d}6yQ5Ql#`s;_3_g=vOv;-Kj;lQ8 z6h8foBP&B?+9`zzmrOUhFIca(_=ADca~&gT77KxQJ4BAVy3CR+>sdHkvEOHt;dYNh zEzANT4hgv{I}a!n#?~!xG2zLiEH^E)o2l~L z+zLK92XY$!ulg^3M0(;4rn5#j+I-D#9&R|~%usx;q2*R~_0|;}YY)^W+TD(@GP`?w zTF)t2Zwm)U7WuN5jjPtU{mMF&m|tgMaLLAq>5ANq4?p52_M0ZQ7Ce8v?CkpIHfJu) zeAjUB-ldhlI1O8x=azg(@ow&5Tr|JVI&Eh)D@(5KpNV{vXZnAx`EYph93Gv?cLdwT z;~GA;YaHCMOYikH?~W=X{{4z;0;;8`gqov|4TOQ6>&|HK0V{uK>;(n1Rj>Er>Cd!h?Y6> zT+%JV*z{NA_-ZIUKbe$M%h)5L^tjbQLuQ<%q!s{-paVQwdZ4BO0qMfh=Qzq zL}71^PnWd)1tx|+iPE|%vt>V4xNn}S$Y7W4DDaQtgag-7OBszPasr;mA6T|b^z(@k zRM4F3X?JXr^T8Bup#|(Y5{oCV59Sd1&*&xX#VoAcFk@|%hiFLLr4ac9RTH5w_l_$< zRhO(Am<uaEh}!I?w*&S(D2N+;!_N zD%&ic3Y3R^()@G?&@ufhEJVi0ZS`GID zI|MRW9`zi3ct0tuYw|R+2TKimRXy4iCq!yJ5kI`bnc)YAUt!(UEBrZagjW+je+0|JSYs)2bYpU0PIq*T34pq@ds> zvYPnfgwKG@eTIjZ0UMgiP zd*79;&Yti(?fdM*wX4bI6PNmx&eG@z6ue@Sbv@%`gI#vDalEiJ@ zt;TEA_Z)FOb~C4R!sO*gl+VT5yKwyV3go_L5ZB9DedF(6R{a9S>jq+`=R8VTWdtsy z%XZ(m$)%ZHxGXl;@AifpLXyW4k^?w$b$2Or`pHPx?0F|JPx3BXVRA*0RQtzUZ>}c& zVb`zNsHfk* zIGSW=m?mWMfbZAZ%3SF%cIF9ItX2inj(dJ_d-Ou#g(|zM{*wd-7K;arK~cL*x7~`f zG z-tPVX@CK8^Csyu)18hnQm;-;v-nY#DlE!_=AfkcsxZIES9Rl_OeR(UZCq}&yJeqOo z;OgZQnm4c=<}Qk64tDU8T99UNXoakeF1=F{jPN^1VibB^Wy*8{qzea>X;m2Y1 zj{i4LI8-{9YB9~cwmwsGk#Sp&=<{Tuj<*8mFDg_$;NR(9;lk(@Xe7Rzh4%u>tZ%80 zo^zEZuu2=q8YLIpHWE4%z|Li${$D|^eS7w^D-7uhB|IfQ%!)kK-+ZrZWIyA;+mkAA zD1qk%GY8A$Y8DNlbpdP~0Rj`0Qy*MqP~XDyYkI+>z;moX zQ|C&*3T8(7cIq}6zRK|%YI~LHDr0w z=Bassq0pcy@~8*rMay%GTi#ChT^%lX=>tETfxt%dW-d1tV}k-)2hL-Yn&&SQNRTi~ zeo^ygd6@YBgDG4F0;&PxyT8dE6=bw^;8@qd9d*rRlbYZkQ|~{bf;$}8SPTSGlNy%= z$%uoyy>$&-yAL?ct7zv>EcUMGkYVKV|G_W2AUSx3l2b_ysLQ>9ZSn&y?r^iM7D2l_ z1i~`}qo1bi^KcD&l4GaPBP$do@PL6kfgvb>eU3r*KGytyE#0fWcSF}vt|Y3ofiyTAG+!oxaV|)Jp1AKYDVAr9fC5?>fd+dc_^@$U0~95P>@aPKeB>> z`v6P91dbr}@c%1HUuaAa3KKlMq5Sa2KHKZb{mm?P8z%h!pm^J(N96<4!xNl44sbJU ztxVi9Q6{sS|Nn6p@0O5$0p`4LuX8K~sy{6vjQXRC7`1rB->-c{g0WKJNB=Uh~mG{Yt0a@JHuu1iI^};fvBwo zD;qdF6hJ*<`+^egf{3j_0cY6?TmvUXBrzLbn6PHYBmoA-Fb0kd1v)_|JH*_BtybpV zZsT6rz_l=dqcngmRDfBzfT8Z^^!BSW3Z5%|ZV8lg7j1jV+__Row4gG(fctg$%oK_I z1>d+gP2lPm;Fzz;s@zbr>?K10b9sSyRGU-9{^PNdTeEW=r>INLKI&M(A254T=j@f{ zf_oA;O9NOJd(PqbUofjzQZ;DNoR;<}JD)1PG1N(5}5aC4YqwqV9|SH|)UJjWc$ zi`qED3mED-O&7GzJE5$rYrt%^fcfEEnAaEDKo7_dxS< z(IVShi?@7Vppee!tH9-bOi(ne?h@m&M6G3)+Xagmm8aimGqOrt5WrIHQqlBtS-#YA zmWyIDR9tKumW3W|5jg0}B+!`qKWb8))Ut*ufoR9&M>n#anZOfeme}!N@{(tB`cEyI z7$xBr*z6aukVoC<@6_ehs~AI7md?KwyD&q6B zYZS)tK44kG8gct(sOT|^gqe%>TV)9Y*H4TDmg#w$y z7=qU?6WC*=Ui)fo72`Ug#OfmtnXX#dJ-ape*W{pAyMo_H2_6?^Of2A98rts1&K0`B zz3tMf?_3!_y#)7tRMuO-!OpyaHPNi7!0m-p*#21?j=9RDu?BgtZe&u-H$1TB8`m0% zXkk4s85IZ4M~|%pZ|hdyTEQQ+$#G)uiBh($|39oh$rZ54U}Mka73+S@G2)hQJfUi( z!0DJ8qVU?6{o7_OsV!E54kwnf{VrL1Ln?qp+y9;AQa^5y1`P-OhGlymSP4Zh7CpVi zZr4^TM&%=dj4w)btc24H7sM)Ci)U1OI!iM;Uf{HdHq(1u&AN1JskDe?!ct`mbNR@K z;!lk8w89!^2jo9tRQbR@@g(<31$O0t^@%5U^v>RnU6B@7n2@ zSpCY8QNV%e_{v#zEIU?I`wP8d6kjmMeAdoDv)$jnNFP-cIQw$N>r=Zu8E0!wU=p4o z>s-0($ZC;5u2pAOiwL}0b3tlv+Q;SBc8k=_+I!1;)1BEO1scEhUgF;S$a>$I=zY(+ z*T3N2cX;={ySsP4`@N4tdcQy8mM`6+ytDQqcb@$jW-+d0sKMwwS4`j#Y=fVmE#7)( zfnhRe%e(<(c|ey_M#ql>o0jq_swbbC<5|3Lf{d0$&4&Yn0SCi;(@`QLb3RQhrQ_+6FX}UI2Of!VC6NvB2#=uuYhL*qrcUi_W9wLw=x`% z|Hr8Dpka^XW*?1&Js<8SIS4Ml;JobN(JK+JHXi3OnHia}&}5zr!$DTL8xJ0~2cJ9^ z#H{kF?9pVFxEGuW557)0#A75?65QPVRpf~Dlp9TFO|D2RzHPu{mwb|gh2xsyq>{#^ z!Aw;NpYKohPuqUiXkLTkq4I?*8CZnm_N6|~db#%cy&0*mw%zW`I(A_hd;X!9Qw4O+ ztYkMyd-U>U-mwRV7BO>tV!6U=$G~`mS4-nsDz~o7e~B|KJLkUCG`OU2sDUZ3Eu}?p znw;u$cFsKqeU@*xTY1-TozJC5%%T58#EVw&$)XJ{5j;t@MPNqW}z4JR> z)Yb#s22*aS7JDoD{P8@v*Sv1R<3*QMF27$a%zT(zlF{OUBlkDeH6ISC`)<20zHv(A zragxwHlLniy~BWcjV?=JTg$A-7w^w9fezHx{BP`hTJJyCW>0gAJ+5buDfFs0vg$GW z>dtMErxyo@{PMH%m}K>OkMi0tqKr8KjHfr9pO^Pmm{Bo|d&--AzZ~{5+wf?( zvNSld=!)dqd=g=t=;YsJ5pVhBqPlb@!(Jmh>+dJmPjO;y>G0p-`1JA2*X#C5`CI?y z(VWS|(6Zs&XTG5Q!k)?kj~`9=b?vx)$B%p$raAMSPMHf_7k!iPYjHGl?xe~8-!e+A zn*4yJ(tJYV38o4y}9TZPN3=bd^q?Vy-Z3x{k@L+<~y z3g<2bUd6))T9({PTf%B~uHBgHkz|hJk=aw9cnTQaVU%fL^vdjSRI2RQ)nUNQw@07H zbaCRzxWhY{YTk7(ZDC6kJcu794QrOxO;HU3!@$z7Vg}J7Bv>Z zHjN8{o}q^q-(!2eax%|j@jVAv_5LvnCU0nDIHWA6DBLzt!+}W_v@v+<#WqW)_MWsH z2RY5o<&#f55=_x>l60Eb6R)Gveo$IYX1<4@(h^6>KOfqSroZGb;b7wUQJKhm!Gkv{ zX`;$y<-?3D3m916EZ|#b(IzigwC~H;3rc$vmRZeS$*y1_WOk{>*NX~e` z_^acHu%ggmCv{gBug}LXbuc{SeHfu;t6<2YwZu{Sj7}?8ftPs1rWB@6bKI^mwE4b@ z>|Y@#pkzFuYQk^PD>1&Q9!{(e`%<%%dESLEYRxU9|LIYLT&F&Z(q?&xu{! z8XI~2dL5*tB?ge*Q6)nhZ|fatHfGtJ2)3}eS8wo z%_3wF)WW4db(PQQz{`?9zG;Zm21H%#n4KJPQRVi{*6NBW(oGy43WqC>a4>O-@*LZ! z6u9G{lk}-G*)@ub+IB_eShQyQm>&!nsqmaYHb7_GKz$`+v= zOVq432A;6uvDax}axoP$)D>b4USuTyr(u)PC5IK>vda%C9dqkk`|`4)cvxmZ#XB zAj_{qXV3iJ-Ju<;sWY`>J8NOYmW=LBzN$Q8Y(2VY;>jPk4*vMoo>)Y&*B-S#7DVSumklY!$<~WF3~t`=+$XFe%8ZR~(Y! zWB)E!$kCqG3E!}Jz);yZ<{;+J9p-fg$z$VbtYK8|0(oo5nosPG&VDZm{XTsBz7G5dHYoB zhLuZMEUgOko*p-!(CD{nMaG=Amz+gC=PC|z6)rgPKewnkcVqvO`%wi9f&Y8TEMBJ1 zVi$kt(5JZW{R%hsE)9citd~qPro6R!_qAATqU;6*R{n;}uNP}x6|8e*q3IB>|CD~L%sFcm)FT(?2;@1=~TVS<7k>8gR%b^jljeLZSXprmdi$S48s z8y5s{tZ3lg!@zSrtxjxXM=?he`xDESg?8`Ub;URM^DSWDNMHzJU~kzW$@g4e$+2rv zn$WiAZWDjx$UCvvEnxCr$SAeJU*JR6%pIK@5_tAqaqrsEZCugbFP4}#)hS?c+r<)Q z%?qlEr9J!~7}iU4Cj_uB4Cv_DR`2c6n;_99SeRSa;(6==SLy?|%!AHLSkzmTSj-HV zV=oDdZtxeG(4#-0^VtlpJs)~rbu|B8mcN}z@PkDEeuIgd7`QqD*rN=XxEsV=n5<^C zsr>F>alX)h<&f}w55|W-y0{C#-SrLJJo_N9F6TtECN;O}ll0>2B z9tG|d7bX`hU=0$OlG@4e^GW$bjS0tQOxI3k{`PQMZHN43XAQdoX8)feYdaVPHn44X zsBoXi)#$)xxS^=;B}3=rX%j8w6+%}4>OYm8OsBbj{YyJ>Oa7IXUVkl zo%-5~WiCg~y;eE*z>L`+GFj$WGTShg>ML-HGR^4CVCQM5_ID4FIv@m^dA>03_RIyJ zB~61jFZiO#GXEw+Rzb*-%DTo6^X0eCyS!7BbJi5TUlU(_S~$f*?BQgdX)5tM%;n`5 zFuz;5K)!13;>QajW`qe_m8OQWd|Tll_iK@X)Z)*UI&v47r)-!n^&_KwYLK*o$NQ6u z^=~=-dd!^kuv8>!iP%S;Pg9MoPA!Sza^39QDR_bTmt|OpmZ0U7#itu*MrlRciI|>J z7Kjr!%$m|6P`Ttqv+eeo%jCISxeiWA{K)U*wPeu`?`ZiWNw z?eNMLu8-E1QYIN)E4-Jj;4)m4kYzlfOJM&4cAgJb8-rI)lbS!{mVICq+tvi$LaSvm z$C+DKF}6po`dP8+si2sn)slSil`9Xh9b`AZ>9P7o=4z3HD;9rW(KJ(Fmr$#h*D4;b zHS?wk%Y9gy7&ZA?$KpLotG#b6zA#IECD-z~Qi<-T%C#>~Vf^OJ{2>OM0HYfU8r>WIn@hDPygLg2Dce z#6s3Tc0KoN8h5p3;>LBms?r6gaitjOd8m1PsNA@raQ&*T!iXi>9NF=Ayf*bKZulkX z#C)kFKV+lWp4XdVFK$?6qJ0cP%=-W6A27%c^&+=uTYqd*{|$y9|<79TY-Z z@9w}biE$l6B}Rv~V*;^F7rJm8?BMN)Xd6lSvt*TmC3@xl1eUF zqM2J(U0>x8Ve<9DqMYs(7UlOUeugeMEUmSv%jNaM!#t~UKQCJ%_~~$q?v$*fK~Ihz zWabLAUt!R-X_bIfQU0SAuX4BKy)z8C0tGi6oECn2g{t>9ZNbUBQWsVomAYgA-xJd``PC$Xx>`ua+CUbTG|n~wHG zuC?GZc<_JAp51>A-7_!kxHTTUG)>nniiES=?%JEwB))dOeYTh_-%Zq-2y z)}Y`y2JiN&^D419Oo-~U{?z5o|;w!D@IC|(_ zk-D{X-{FR!Bm2d-e9%4kP%1`LaL&>T4l+jq9)CD|AZ`|q*1J51={botP7gAo>wJt2 z6h9|CwpUvmv*DDNprP|2-Z_cfrfc|opUggPXnayCAtJF=yigeU;cX3J$Vb?&B@LWAyRq zC-JiU73&=jgSFE-Zer<22$Ys7U-mm)I8R5J6415#5D!f|By?#>v=DMamZ*KTqsd=av z&bXI-8sqyNUkx3-#8mIBS!LsVKiZZ@%}{`W@u&Ly{(WAr+znR#-n`l4&llBR_nrfc z-xrI1{dU}5vr@t0HbcU977K@jzsiAp4n0iG#~u16tY+oC!EDxZ(3U$ZrGZtFZH>{5 zwSV@mZI*Go!7e1gp0?sutwiU1$BK=+c>^30o>eRI{5SnHmx&<2b7 zdkE@O9m_kG@z||RaYEvciTyl3g_v)Y?b5s?sQe<+LD=fxF@|4H`s;X76okU3I~9GH zAofvkLZA5(&QmE8`yaG!Wsr2U6j@MyZ<4Z_K2yuiEe*AEO%{4FXm-1AILN;)Le#l! zE2fw{BTf3ixa z%xa2{6Efa@>P)iBBcqjq%Uh1$QP$w7(wXyOitR}kj$Q!)TmBmj%UDkPym~fciuNK8 z_9-`x8QGbipTd#6n(v0gc7=mI#at@RES}MS-#lq9+qN`NzBem6GeDM~=a4Hu>tmhP zgL|EmQWa~@=FF-qi)W>a$Cme;~zzT({J zuGUv!%t%FX|3JW5am%^1|6(ixgVSG@9lAo!B((Z)0CQ!@|AF>-@ModLCU{^+Tz~giWtt zp?AxMAOGbA?zzg&nDl8O7!u*Jgjh}6l0iZ2d6w~bHcF6aB=YNM3GD^Vq>nf6is;-4eILJorLTr2L` zcnWarPU7WS;E)wmVAbo=$Pp57Y}(6(Jz-OlZ}cu;TrfZDXn)9ao-Gz8pMPZRPB|5| zxJD$I!9$?YVu933_QJIeAG_v@X_Z|m;b@=sS&&o3MUnT`jUvsE4LN^%Z{0M%=pg0y zC-+(FC83lROfnV|d4%Gs6*hUW&JI?*$LsQd=ZHq%q}N#j9E+3oo4?A}I=}X;^A6|J zw>S<9ELy-6l(SQO;s0&sQgi1{HgLIpVrQ|Ev_ydy`uyYNlRwDJ9HJ=FD$&>* zcWi_Ec^8Q}2~2r=v*NT@gPQ{Vil;VBoQHXaan zVE(N9`8C(_EtA+`?BEgzpQVa(!aI}>N+d00l9N&JOl%=Cqy8yS?gFOy!ahgx+9LZr>BcRw^K ze#n&Fz;)~Zx65O9J68K68NDxm1e*x?sb$y|PL8!GWRw7Hif5lw!0m8Y^#w;y{Fc5O z7T%Y{ZEXZyd>)5cI)avk>u+FAU|(32HJEs^fqPX@FL&b9^*7unY?-`c1NVvv9Hk3b4G%D!-NL}NfPte# z;$ugcv!vp}3TER1v699qxi1;GE=(#2;MkxrwTv@!(hm1XNv{PTIEozDf&yl=&zvDp zAhAnKNqS1es>RCchAegl%o&+evN|X6e_#-R4l{6U5Kv}cKGCHqrC?dwIsvY_0JcyA zCiVgb?hOnVjQv*6oRYoMB2zFbG9#kU*?RFgv4DOhb}=g+igHVljIF!?$9Io0|H@2Fy}g z3!H8)l>4=C(@i0(fJtJZi_R4Ah)W17E@owO2-A~NvTj`X$8+&r$)pH&OTR1@tDxC# zKN{b5W8=@O1Y0@Xl(pAqt}gFd&E#mn@tI%j!HTFLrz;xVITI|-F}fU+N;)x1 z;K3v2NrI;8w}KgV3Y`Bi@fypr>#J7YJXJoYaha_G=Q^zxZbP1R3s@a)n*GaM^YWMQ z-72=2FRMSS64`oEAtO69trR>DS47;P7D>=IumrD}Acc+%0T)$FrH?yRay4B%$} zG&Acsn^S1!zT)*4LN~GpPcnbV#3LQaXD#qpt0d`?lhW_`DznAcifD%YFW@pdypex~ z-^AsN!l!eLqc=VD;P@-HZowD+jaI9Tza~4bmVWZdVan!>$29{EbyYe_Zk~H%OQm6` zMIuuR1FzQa^#UGiS-Mvmt={@rNmX8e(fa|XrS;bT7dAak&O6?mS({+zNho z(R~3!rDV!_pX}{BH?7P3wXQ&IHHUyJYjkYO@7^yJ!r2E51h(lPlJXPE-lp_(M{Z*< z?*o>(8*JY*HafYk-fz5P&TPq>rNS=PW943M>TcS4Z^kaWh0EVmv2U2*vj0G_(2LEp zW^dinEvXhHE(adFoAZD@J6R$nab2JEp8F>v>XO>pC6n!cFS#&Vd_EIP`YT2+%Y_z+ zj%pFJ_ul^@q!KC1G*Q^9U{|U4zPO2TvJaWJ|7851AfBMLyZ7b3P{EG>517Aq@Bj5$ zBe82OV~$#T)B!f1jT~o`19u(hyL5nW&Vjem2X`AD6p1dwb^CZMQJmNcpGKBo=i0e&(PA!nrwJ)CGXpyK6%;0RsGQuC>ZWAkQt;!! z!e{OL#w|N!JXPAc1kLkT?O0g6{NiHv#uX0?HZKdFZCta$g)7j*XPL?TM^n7EuJ%^c zNvqrNV9J_nEBN<{u@sqR_;ROZFZ-}?+dJ18zP1?!MQJCw*+rD*_`aOl5j4~M{;N_) zCgxUd)ATi4yd@W1I%1_Hn7r+c$Q)S-h3vV}S2E7e@0`EQLbx+*g{i*W^(%opw;hu9 zHT{#=)_ZGX%E<)As7DVP6PC*d3Cy)ATFkXw?nKrLL3J_Xj2qK@nU_3hWaFPS^Y(u^ z|Kzl0we{Ont-pEC*l>Rxm*Gu?sMWof#Md(UzBM^9KjOyEvNMK5%K{u{3=Z%3ep`34fg=;kCdKK&&0LagQuT6MHnb=oWXa%ZeD~4FN0xuW z0)=L`CmAix{P$E6b*`M?I5WXHt)jUJ0~m9C2_yTgAfX z{6zoK561>(bESpJeKtXC3tP6ZX!1;SN&7L+aC^n3V|)r>1`!@?lE)@S_*s2)SKs5S zyr4Sn&`)kj#tAzY%uHW2b6NO~-mA?TcRqYlo72T-oM5!#&PvD0)mAAHJ{s3Vj>s`2 z9bRhCS@hpZMZag#O{TtyURIhxmMYJfRPRJ+WY3Y3Vt$o=G;qOHb~)Xr(@Ls0N<3J- z@sw4MPE^lN|B9Wjc4!AVFg$JKJiukGv)ql1y`%lB<;!*Kj(a|O8tmnLac}1wJ7z9^ z7KaUMz3#sHwbuLLB@suJgLz%+7rp<>)~)1iw_wfWf~!xC$h9OHpIyB{Pv*I@@|V|* zd<^V+9v@(_zwX3bos;}-C)3GaaYnm+9a5K0jqrCNQ;WqOJPiGwd zVZLwA2EhYtB6qq<9(COhje8tFN9gAhuE^is)e?E{J{qh94=!|^+qQjaa!D0)bcIu| z;hODwzdsf>Ejs#kXTM+7d(p2}VFEMMf^A$*oVMdpvtjuV%iUqmZ|i!gUx(BDTKxWi zZ}s-cCpqrP@7;aiv42Q`Z`XqNA6?&^_L^{$=fgc#53~KhVxJfZDz*IkmOk;H;7Wx{ z94(9@2D3kuo^B9xRABhGKyE>=OBoku45LPd1@|+qX3@rIE(QViG?mBVJZDZk6WO%F zZ7D~1juEprxg=^|J6z?I>Vt~;OHr#tJ0Ja9H#W~#EF(W?-M3$ zN%GE6XP5i4fNS1?Rs%7i9S23<70h{)5;W~n6K~OBiTW@1HKwLBuxK1$_NITW|-zxSjIfsAD(TnyhBdQ((fq?)XkJxuEK zZwfiZZ2QASBk|azw?`dPn4T{9n)K~Jy-NT?%Wh>srfUJsB05fq9j>j5JdaKL!^9`i z+sEg!a9*Rx#6Cq|Wl!%_g2!B6@Lz~<6V;3gjPOuoxPIk;LQ_>wJ;S83n?|={L{0`b z3M}lk%VP4qJpEi3&tcJmgeKub4xC8|%?^H7Q)lGNP*QxdVU_uUN$k^h@ti!mVbP%z z(k2y;S5-5fTfy>!ufl25<+iw~Ub-F4y5~*>WxjK9o}R5E+27b97~rtMQd7t7{qsh) zC0o`fm#p!A!lHcgkf+3+70y2HB~CSRX4-Nb%(^kD;r#zsr54A>I$Q7m-1vJ-*-YDo zK`d%pc#r*Ct2aBFUuRW-%+41L8@i{Y@_lRG^<|CvmIfESoBuv`CoW*(;S=!X;*hv& zGfP85utM2HE9CauEc3Rvj;$gJ6BJlIm+r~VNqao!1E;Pe^X{8xLHo%Q9(M*Q+78M_DA<^tlw14sK)E^|SQa7Zc~`C%sQ3owXTQ$~O2)mhPC(_EHaY zru}=H&aGcgpE&8WM_9q2Pt8%HC33Q1$alU;2NeIfH`;P-I`8W6zj0R88l6`S>Su(m zX=FSy@;<<%A^WE>?z-(ghnR^R_61DhJKj9gcWC5_iD(uUH+5vT=m?u$a$U64pkZp^ zqcGd(lqGHwFYPz|F$=lq!d@MrGt>9>`S=@&ENm}SB`gwq<5iCE@fbLW3I(T5wl&(OoDVS92A@-;3BbN!5i6GR<0!hr89F^rv->4wn%wc zu*NLtcqsWq^3HD=R<(JXJ&lv4HavPU!ENWAEw-I|{@QV@Sj@m#^5O9l_5a~+(jK}K zuU}fin%}{i8+*s!%FN3|YQ~n;e22I#Q;e7#t{;%hy7*|u(yfanU#_cR=9av)K}Io9 zz)5<_!T#n2&H@eMdPa4%y^ajg4Yo6s-JO+G8#>88Gi!DaHT0RacQ! z+x{dwpPNTt)xrryFAlN?o_J7P<8mkQQp`J6eWshG4xO{)Y84JU2x(a*%D&+-eiyLM zqukjhDMq*DrlkdoE!(61OTU{HuHR@{F}GsZ#*9*FCsylAN8h%yvTWI$sqo89o`Z*} z`jzWM-`5uldjvPXeQ@`|#P3c$4y>sY=E)t+V72no7pO96ViVPjcpTTyTN3p{;rNH< z|BN0EO}r5cgD5 zbuO)yYBNf*pK5%cTK;2sJ@Z8V2?i`74Qxyr0{;TI!~!+#H>tW+v~(231ShxYeQo)c z>d0}i=E`^eFAI3q2Jo>Y)*2@?2wl|9cjUM$Zq0Js{++8pqeayJ2bO(F{!Ej_Of{;w z9`djJ|2=1#VMUD#hh9l+lS_?gV_W)25A_G&=U*@NN3SJ-LN@T?4phx*)e# zNMg}um+#?4|0eMNoWXy+fKAI$Nw84TuhCbSosn+=1GKZvz`diOJL_2|Z%CiG+QjvT zxmPxDdG5KA9OaM9VRB3x8)YtDM07 zKY>9xfVK3(gxw9?ZQIjcFK*dL~G(yy98!qhG`p2r*WlEOYfWv8WNbmv96#}aATqPH~z^j zpgwcZgDC+w^@B7G8!V?)6$)z_Fk2l^IJqP;Gl`{h=M3WuOz#(ovt;(N?_@4$;5x1_ zB{nc&!2!0998(oCCyS^@_+4VMTEN`?xxeM43-e^S}c|1OikrA(n7&S^<28TmJ`Z9gE#_>05Pz)4{dqrAf+ zu2TzmgoG|}F4UP-ZgXkTmX$)cG$%_x;J7lO@bEF)ecu=^vCZYPns0C_;Ofmq|6ed` zJ`j2NlykLl)FuZuvWg<)eM=VWwwa80& zNu-sSz5-WX&=e8ILYoKKA_~hKqLvBFa{v6eOHP0>-+`y(@Jum5i@h$3tWuYUXnF5u zHvcccX#0Nw$7KhbMWTX-8I1N#Q`(TSqCF~fA`^?rM}FP{w&emY6Hj?q!;XC>ki9YzH3*yp=NG5 z1Me{fm%JZg@hJXi+9idfgG=qgf-ARR22WBM;x?3pETzR8PByOgt$OWhRUu#&d zEfFq>?EJDIEoz;L;)EC1IQLskpKv|RQ)PXt=X#aGP?L)mg$#M;xK=!R#uc8h>ZsNd zhHMd^V&NVyPKocv9FD8+O}5@}auI*Fc-60!TPLh{&2(cIkCVEvA^hgXSVfkA5MjLs z9H$vp7M1H>@>-kw|M_~YZ1Fj()`l^t=ub|bCcxY*Y&HGW2Fq#@|0xn`8$w>M>NYfU z^sb8Yocwp-ZmGx7-B|Bd;ifmwMXy95A!2aQLwx-dtD(PKW2UjQU zWX$YjxU)>h{Pe~R-jYnOMNBQHia*%uwtKh7MnNOV8HcR*9H|!3lbme+kzf7-li7xi zyLRuH`f!rnguPm?)+?s(ja8iQsQqfMe%0DX*83ht@8fe?_aa*Q$?kn`b}L_fz3;uY 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≤f6^WAekCp!aX%?+h&_uk#$bMDz! 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

%DGjX6yQquz_cjbvZ1B^=kj{#)UbF5 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 z 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 new Date(year, month, day); -export const Date$isDate = (value) => value instanceof Date; -export const Date$Date$year = (value) => value.year; -export const Date$Date$0 = (value) => value.year; -export const Date$Date$month = (value) => value.month; -export const Date$Date$1 = (value) => value.month; -export const Date$Date$day = (value) => value.day; -export const Date$Date$2 = (value) => value.day; - -export class TimeOfDay extends $CustomType { - constructor(hours, minutes, seconds, nanoseconds) { - super(); - this.hours = hours; - this.minutes = minutes; - this.seconds = seconds; - this.nanoseconds = nanoseconds; - } -} -export const TimeOfDay$TimeOfDay = (hours, minutes, seconds, nanoseconds) => - new TimeOfDay(hours, minutes, seconds, nanoseconds); -export const TimeOfDay$isTimeOfDay = (value) => value instanceof TimeOfDay; -export const TimeOfDay$TimeOfDay$hours = (value) => value.hours; -export const TimeOfDay$TimeOfDay$0 = (value) => value.hours; -export const TimeOfDay$TimeOfDay$minutes = (value) => value.minutes; -export const TimeOfDay$TimeOfDay$1 = (value) => value.minutes; -export const TimeOfDay$TimeOfDay$seconds = (value) => value.seconds; -export const TimeOfDay$TimeOfDay$2 = (value) => value.seconds; -export const TimeOfDay$TimeOfDay$nanoseconds = (value) => value.nanoseconds; -export const TimeOfDay$TimeOfDay$3 = (value) => value.nanoseconds; - -export class January extends $CustomType {} -export const Month$January = () => new January(); -export const Month$isJanuary = (value) => value instanceof January; - -export class February extends $CustomType {} -export const Month$February = () => new February(); -export const Month$isFebruary = (value) => value instanceof February; - -export class March extends $CustomType {} -export const Month$March = () => new March(); -export const Month$isMarch = (value) => value instanceof March; - -export class April extends $CustomType {} -export const Month$April = () => new April(); -export const Month$isApril = (value) => value instanceof April; - -export class May extends $CustomType {} -export const Month$May = () => new May(); -export const Month$isMay = (value) => value instanceof May; - -export class June extends $CustomType {} -export const Month$June = () => new June(); -export const Month$isJune = (value) => value instanceof June; - -export class July extends $CustomType {} -export const Month$July = () => new July(); -export const Month$isJuly = (value) => value instanceof July; - -export class August extends $CustomType {} -export const Month$August = () => new August(); -export const Month$isAugust = (value) => value instanceof August; - -export class September extends $CustomType {} -export const Month$September = () => new September(); -export const Month$isSeptember = (value) => value instanceof September; - -export class October extends $CustomType {} -export const Month$October = () => new October(); -export const Month$isOctober = (value) => value instanceof October; - -export class November extends $CustomType {} -export const Month$November = () => new November(); -export const Month$isNovember = (value) => value instanceof November; - -export class December extends $CustomType {} -export const Month$December = () => new December(); -export const Month$isDecember = (value) => value instanceof December; - -/** - * Get the offset for the computer's currently configured time zone. - * - * Note this may not be the time zone that is correct to use for your user. - * For example, if you are making a web application that runs on a server you - * want _their_ computer's time zone, not yours. - * - * This is the _current local_ offset, not the current local time zone. This - * means that while it will result in the expected outcome for the current - * time, it may result in unexpected output if used with other timestamps. For - * example: a timestamp that would locally be during daylight savings time if - * is it not currently daylight savings time when this function is called. - */ -export function local_offset() { - return $duration.seconds(local_time_offset_seconds()); -} - -/** - * Returns the English name for a month. - * - * # Examples - * - * ```gleam - * month_to_string(April) - * // -> "April" - * ``` - */ -export function month_to_string(month) { - if (month instanceof January) { - return "January"; - } else if (month instanceof February) { - return "February"; - } else if (month instanceof March) { - return "March"; - } else if (month instanceof April) { - return "April"; - } else if (month instanceof May) { - return "May"; - } else if (month instanceof June) { - return "June"; - } else if (month instanceof July) { - return "July"; - } else if (month instanceof August) { - return "August"; - } else if (month instanceof September) { - return "September"; - } else if (month instanceof October) { - return "October"; - } else if (month instanceof November) { - return "November"; - } else { - return "December"; - } -} - -/** - * Returns the number for the month, where January is 1 and December is 12. - * - * # Examples - * - * ```gleam - * month_to_int(January) - * // -> 1 - * ``` - */ -export function month_to_int(month) { - if (month instanceof January) { - return 1; - } else if (month instanceof February) { - return 2; - } else if (month instanceof March) { - return 3; - } else if (month instanceof April) { - return 4; - } else if (month instanceof May) { - return 5; - } else if (month instanceof June) { - return 6; - } else if (month instanceof July) { - return 7; - } else if (month instanceof August) { - return 8; - } else if (month instanceof September) { - return 9; - } else if (month instanceof October) { - return 10; - } else if (month instanceof November) { - return 11; - } else { - return 12; - } -} - -/** - * Returns the month for a given number, where January is 1 and December is 12. - * - * # Examples - * - * ```gleam - * month_from_int(1) - * // -> Ok(January) - * ``` - */ -export function month_from_int(month) { - if (month === 1) { - return new Ok(new January()); - } else if (month === 2) { - return new Ok(new February()); - } else if (month === 3) { - return new Ok(new March()); - } else if (month === 4) { - return new Ok(new April()); - } else if (month === 5) { - return new Ok(new May()); - } else if (month === 6) { - return new Ok(new June()); - } else if (month === 7) { - return new Ok(new July()); - } else if (month === 8) { - return new Ok(new August()); - } else if (month === 9) { - return new Ok(new September()); - } else if (month === 10) { - return new Ok(new October()); - } else if (month === 11) { - return new Ok(new November()); - } else if (month === 12) { - return new Ok(new December()); - } else { - return new Error(undefined); - } -} - -/** - * Determines if a given year is a leap year. - * - * A leap year occurs every 4 years, except for years divisible by 100, - * unless they are also divisible by 400. - * - * # Examples - * - * ```gleam - * is_leap_year(2024) - * // -> True - * ``` - * - * ```gleam - * is_leap_year(2023) - * // -> False - * ``` - */ -export function is_leap_year(year) { - let $ = (year % 400) === 0; - if ($) { - return $; - } else { - let $1 = (year % 100) === 0; - if ($1) { - return false; - } else { - return (year % 4) === 0; - } - } -} - -/** - * Checks if a given date is valid. - * - * This function properly accounts for leap years when validating February days. - * A leap year occurs every 4 years, except for years divisible by 100, - * unless they are also divisible by 400. - * - * # Examples - * - * ```gleam - * is_valid_date(Date(2023, April, 15)) - * // -> True - * ``` - * - * ```gleam - * is_valid_date(Date(2023, April, 31)) - * // -> False - * ``` - * - * ```gleam - * is_valid_date(Date(2024, February, 29)) - * // -> True (2024 is a leap year) - * ``` - */ -export function is_valid_date(date) { - let year; - let month; - let day; - year = date.year; - month = date.month; - day = date.day; - let $ = day < 1; - if ($) { - return false; - } else { - if (month instanceof January) { - return day <= 31; - } else if (month instanceof February) { - let _block; - let $1 = is_leap_year(year); - if ($1) { - _block = 29; - } else { - _block = 28; - } - let max_february_days = _block; - return day <= max_february_days; - } else if (month instanceof March) { - return day <= 31; - } else if (month instanceof April) { - return day <= 30; - } else if (month instanceof May) { - return day <= 31; - } else if (month instanceof June) { - return day <= 30; - } else if (month instanceof July) { - return day <= 31; - } else if (month instanceof August) { - return day <= 31; - } else if (month instanceof September) { - return day <= 30; - } else if (month instanceof October) { - return day <= 31; - } else if (month instanceof November) { - return day <= 30; - } else { - return day <= 31; - } - } -} - -/** - * Checks if a time of day is valid. - * - * Validates that hours are 0-23, minutes are 0-59, seconds are 0-59, - * and nanoseconds are 0-999,999,999. - * - * # Examples - * - * ```gleam - * is_valid_time_of_day(TimeOfDay(12, 30, 45, 123456789)) - * // -> True - * ``` - */ -export function is_valid_time_of_day(time) { - let hours; - let minutes; - let seconds; - let nanoseconds; - hours = time.hours; - minutes = time.minutes; - seconds = time.seconds; - nanoseconds = time.nanoseconds; - return (((((((hours >= 0) && (hours <= 23)) && (minutes >= 0)) && (minutes <= 59)) && (seconds >= 0)) && (seconds <= 59)) && (nanoseconds >= 0)) && (nanoseconds <= 999_999_999); -} - -/** - * Naively compares two dates without any time zone information, returning an - * order. - * - * ## Correctness - * - * This function compares dates without any time zone information, only using - * the rules for the gregorian calendar. This is typically sufficient, but be - * aware that in reality some time zones will change their calendar date - * occasionally. This can result in days being skipped, out of order, or - * happening multiple times. - * - * If you need real-world correct time ordering then use the - * `gleam/time/timestamp` module instead. - */ -export function naive_date_compare(one, other) { - let _pipe = $int.compare(one.year, other.year); - let _pipe$1 = $order.lazy_break_tie( - _pipe, - () => { - return $int.compare(month_to_int(one.month), month_to_int(other.month)); - }, - ); - return $order.lazy_break_tie( - _pipe$1, - () => { return $int.compare(one.day, other.day); }, - ); -} - -/** - * The offset for the [Coordinated Universal Time (UTC)](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) - * time zone. - * - * The utc zone has no time adjustments, it is always zero. It never observes - * daylight-saving time and it never shifts around based on political - * restructuring. - */ -export const utc_offset = $duration.empty; diff --git a/build/dev/javascript/gleam_time/gleam/time/duration.mjs b/build/dev/javascript/gleam_time/gleam/time/duration.mjs deleted file mode 100644 index 53657d0..0000000 --- a/build/dev/javascript/gleam_time/gleam/time/duration.mjs +++ /dev/null @@ -1,382 +0,0 @@ -import * as $bool from "../../../gleam_stdlib/gleam/bool.mjs"; -import * as $int from "../../../gleam_stdlib/gleam/int.mjs"; -import * as $order from "../../../gleam_stdlib/gleam/order.mjs"; -import * as $string from "../../../gleam_stdlib/gleam/string.mjs"; -import { CustomType as $CustomType, remainderInt, divideInt, isEqual } from "../../gleam.mjs"; - -class Duration extends $CustomType { - constructor(seconds, nanoseconds) { - super(); - this.seconds = seconds; - this.nanoseconds = nanoseconds; - } -} - -export class Nanosecond extends $CustomType {} -export const Unit$Nanosecond = () => new Nanosecond(); -export const Unit$isNanosecond = (value) => value instanceof Nanosecond; - -export class Microsecond extends $CustomType {} -export const Unit$Microsecond = () => new Microsecond(); -export const Unit$isMicrosecond = (value) => value instanceof Microsecond; - -export class Millisecond extends $CustomType {} -export const Unit$Millisecond = () => new Millisecond(); -export const Unit$isMillisecond = (value) => value instanceof Millisecond; - -export class Second extends $CustomType {} -export const Unit$Second = () => new Second(); -export const Unit$isSecond = (value) => value instanceof Second; - -export class Minute extends $CustomType {} -export const Unit$Minute = () => new Minute(); -export const Unit$isMinute = (value) => value instanceof Minute; - -export class Hour extends $CustomType {} -export const Unit$Hour = () => new Hour(); -export const Unit$isHour = (value) => value instanceof Hour; - -export class Day extends $CustomType {} -export const Unit$Day = () => new Day(); -export const Unit$isDay = (value) => value instanceof Day; - -export class Week extends $CustomType {} -export const Unit$Week = () => new Week(); -export const Unit$isWeek = (value) => value instanceof Week; - -export class Month extends $CustomType {} -export const Unit$Month = () => new Month(); -export const Unit$isMonth = (value) => value instanceof Month; - -export class Year extends $CustomType {} -export const Unit$Year = () => new Year(); -export const Unit$isYear = (value) => value instanceof Year; - -/** - * Ensure the duration is represented with `nanoseconds` being positive and - * less than 1 second. - * - * This function does not change the amount of time that the duratoin refers - * to, it only adjusts the values used to represent the time. - * - * @ignore - */ -function normalise(duration) { - let multiplier = 1_000_000_000; - let nanoseconds$1 = remainderInt(duration.nanoseconds, multiplier); - let overflow = duration.nanoseconds - nanoseconds$1; - let seconds$1 = duration.seconds + (divideInt(overflow, multiplier)); - let $ = nanoseconds$1 >= 0; - if ($) { - return new Duration(seconds$1, nanoseconds$1); - } else { - return new Duration(seconds$1 - 1, multiplier + nanoseconds$1); - } -} - -/** - * Convert a duration to a number of the largest number of a unit, serving as - * a rough description of the duration that a human can understand. - * - * The size used for each unit are described in the documentation for the - * `Unit` type. - * - * ```gleam - * seconds(125) - * |> approximate - * // -> #(2, Minute) - * ``` - * - * This function rounds _towards zero_. This means that if a duration is just - * short of 2 days then it will approximate to 1 day. - * - * ```gleam - * hours(47) - * |> approximate - * // -> #(1, Day) - * ``` - */ -export function approximate(duration) { - let s; - let ns; - s = duration.seconds; - ns = duration.nanoseconds; - let minute = 60; - let hour = minute * 60; - let day = hour * 24; - let week = day * 7; - let year = day * 365 + hour * 6; - let month = globalThis.Math.trunc(year / 12); - let microsecond = 1000; - let millisecond = microsecond * 1000; - let $ = undefined; - if (s < 0) { - let _block; - let _pipe = new Duration(- s, - ns); - let _pipe$1 = normalise(_pipe); - _block = approximate(_pipe$1); - let $1 = _block; - let amount; - let unit; - amount = $1[0]; - unit = $1[1]; - return [- amount, unit]; - } else if (s >= year) { - return [divideInt(s, year), new Year()]; - } else if (s >= month) { - return [divideInt(s, month), new Month()]; - } else if (s >= week) { - return [divideInt(s, week), new Week()]; - } else if (s >= day) { - return [divideInt(s, day), new Day()]; - } else if (s >= hour) { - return [divideInt(s, hour), new Hour()]; - } else if (s >= minute) { - return [divideInt(s, minute), new Minute()]; - } else if (s > 0) { - return [s, new Second()]; - } else if (ns >= millisecond) { - return [divideInt(ns, millisecond), new Millisecond()]; - } else if (ns >= microsecond) { - return [divideInt(ns, microsecond), new Microsecond()]; - } else { - return [ns, new Nanosecond()]; - } -} - -/** - * Compare one duration to another, indicating whether the first spans a - * larger amount of time (and so is greater) or smaller amount of time (and so - * is lesser) than the second. - * - * # Examples - * - * ```gleam - * compare(seconds(1), seconds(2)) - * // -> order.Lt - * ``` - * - * Whether a duration is negative or positive doesn't matter for comparing - * them, only the amount of time spanned matters. - * - * ```gleam - * compare(seconds(-2), seconds(1)) - * // -> order.Gt - * ``` - */ -export function compare(left, right) { - let parts = (x) => { - let $ = x.seconds >= 0; - if ($) { - return [x.seconds, x.nanoseconds]; - } else { - return [x.seconds * -1 - 1, 1_000_000_000 - x.nanoseconds]; - } - }; - let $ = parts(left); - let ls; - let lns; - ls = $[0]; - lns = $[1]; - let $1 = parts(right); - let rs; - let rns; - rs = $1[0]; - rns = $1[1]; - let _pipe = $int.compare(ls, rs); - return $order.break_tie(_pipe, $int.compare(lns, rns)); -} - -/** - * Calculate the difference between two durations. - * - * This is effectively substracting the first duration from the second. - * - * # Examples - * - * ```gleam - * difference(seconds(1), seconds(5)) - * // -> seconds(4) - * ``` - */ -export function difference(left, right) { - let _pipe = new Duration( - right.seconds - left.seconds, - right.nanoseconds - left.nanoseconds, - ); - return normalise(_pipe); -} - -/** - * Add two durations together. - * - * # Examples - * - * ```gleam - * add(seconds(1), seconds(5)) - * // -> seconds(6) - * ``` - */ -export function add(left, right) { - let _pipe = new Duration( - left.seconds + right.seconds, - left.nanoseconds + right.nanoseconds, - ); - return normalise(_pipe); -} - -function nanosecond_digits(loop$n, loop$position, loop$acc) { - while (true) { - let n = loop$n; - let position = loop$position; - let acc = loop$acc; - if (position === 9) { - return acc; - } else if ((acc === "") && ((remainderInt(n, 10)) === 0)) { - loop$n = globalThis.Math.trunc(n / 10); - loop$position = position + 1; - loop$acc = acc; - } else { - let acc$1 = $int.to_string(n % 10) + acc; - loop$n = globalThis.Math.trunc(n / 10); - loop$position = position + 1; - loop$acc = acc$1; - } - } -} - -/** - * Create a duration of a number of seconds. - */ -export function seconds(amount) { - return new Duration(amount, 0); -} - -/** - * Create a duration of a number of minutes. - */ -export function minutes(amount) { - return seconds(amount * 60); -} - -/** - * Create a duration of a number of hours. - */ -export function hours(amount) { - return seconds(amount * 60 * 60); -} - -/** - * Create a duration of a number of milliseconds. - */ -export function milliseconds(amount) { - let remainder = amount % 1000; - let overflow = amount - remainder; - let nanoseconds$1 = remainder * 1_000_000; - let seconds$1 = globalThis.Math.trunc(overflow / 1000); - let _pipe = new Duration(seconds$1, nanoseconds$1); - return normalise(_pipe); -} - -/** - * Create a duration of a number of nanoseconds. - * - * # JavaScript int limitations - * - * Remember that JavaScript can only perfectly represent ints between positive - * and negative 9,007,199,254,740,991! If you use a single call to this - * function to create durations larger than that number of nanoseconds then - * you will likely not get exactly the value you expect. Use `seconds` and - * `milliseconds` as much as possible for large durations. - */ -export function nanoseconds(amount) { - let _pipe = new Duration(0, amount); - return normalise(_pipe); -} - -/** - * Convert the duration to a number of seconds. - * - * There may be some small loss of precision due to `Duration` being - * nanosecond accurate and `Float` not being able to represent this. - */ -export function to_seconds(duration) { - let seconds$1 = $int.to_float(duration.seconds); - let nanoseconds$1 = $int.to_float(duration.nanoseconds); - return seconds$1 + (nanoseconds$1 / 1_000_000_000.0); -} - -/** - * Convert the duration to a number of seconds and nanoseconds. There is no - * loss of precision with this conversion on any target. - */ -export function to_seconds_and_nanoseconds(duration) { - return [duration.seconds, duration.nanoseconds]; -} - -export const empty = /* @__PURE__ */ new Duration(0, 0); - -/** - * Convert the duration to an [ISO8601][1] formatted duration string. - * - * The ISO8601 duration format is ambiguous without context due to months and - * years having different lengths, and because of leap seconds. This function - * encodes the duration as days, hours, and seconds without any leap seconds. - * Be sure to take this into account when using the duration strings. - * - * [1]: https://en.wikipedia.org/wiki/ISO_8601#Durations - */ -export function to_iso8601_string(duration) { - return $bool.guard( - isEqual(duration, empty), - "PT0S", - () => { - let split = (total, limit) => { - let amount = remainderInt(total, limit); - let remainder = divideInt((total - amount), limit); - return [amount, remainder]; - }; - let $ = split(duration.seconds, 60); - let seconds$1; - let rest; - seconds$1 = $[0]; - rest = $[1]; - let $1 = split(rest, 60); - let minutes$1; - let rest$1; - minutes$1 = $1[0]; - rest$1 = $1[1]; - let $2 = split(rest$1, 24); - let hours$1; - let rest$2; - hours$1 = $2[0]; - rest$2 = $2[1]; - let days = rest$2; - let add$1 = (out, value, unit) => { - if (value === 0) { - return out; - } else { - return (out + $int.to_string(value)) + unit; - } - }; - let _block; - let _pipe = "P"; - let _pipe$1 = add$1(_pipe, days, "D"); - let _pipe$2 = $string.append(_pipe$1, "T"); - let _pipe$3 = add$1(_pipe$2, hours$1, "H"); - _block = add$1(_pipe$3, minutes$1, "M"); - let output = _block; - let $3 = duration.nanoseconds; - if ($3 === 0) { - if (seconds$1 === 0) { - return output; - } else { - return (output + $int.to_string(seconds$1)) + "S"; - } - } else { - let f = nanosecond_digits(duration.nanoseconds, 0, ""); - return (((output + $int.to_string(seconds$1)) + ".") + f) + "S"; - } - }, - ); -} diff --git a/build/dev/javascript/gleam_time/gleam/time/timestamp.mjs b/build/dev/javascript/gleam_time/gleam/time/timestamp.mjs deleted file mode 100644 index 2f3ec9b..0000000 --- a/build/dev/javascript/gleam_time/gleam/time/timestamp.mjs +++ /dev/null @@ -1,1215 +0,0 @@ -import * as $bit_array from "../../../gleam_stdlib/gleam/bit_array.mjs"; -import * as $float from "../../../gleam_stdlib/gleam/float.mjs"; -import * as $int from "../../../gleam_stdlib/gleam/int.mjs"; -import * as $list from "../../../gleam_stdlib/gleam/list.mjs"; -import * as $order from "../../../gleam_stdlib/gleam/order.mjs"; -import * as $result from "../../../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../../../gleam_stdlib/gleam/string.mjs"; -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - remainderInt, - divideFloat, - divideInt, - toBitArray, - bitArraySlice, -} from "../../gleam.mjs"; -import * as $calendar from "../../gleam/time/calendar.mjs"; -import * as $duration from "../../gleam/time/duration.mjs"; -import { system_time as get_system_time } from "../../gleam_time_ffi.mjs"; - -class Timestamp extends $CustomType { - constructor(seconds, nanoseconds) { - super(); - this.seconds = seconds; - this.nanoseconds = nanoseconds; - } -} - -/** - * Ensure the time is represented with `nanoseconds` being positive and less - * than 1 second. - * - * This function does not change the time that the timestamp refers to, it - * only adjusts the values used to represent the time. - * - * @ignore - */ -function normalise(timestamp) { - let multiplier = 1_000_000_000; - let nanoseconds = remainderInt(timestamp.nanoseconds, multiplier); - let overflow = timestamp.nanoseconds - nanoseconds; - let seconds = timestamp.seconds + (divideInt(overflow, multiplier)); - let $ = nanoseconds >= 0; - if ($) { - return new Timestamp(seconds, nanoseconds); - } else { - return new Timestamp(seconds - 1, multiplier + nanoseconds); - } -} - -/** - * Compare one timestamp to another, indicating whether the first is further - * into the future (greater) or further into the past (lesser) than the - * second. - * - * # Examples - * - * ```gleam - * compare(from_unix_seconds(1), from_unix_seconds(2)) - * // -> order.Lt - * ``` - */ -export function compare(left, right) { - return $order.break_tie( - $int.compare(left.seconds, right.seconds), - $int.compare(left.nanoseconds, right.nanoseconds), - ); -} - -/** - * Get the current system time. - * - * Note this time is not unique or monotonic, it could change at any time or - * even go backwards! The exact behaviour will depend on the runtime used. See - * the module documentation for more information. - * - * On Erlang this uses [`erlang:system_time/1`][1]. On JavaScript this uses - * [`Date.now`][2]. - * - * [1]: https://www.erlang.org/doc/apps/erts/erlang#system_time/1 - * [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now - */ -export function system_time() { - let $ = get_system_time(); - let seconds; - let nanoseconds; - seconds = $[0]; - nanoseconds = $[1]; - return normalise(new Timestamp(seconds, nanoseconds)); -} - -/** - * Calculate the difference between two timestamps. - * - * This is effectively substracting the first timestamp from the second. - * - * # Examples - * - * ```gleam - * difference(from_unix_seconds(1), from_unix_seconds(5)) - * // -> duration.seconds(4) - * ``` - */ -export function difference(left, right) { - let seconds = $duration.seconds(right.seconds - left.seconds); - let nanoseconds = $duration.nanoseconds(right.nanoseconds - left.nanoseconds); - return $duration.add(seconds, nanoseconds); -} - -/** - * Add a duration to a timestamp. - * - * # Examples - * - * ```gleam - * add(from_unix_seconds(1000), duration.seconds(5)) - * // -> from_unix_seconds(1005) - * ``` - */ -export function add(timestamp, duration) { - let $ = $duration.to_seconds_and_nanoseconds(duration); - let seconds; - let nanoseconds; - seconds = $[0]; - nanoseconds = $[1]; - let _pipe = new Timestamp( - timestamp.seconds + seconds, - timestamp.nanoseconds + nanoseconds, - ); - return normalise(_pipe); -} - -function pad_digit(digit, desired_length) { - let _pipe = $int.to_string(digit); - return $string.pad_start(_pipe, desired_length, "0"); -} - -function duration_to_minutes(duration) { - return $float.round($duration.to_seconds(duration) / 60.0); -} - -function modulo(n, m) { - let $ = $int.modulo(n, m); - if ($ instanceof Ok) { - let n$1 = $[0]; - return n$1; - } else { - return 0; - } -} - -function floored_div(numerator, denominator) { - let n = divideFloat($int.to_float(numerator), denominator); - return $float.round($float.floor(n)); -} - -function to_civil(minutes) { - let raw_day = floored_div(minutes, (60.0 * 24.0)) + 719_468; - let _block; - let $ = raw_day >= 0; - if ($) { - _block = globalThis.Math.trunc(raw_day / 146_097); - } else { - _block = globalThis.Math.trunc((raw_day - 146_096) / 146_097); - } - let era = _block; - let day_of_era = raw_day - era * 146_097; - let year_of_era = globalThis.Math.trunc( - (((day_of_era - (globalThis.Math.trunc(day_of_era / 1460))) + (globalThis.Math.trunc( - day_of_era / 36_524 - ))) - (globalThis.Math.trunc(day_of_era / 146_096))) / 365 - ); - let year = year_of_era + era * 400; - let day_of_year = day_of_era - ((365 * year_of_era + (globalThis.Math.trunc( - year_of_era / 4 - ))) - (globalThis.Math.trunc(year_of_era / 100))); - let mp = globalThis.Math.trunc((5 * day_of_year + 2) / 153); - let _block$1; - let $1 = mp < 10; - if ($1) { - _block$1 = mp + 3; - } else { - _block$1 = mp - 9; - } - let month = _block$1; - let day = (day_of_year - (globalThis.Math.trunc((153 * mp + 2) / 5))) + 1; - let _block$2; - let $2 = month <= 2; - if ($2) { - _block$2 = year + 1; - } else { - _block$2 = year; - } - let year$1 = _block$2; - return [year$1, month, day]; -} - -function to_calendar_from_offset(timestamp, offset) { - let total = timestamp.seconds + offset * 60; - let seconds = modulo(total, 60); - let total_minutes = floored_div(total, 60.0); - let minutes = globalThis.Math.trunc(modulo(total, 60 * 60) / 60); - let hours = divideInt(modulo(total, 24 * 60 * 60), 60 * 60); - let $ = to_civil(total_minutes); - let year; - let month; - let day; - year = $[0]; - month = $[1]; - day = $[2]; - return [year, month, day, hours, minutes, seconds]; -} - -/** - * Convert a `Timestamp` to calendar time, suitable for presenting to a human - * to read. - * - * If you want a machine to use the time value then you should not use this - * function and should instead keep it as a timestamp. See the documentation - * for the `gleam/time/calendar` module for more information. - * - * # Examples - * - * ```gleam - * timestamp.from_unix_seconds(0) - * |> timestamp.to_calendar(calendar.utc_offset) - * // -> #(Date(1970, January, 1), TimeOfDay(0, 0, 0, 0)) - * ``` - */ -export function to_calendar(timestamp, offset) { - let offset$1 = duration_to_minutes(offset); - let $ = to_calendar_from_offset(timestamp, offset$1); - let year; - let month; - let day; - let hours; - let minutes; - let seconds; - year = $[0]; - month = $[1]; - day = $[2]; - hours = $[3]; - minutes = $[4]; - seconds = $[5]; - let _block; - if (month === 1) { - _block = new $calendar.January(); - } else if (month === 2) { - _block = new $calendar.February(); - } else if (month === 3) { - _block = new $calendar.March(); - } else if (month === 4) { - _block = new $calendar.April(); - } else if (month === 5) { - _block = new $calendar.May(); - } else if (month === 6) { - _block = new $calendar.June(); - } else if (month === 7) { - _block = new $calendar.July(); - } else if (month === 8) { - _block = new $calendar.August(); - } else if (month === 9) { - _block = new $calendar.September(); - } else if (month === 10) { - _block = new $calendar.October(); - } else if (month === 11) { - _block = new $calendar.November(); - } else { - _block = new $calendar.December(); - } - let month$1 = _block; - let nanoseconds = timestamp.nanoseconds; - let date = new $calendar.Date(year, month$1, day); - let time = new $calendar.TimeOfDay(hours, minutes, seconds, nanoseconds); - return [date, time]; -} - -function do_remove_trailing_zeros(loop$reversed_digits) { - while (true) { - let reversed_digits = loop$reversed_digits; - if (reversed_digits instanceof $Empty) { - return reversed_digits; - } else { - let digit = reversed_digits.head; - if (digit === 0) { - let digits = reversed_digits.tail; - loop$reversed_digits = digits; - } else { - let reversed_digits$1 = reversed_digits; - return $list.reverse(reversed_digits$1); - } - } - } -} - -/** - * Given a list of digits, return new list with any trailing zeros removed. - * - * @ignore - */ -function remove_trailing_zeros(digits) { - let reversed_digits = $list.reverse(digits); - return do_remove_trailing_zeros(reversed_digits); -} - -function do_get_zero_padded_digits(loop$number, loop$digits, loop$count) { - while (true) { - let number = loop$number; - let digits = loop$digits; - let count = loop$count; - let number$1 = number; - if ((number$1 <= 0) && (count >= 9)) { - return digits; - } else { - let number$2 = number; - if (number$2 <= 0) { - loop$number = number$2; - loop$digits = listPrepend(0, digits); - loop$count = count + 1; - } else { - let number$3 = number; - let digit = number$3 % 10; - let number$4 = floored_div(number$3, 10.0); - loop$number = number$4; - loop$digits = listPrepend(digit, digits); - loop$count = count + 1; - } - } - } -} - -/** - * Returns the list of digits of `number`. If the number of digits is less - * than 9, the result is zero-padded at the front. - * - * @ignore - */ -function get_zero_padded_digits(number) { - return do_get_zero_padded_digits(number, toList([]), 0); -} - -/** - * Converts nanoseconds into a `String` representation of fractional seconds. - * - * Assumes that `nanoseconds < 1_000_000_000`, which will be true for any - * normalised timestamp. - * - * @ignore - */ -function show_second_fraction(nanoseconds) { - let $ = $int.compare(nanoseconds, 0); - if ($ instanceof $order.Lt) { - return ""; - } else if ($ instanceof $order.Eq) { - return ""; - } else { - let _block; - let _pipe = nanoseconds; - let _pipe$1 = get_zero_padded_digits(_pipe); - let _pipe$2 = remove_trailing_zeros(_pipe$1); - let _pipe$3 = $list.map(_pipe$2, $int.to_string); - _block = $string.join(_pipe$3, ""); - let second_fraction_part = _block; - return "." + second_fraction_part; - } -} - -/** - * Convert a timestamp to a RFC 3339 formatted time string, with an offset - * supplied as an additional argument. - * - * The output of this function is also ISO 8601 compatible so long as the - * offset not negative. Offsets have at-most minute precision, so an offset - * with higher precision will be rounded to the nearest minute. - * - * If you are making an API such as a HTTP JSON API you are encouraged to use - * Unix timestamps instead of this format or ISO 8601. Unix timestamps are a - * better choice as they don't contain offset information. Consider: - * - * - UTC offsets are not time zones. This does not and cannot tell us the time - * zone in which the date was recorded. So what are we supposed to do with - * this information? - * - Users typically want dates formatted according to their local time zone. - * What if the provided UTC offset is different from the current user's time - * zone? What are we supposed to do with it then? - * - Despite it being useless (or worse, a source of bugs), the UTC offset - * creates a larger payload to transfer. - * - * They also uses more memory than a unix timestamp. The way they are better - * than Unix timestamp is that it is easier for a human to read them, but - * this is a hinderance that tooling can remedy, and APIs are not primarily - * for humans. - * - * # Examples - * - * ```gleam - * timestamp.from_unix_seconds_and_nanoseconds(1000, 123_000_000) - * |> to_rfc3339(calendar.utc_offset) - * // -> "1970-01-01T00:16:40.123Z" - * ``` - * - * ```gleam - * timestamp.from_unix_seconds(1000) - * |> to_rfc3339(duration.seconds(3600)) - * // -> "1970-01-01T01:16:40+01:00" - * ``` - */ -export function to_rfc3339(timestamp, offset) { - let offset$1 = duration_to_minutes(offset); - let $ = to_calendar_from_offset(timestamp, offset$1); - let years; - let months; - let days; - let hours; - let minutes; - let seconds; - years = $[0]; - months = $[1]; - days = $[2]; - hours = $[3]; - minutes = $[4]; - seconds = $[5]; - let offset_minutes = modulo(offset$1, 60); - let offset_hours = $int.absolute_value(floored_div(offset$1, 60.0)); - let n2 = (_capture) => { return pad_digit(_capture, 2); }; - let n4 = (_capture) => { return pad_digit(_capture, 4); }; - let out = ""; - let out$1 = ((((out + n4(years)) + "-") + n2(months)) + "-") + n2(days); - let out$2 = out$1 + "T"; - let out$3 = ((((out$2 + n2(hours)) + ":") + n2(minutes)) + ":") + n2(seconds); - let out$4 = out$3 + show_second_fraction(timestamp.nanoseconds); - let $1 = $int.compare(offset$1, 0); - if ($1 instanceof $order.Lt) { - return (((out$4 + "-") + n2(offset_hours)) + ":") + n2(offset_minutes); - } else if ($1 instanceof $order.Eq) { - return out$4 + "Z"; - } else { - return (((out$4 + "+") + n2(offset_hours)) + ":") + n2(offset_minutes); - } -} - -function is_leap_year(year) { - return ((year % 4) === 0) && (((year % 100) !== 0) || ((year % 400) === 0)); -} - -function parse_sign(bytes) { - if (bytes.bitSize >= 8) { - if (bytes.byteAt(0) === 43) { - if ((bytes.bitSize - 8) % 8 === 0) { - let remaining_bytes = bitArraySlice(bytes, 8); - return new Ok(["+", remaining_bytes]); - } else { - return new Error(undefined); - } - } else if (bytes.byteAt(0) === 45 && (bytes.bitSize - 8) % 8 === 0) { - let remaining_bytes = bitArraySlice(bytes, 8); - return new Ok(["-", remaining_bytes]); - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} - -/** - * Accept the given value from `bytes` and move past it if found. - * - * @ignore - */ -function accept_byte(bytes, value) { - if (bytes.bitSize >= 8 && (bytes.bitSize - 8) % 8 === 0) { - let byte = bytes.byteAt(0); - if (byte === value) { - let remaining_bytes = bitArraySlice(bytes, 8); - return new Ok(remaining_bytes); - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} - -function accept_empty(bytes) { - if (bytes.bitSize === 0) { - return new Ok(undefined); - } else { - return new Error(undefined); - } -} - -/** - * Note: It is the callers responsibility to ensure the inputs are valid. - * - * See https://www.tondering.dk/claus/cal/julperiod.php#formula - * - * @ignore - */ -function julian_day_from_ymd(year, month, day) { - let adjustment = globalThis.Math.trunc((14 - month) / 12); - let adjusted_year = (year + 4800) - adjustment; - let adjusted_month = (month + 12 * adjustment) - 3; - return (((((day + (globalThis.Math.trunc((153 * adjusted_month + 2) / 5))) + 365 * adjusted_year) + (globalThis.Math.trunc( - adjusted_year / 4 - ))) - (globalThis.Math.trunc(adjusted_year / 100))) + (globalThis.Math.trunc( - adjusted_year / 400 - ))) - 32_045; -} - -/** - * Create a timestamp from a number of seconds since 00:00:00 UTC on 1 January - * 1970. - */ -export function from_unix_seconds(seconds) { - return new Timestamp(seconds, 0); -} - -/** - * Create a timestamp from a number of seconds and nanoseconds since 00:00:00 - * UTC on 1 January 1970. - * - * # JavaScript int limitations - * - * Remember that JavaScript can only perfectly represent ints between positive - * and negative 9,007,199,254,740,991! If you only use the nanosecond field - * then you will almost certainly not get the date value you want due to this - * loss of precision. Always use seconds primarily and then use nanoseconds - * for the final sub-second adjustment. - */ -export function from_unix_seconds_and_nanoseconds(seconds, nanoseconds) { - let _pipe = new Timestamp(seconds, nanoseconds); - return normalise(_pipe); -} - -/** - * Convert the timestamp to a number of seconds since 00:00:00 UTC on 1 - * January 1970. - * - * There may be some small loss of precision due to `Timestamp` being - * nanosecond accurate and `Float` not being able to represent this. - */ -export function to_unix_seconds(timestamp) { - let seconds = $int.to_float(timestamp.seconds); - let nanoseconds = $int.to_float(timestamp.nanoseconds); - return seconds + (nanoseconds / 1_000_000_000.0); -} - -/** - * Convert the timestamp to a number of seconds and nanoseconds since 00:00:00 - * UTC on 1 January 1970. There is no loss of precision with this conversion - * on any target. - */ -export function to_unix_seconds_and_nanoseconds(timestamp) { - return [timestamp.seconds, timestamp.nanoseconds]; -} - -const seconds_per_day = 86_400; - -const seconds_per_hour = 3600; - -const seconds_per_minute = 60; - -function offset_to_seconds(sign, hours, minutes) { - let abs_seconds = hours * seconds_per_hour + minutes * seconds_per_minute; - if (sign === "-") { - return - abs_seconds; - } else { - return abs_seconds; - } -} - -/** - * `julian_seconds_from_parts(year, month, day, hours, minutes, seconds)` - * returns the number of Julian - * seconds represented by the given arguments. - * - * Note: It is the callers responsibility to ensure the inputs are valid. - * - * See https://www.tondering.dk/claus/cal/julperiod.php#formula - * - * @ignore - */ -function julian_seconds_from_parts(year, month, day, hours, minutes, seconds) { - let julian_day_seconds = julian_day_from_ymd(year, month, day) * seconds_per_day; - return ((julian_day_seconds + hours * seconds_per_hour) + minutes * seconds_per_minute) + seconds; -} - -const nanoseconds_per_second = 1_000_000_000; - -/** - * The `:` character as a byte - * - * @ignore - */ -const byte_colon = 0x3A; - -/** - * The `-` character as a byte - * - * @ignore - */ -const byte_minus = 0x2D; - -/** - * The `0` character as a byte - * - * @ignore - */ -const byte_zero = 0x30; - -/** - * The `9` character as a byte - * - * @ignore - */ -const byte_nine = 0x39; - -function do_parse_second_fraction_as_nanoseconds( - loop$bytes, - loop$acc, - loop$power -) { - while (true) { - let bytes = loop$bytes; - let acc = loop$acc; - let power = loop$power; - let power$1 = globalThis.Math.trunc(power / 10); - if (bytes.bitSize >= 8 && (bytes.bitSize - 8) % 8 === 0) { - let byte = bytes.byteAt(0); - if (((0x30 <= byte) && (byte <= 0x39)) && (power$1 < 1)) { - let remaining_bytes = bitArraySlice(bytes, 8); - loop$bytes = remaining_bytes; - loop$acc = acc; - loop$power = power$1; - } else { - let byte$1 = bytes.byteAt(0); - if ((0x30 <= byte$1) && (byte$1 <= 0x39)) { - let remaining_bytes = bitArraySlice(bytes, 8); - let digit = byte$1 - 0x30; - loop$bytes = remaining_bytes; - loop$acc = acc + digit * power$1; - loop$power = power$1; - } else { - return new Ok([acc, bytes]); - } - } - } else { - return new Ok([acc, bytes]); - } - } -} - -function parse_second_fraction_as_nanoseconds(bytes) { - if (bytes.bitSize >= 8 && bytes.byteAt(0) === 46) { - if (bytes.bitSize >= 16 && (bytes.bitSize - 16) % 8 === 0) { - let byte = bytes.byteAt(1); - if ((0x30 <= byte) && (byte <= 0x39)) { - let remaining_bytes = bitArraySlice(bytes, 16); - return do_parse_second_fraction_as_nanoseconds( - toBitArray([byte, remaining_bytes]), - 0, - nanoseconds_per_second, - ); - } else if ((bytes.bitSize - 8) % 8 === 0) { - return new Error(undefined); - } else { - return new Ok([0, bytes]); - } - } else if ((bytes.bitSize - 8) % 8 === 0) { - return new Error(undefined); - } else { - return new Ok([0, bytes]); - } - } else { - return new Ok([0, bytes]); - } -} - -function do_parse_digits(loop$bytes, loop$count, loop$acc, loop$k) { - while (true) { - let bytes = loop$bytes; - let count = loop$count; - let acc = loop$acc; - let k = loop$k; - if (k >= count) { - return new Ok([acc, bytes]); - } else if (bytes.bitSize >= 8 && (bytes.bitSize - 8) % 8 === 0) { - let byte = bytes.byteAt(0); - if ((0x30 <= byte) && (byte <= 0x39)) { - let remaining_bytes = bitArraySlice(bytes, 8); - loop$bytes = remaining_bytes; - loop$count = count; - loop$acc = acc * 10 + (byte - 0x30); - loop$k = k + 1; - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } - } -} - -/** - * Parse and return the given number of digits from the given bytes. - * - * @ignore - */ -function parse_digits(bytes, count) { - return do_parse_digits(bytes, count, 0, 0); -} - -function parse_year(bytes) { - return parse_digits(bytes, 4); -} - -function parse_month(bytes) { - return $result.try$( - parse_digits(bytes, 2), - (_use0) => { - let month; - let bytes$1; - month = _use0[0]; - bytes$1 = _use0[1]; - let $ = (1 <= month) && (month <= 12); - if ($) { - return new Ok([month, bytes$1]); - } else { - return new Error(undefined); - } - }, - ); -} - -function parse_day(bytes, year, month) { - return $result.try$( - parse_digits(bytes, 2), - (_use0) => { - let day; - let bytes$1; - day = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - (() => { - if (month === 1) { - return new Ok(31); - } else if (month === 3) { - return new Ok(31); - } else if (month === 5) { - return new Ok(31); - } else if (month === 7) { - return new Ok(31); - } else if (month === 8) { - return new Ok(31); - } else if (month === 10) { - return new Ok(31); - } else if (month === 12) { - return new Ok(31); - } else if (month === 4) { - return new Ok(30); - } else if (month === 6) { - return new Ok(30); - } else if (month === 9) { - return new Ok(30); - } else if (month === 11) { - return new Ok(30); - } else if (month === 2) { - let $ = is_leap_year(year); - if ($) { - return new Ok(29); - } else { - return new Ok(28); - } - } else { - return new Error(undefined); - } - })(), - (max_day) => { - let $ = (1 <= day) && (day <= max_day); - if ($) { - return new Ok([day, bytes$1]); - } else { - return new Error(undefined); - } - }, - ); - }, - ); -} - -function parse_hours(bytes) { - return $result.try$( - parse_digits(bytes, 2), - (_use0) => { - let hours; - let bytes$1; - hours = _use0[0]; - bytes$1 = _use0[1]; - let $ = (0 <= hours) && (hours <= 23); - if ($) { - return new Ok([hours, bytes$1]); - } else { - return new Error(undefined); - } - }, - ); -} - -function parse_minutes(bytes) { - return $result.try$( - parse_digits(bytes, 2), - (_use0) => { - let minutes; - let bytes$1; - minutes = _use0[0]; - bytes$1 = _use0[1]; - let $ = (0 <= minutes) && (minutes <= 59); - if ($) { - return new Ok([minutes, bytes$1]); - } else { - return new Error(undefined); - } - }, - ); -} - -function parse_seconds(bytes) { - return $result.try$( - parse_digits(bytes, 2), - (_use0) => { - let seconds; - let bytes$1; - seconds = _use0[0]; - bytes$1 = _use0[1]; - let $ = (0 <= seconds) && (seconds <= 60); - if ($) { - return new Ok([seconds, bytes$1]); - } else { - return new Error(undefined); - } - }, - ); -} - -function parse_numeric_offset(bytes) { - return $result.try$( - parse_sign(bytes), - (_use0) => { - let sign; - let bytes$1; - sign = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - parse_hours(bytes$1), - (_use0) => { - let hours; - let bytes$2; - hours = _use0[0]; - bytes$2 = _use0[1]; - return $result.try$( - accept_byte(bytes$2, byte_colon), - (bytes) => { - return $result.try$( - parse_minutes(bytes), - (_use0) => { - let minutes; - let bytes$1; - minutes = _use0[0]; - bytes$1 = _use0[1]; - let offset_seconds = offset_to_seconds(sign, hours, minutes); - return new Ok([offset_seconds, bytes$1]); - }, - ); - }, - ); - }, - ); - }, - ); -} - -function parse_offset(bytes) { - if (bytes.bitSize >= 8) { - if (bytes.byteAt(0) === 90) { - if ((bytes.bitSize - 8) % 8 === 0) { - let remaining_bytes = bitArraySlice(bytes, 8); - return new Ok([0, remaining_bytes]); - } else { - return parse_numeric_offset(bytes); - } - } else if (bytes.byteAt(0) === 122 && (bytes.bitSize - 8) % 8 === 0) { - let remaining_bytes = bitArraySlice(bytes, 8); - return new Ok([0, remaining_bytes]); - } else { - return parse_numeric_offset(bytes); - } - } else { - return parse_numeric_offset(bytes); - } -} - -/** - * The `t` character as a byte - * - * @ignore - */ -const byte_t_lowercase = 0x74; - -/** - * The `T` character as a byte - * - * @ignore - */ -const byte_t_uppercase = 0x54; - -/** - * The `T` character as a byte - * - * @ignore - */ -const byte_space = 0x20; - -function accept_date_time_separator(bytes) { - if (bytes.bitSize >= 8 && (bytes.bitSize - 8) % 8 === 0) { - let byte = bytes.byteAt(0); - if (((byte === 0x54) || (byte === 0x74)) || (byte === 0x20)) { - let remaining_bytes = bitArraySlice(bytes, 8); - return new Ok(remaining_bytes); - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} - -/** - * The Julian seconds of the UNIX epoch (Julian day is 2_440_588) - * - * @ignore - */ -const julian_seconds_unix_epoch = 210_866_803_200; - -/** - * Note: The caller of this function must ensure that all inputs are valid. - * - * @ignore - */ -function from_date_time( - year, - month, - day, - hours, - minutes, - seconds, - second_fraction_as_nanoseconds, - offset_seconds -) { - let julian_seconds = julian_seconds_from_parts( - year, - month, - day, - hours, - minutes, - seconds, - ); - let julian_seconds_since_epoch = julian_seconds - julian_seconds_unix_epoch; - let _pipe = new Timestamp( - julian_seconds_since_epoch - offset_seconds, - second_fraction_as_nanoseconds, - ); - return normalise(_pipe); -} - -/** - * Create a `Timestamp` from a human-readable calendar time. - * - * # Examples - * - * ```gleam - * timestamp.from_calendar( - * date: calendar.Date(2024, calendar.December, 25), - * time: calendar.TimeOfDay(12, 30, 50, 0), - * offset: calendar.utc_offset, - * ) - * |> timestamp.to_rfc3339(calendar.utc_offset) - * // -> "2024-12-25T12:30:50Z" - * ``` - */ -export function from_calendar(date, time, offset) { - let _block; - let $ = date.month; - if ($ instanceof $calendar.January) { - _block = 1; - } else if ($ instanceof $calendar.February) { - _block = 2; - } else if ($ instanceof $calendar.March) { - _block = 3; - } else if ($ instanceof $calendar.April) { - _block = 4; - } else if ($ instanceof $calendar.May) { - _block = 5; - } else if ($ instanceof $calendar.June) { - _block = 6; - } else if ($ instanceof $calendar.July) { - _block = 7; - } else if ($ instanceof $calendar.August) { - _block = 8; - } else if ($ instanceof $calendar.September) { - _block = 9; - } else if ($ instanceof $calendar.October) { - _block = 10; - } else if ($ instanceof $calendar.November) { - _block = 11; - } else { - _block = 12; - } - let month = _block; - return from_date_time( - date.year, - month, - date.day, - time.hours, - time.minutes, - time.seconds, - time.nanoseconds, - $float.round($duration.to_seconds(offset)), - ); -} - -/** - * Parses an [RFC 3339 formatted time string][spec] into a `Timestamp`. - * - * [spec]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6 - * - * # Examples - * - * ```gleam - * let assert Ok(ts) = timestamp.parse_rfc3339("1970-01-01T00:00:01Z") - * timestamp.to_unix_seconds_and_nanoseconds(ts) - * // -> #(1, 0) - * ``` - * - * Parsing an invalid timestamp returns an error. - * - * ```gleam - * let assert Error(Nil) = timestamp.parse_rfc3339("1995-10-31") - * ``` - * - * ## Time zones - * - * It may at first seem that the RFC 3339 format includes timezone - * information, as it can specify an offset such as `Z` or `+3`, so why does - * this function not return calendar time with a time zone? There are multiple - * reasons: - * - * - RFC 3339's timestamp format is based on calendar time, but it is - * unambigous, so it can be converted into epoch time when being parsed. It - * is always better to internally use epoch time to represent unambiguous - * points in time, so we perform that conversion as a convenience and to - * ensure that programmers with less time experience don't accidentally use - * a less suitable time representation. - * - * - RFC 3339's contains _calendar time offset_ information, not time zone - * information. This is enough to convert it to an unambiguous timestamp, - * but it is not enough information to reliably work with calendar time. - * Without the time zone and the time zone database it's not possible to - * know what time period that offset is valid for, so it cannot be used - * without risk of bugs. - * - * ## Behaviour details - * - * - Follows the grammar specified in section 5.6 Internet Date/Time Format of - * RFC 3339 . - * - The `T` and `Z` characters may alternatively be lower case `t` or `z`, - * respectively. - * - Full dates and full times must be separated by `T` or `t`. A space is also - * permitted. - * - Leap seconds rules are not considered. That is, any timestamp may - * specify digts `00` - `60` for the seconds. - * - Any part of a fractional second that cannot be represented in the - * nanosecond precision is tructated. That is, for the time string, - * `"1970-01-01T00:00:00.1234567899Z"`, the fractional second `.1234567899` - * will be represented as `123_456_789` in the `Timestamp`. - */ -export function parse_rfc3339(input) { - let bytes = $bit_array.from_string(input); - return $result.try$( - parse_year(bytes), - (_use0) => { - let year; - let bytes$1; - year = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - accept_byte(bytes$1, byte_minus), - (bytes) => { - return $result.try$( - parse_month(bytes), - (_use0) => { - let month; - let bytes$1; - month = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - accept_byte(bytes$1, byte_minus), - (bytes) => { - return $result.try$( - parse_day(bytes, year, month), - (_use0) => { - let day; - let bytes$1; - day = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - accept_date_time_separator(bytes$1), - (bytes) => { - return $result.try$( - parse_hours(bytes), - (_use0) => { - let hours; - let bytes$1; - hours = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - accept_byte(bytes$1, byte_colon), - (bytes) => { - return $result.try$( - parse_minutes(bytes), - (_use0) => { - let minutes; - let bytes$1; - minutes = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - accept_byte(bytes$1, byte_colon), - (bytes) => { - return $result.try$( - parse_seconds(bytes), - (_use0) => { - let seconds; - let bytes$1; - seconds = _use0[0]; - bytes$1 = _use0[1]; - return $result.try$( - parse_second_fraction_as_nanoseconds( - bytes$1, - ), - (_use0) => { - let second_fraction_as_nanoseconds; - let bytes$2; - second_fraction_as_nanoseconds = _use0[0]; - bytes$2 = _use0[1]; - return $result.try$( - parse_offset(bytes$2), - (_use0) => { - let offset_seconds; - let bytes$3; - offset_seconds = _use0[0]; - bytes$3 = _use0[1]; - return $result.try$( - accept_empty(bytes$3), - (_use0) => { - - return new Ok( - from_date_time( - year, - month, - day, - hours, - minutes, - seconds, - second_fraction_as_nanoseconds, - offset_seconds, - ), - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ); -} - -/** - * The epoch of Unix time, which is 00:00:00 UTC on 1 January 1970. - */ -export const unix_epoch = /* @__PURE__ */ new Timestamp(0, 0); diff --git a/build/dev/javascript/gleam_time/gleam@time@calendar.erl b/build/dev/javascript/gleam_time/gleam@time@calendar.erl deleted file mode 100644 index e295d09..0000000 --- a/build/dev/javascript/gleam_time/gleam@time@calendar.erl +++ /dev/null @@ -1,468 +0,0 @@ --module(gleam@time@calendar). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/time/calendar.gleam"). --export([local_offset/0, month_to_string/1, month_to_int/1, month_from_int/1, is_leap_year/1, is_valid_date/1, is_valid_time_of_day/1, naive_date_compare/2]). --export_type([date/0, time_of_day/0, month/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " This module is for working with the Gregorian calendar, established by\n" - " Pope Gregory XIII in 1582!\n" - "\n" - " ## When should you use this module?\n" - "\n" - " > **tldr:** You probably want to use [`gleam/time/timestamp`](./timestamp.html)\n" - " > instead!\n" - "\n" - " Calendar time is difficult to work with programmatically, it is the source\n" - " of most time-related bugs in software. Compared to _epoch time_, which the\n" - " `gleam/time/timestamp` module uses, there are many disadvantages to\n" - " calendar time:\n" - "\n" - " - They are ambiguous if you don't know what time-zone is being used.\n" - "\n" - " - A time-zone database is required to understand calendar time even when\n" - " you have the time zone. These are large and your program has to\n" - " continously be updated as new versions of the database are published.\n" - "\n" - " - The type permits invalid states. e.g. `days` could be set to the number\n" - " 32, but this should not be possible!\n" - "\n" - " - There is not a single unique canonical value for each point in time,\n" - " thanks to time zones. Two different `Date` + `TimeOfDay` value pairs\n" - " could represent the same point in time. This means that you can't check\n" - " for time equality with `==` when using calendar types.\n" - "\n" - " - They are computationally complex, using a more memory to represent and\n" - " requiring a lot more CPU time to manipulate.\n" - "\n" - " There are also advantages to calendar time:\n" - "\n" - " - Calendar time is how human's talk about time, so if you want to show a\n" - " time or take a time from a human user then calendar time will make it\n" - " easier for them.\n" - "\n" - " - They can represent more abstract time periods such as \"New Year's Day\".\n" - " This may seem like an exact window of time at first, but really the\n" - " definition of \"New Year's Day\" is more fuzzy than that. When it starts\n" - " and ends will depend where in the world you are, so if you want to refer\n" - " to a day as a global concept instead of a fixed window of time for that\n" - " day in a specific location, then calendar time can represent that.\n" - "\n" - " So when should you use calendar time? These are our recommendations:\n" - "\n" - " - Default to `gleam/time/timestamp`, which is epoch time. It is\n" - " unambiguous, efficient, and significantly less likely to result in logic\n" - " bugs.\n" - "\n" - " - When writing time to a database or other data storage use epoch time,\n" - " using whatever epoch format it supports. For example, PostgreSQL\n" - " `timestamp` and `timestampz` are both epoch time, and `timestamp` is\n" - " preferred as it is more straightforward to use as your application is\n" - " also using epoch time.\n" - "\n" - " - When communicating with other computer systems continue to use epoch\n" - " time. For example, when sending times to another program you could\n" - " encode time as UNIX timestamps (seconds since 00:00:00 UTC on 1 January\n" - " 1970).\n" - "\n" - " - When communicating with humans use epoch time internally, and convert\n" - " to-and-from calendar time at the last moment, when iteracting with the\n" - " human user. It may also help the users to also show the time as a fuzzy\n" - " duration from the present time, such as \"about 4 days ago\".\n" - "\n" - " - When representing \"fuzzy\" human time concepts that don't exact periods\n" - " in time, such as \"one month\" (varies depending on which month, which\n" - " year, and in which time zone) and \"Christmas Day\" (varies depending on\n" - " which year and time zone) then use calendar time.\n" - "\n" - " Any time you do use calendar time you should be extra careful! It is very\n" - " easy to make mistake with. Avoid it where possible.\n" - "\n" - " ## Time zone offsets\n" - "\n" - " This package includes the `utc_offset` value and the `local_offset`\n" - " function, which are the offset for the UTC time zone and get the time\n" - " offset the computer running the program is configured to respectively.\n" - "\n" - " If you need to use other offsets in your program then you will need to get\n" - " them from somewhere else, such as from a package which loads the\n" - " [IANA Time Zone Database](https://www.iana.org/time-zones), or from the\n" - " website visitor's web browser, which your frontend can send for you.\n" - "\n" - " ## Use in APIs\n" - "\n" - " If you are making an API such as a HTTP JSON API you are encouraged to use\n" - " Unix timestamps instead of calendar times.\n" -). - --type date() :: {date, integer(), month(), integer()}. - --type time_of_day() :: {time_of_day, integer(), integer(), integer(), integer()}. - --type month() :: january | - february | - march | - april | - may | - june | - july | - august | - september | - october | - november | - december. - --file("src/gleam/time/calendar.gleam", 147). -?DOC( - " Get the offset for the computer's currently configured time zone.\n" - "\n" - " Note this may not be the time zone that is correct to use for your user.\n" - " For example, if you are making a web application that runs on a server you\n" - " want _their_ computer's time zone, not yours.\n" - "\n" - " This is the _current local_ offset, not the current local time zone. This\n" - " means that while it will result in the expected outcome for the current\n" - " time, it may result in unexpected output if used with other timestamps. For\n" - " example: a timestamp that would locally be during daylight savings time if\n" - " is it not currently daylight savings time when this function is called.\n" -). --spec local_offset() -> gleam@time@duration:duration(). -local_offset() -> - gleam@time@duration:seconds(gleam_time_ffi:local_time_offset_seconds()). - --file("src/gleam/time/calendar.gleam", 163). -?DOC( - " Returns the English name for a month.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " month_to_string(April)\n" - " // -> \"April\"\n" - " ```\n" -). --spec month_to_string(month()) -> binary(). -month_to_string(Month) -> - case Month of - january -> - <<"January"/utf8>>; - - february -> - <<"February"/utf8>>; - - march -> - <<"March"/utf8>>; - - april -> - <<"April"/utf8>>; - - may -> - <<"May"/utf8>>; - - june -> - <<"June"/utf8>>; - - july -> - <<"July"/utf8>>; - - august -> - <<"August"/utf8>>; - - september -> - <<"September"/utf8>>; - - october -> - <<"October"/utf8>>; - - november -> - <<"November"/utf8>>; - - december -> - <<"December"/utf8>> - end. - --file("src/gleam/time/calendar.gleam", 188). -?DOC( - " Returns the number for the month, where January is 1 and December is 12.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " month_to_int(January)\n" - " // -> 1\n" - " ```\n" -). --spec month_to_int(month()) -> integer(). -month_to_int(Month) -> - case Month of - january -> - 1; - - february -> - 2; - - march -> - 3; - - april -> - 4; - - may -> - 5; - - june -> - 6; - - july -> - 7; - - august -> - 8; - - september -> - 9; - - october -> - 10; - - november -> - 11; - - december -> - 12 - end. - --file("src/gleam/time/calendar.gleam", 213). -?DOC( - " Returns the month for a given number, where January is 1 and December is 12.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " month_from_int(1)\n" - " // -> Ok(January)\n" - " ```\n" -). --spec month_from_int(integer()) -> {ok, month()} | {error, nil}. -month_from_int(Month) -> - case Month of - 1 -> - {ok, january}; - - 2 -> - {ok, february}; - - 3 -> - {ok, march}; - - 4 -> - {ok, april}; - - 5 -> - {ok, may}; - - 6 -> - {ok, june}; - - 7 -> - {ok, july}; - - 8 -> - {ok, august}; - - 9 -> - {ok, september}; - - 10 -> - {ok, october}; - - 11 -> - {ok, november}; - - 12 -> - {ok, december}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/calendar.gleam", 290). -?DOC( - " Determines if a given year is a leap year.\n" - "\n" - " A leap year occurs every 4 years, except for years divisible by 100,\n" - " unless they are also divisible by 400.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " is_leap_year(2024)\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_leap_year(2023)\n" - " // -> False\n" - " ```\n" -). --spec is_leap_year(integer()) -> boolean(). -is_leap_year(Year) -> - case (Year rem 400) =:= 0 of - true -> - true; - - false -> - case (Year rem 100) =:= 0 of - true -> - false; - - false -> - (Year rem 4) =:= 0 - end - end. - --file("src/gleam/time/calendar.gleam", 254). -?DOC( - " Checks if a given date is valid.\n" - "\n" - " This function properly accounts for leap years when validating February days.\n" - " A leap year occurs every 4 years, except for years divisible by 100,\n" - " unless they are also divisible by 400.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " is_valid_date(Date(2023, April, 15))\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_valid_date(Date(2023, April, 31))\n" - " // -> False\n" - " ```\n" - "\n" - " ```gleam\n" - " is_valid_date(Date(2024, February, 29))\n" - " // -> True (2024 is a leap year)\n" - " ```\n" -). --spec is_valid_date(date()) -> boolean(). -is_valid_date(Date) -> - {date, Year, Month, Day} = Date, - case Day < 1 of - true -> - false; - - false -> - case Month of - january -> - Day =< 31; - - march -> - Day =< 31; - - may -> - Day =< 31; - - july -> - Day =< 31; - - august -> - Day =< 31; - - october -> - Day =< 31; - - december -> - Day =< 31; - - april -> - Day =< 30; - - june -> - Day =< 30; - - september -> - Day =< 30; - - november -> - Day =< 30; - - february -> - Max_february_days = case is_leap_year(Year) of - true -> - 29; - - false -> - 28 - end, - Day =< Max_february_days - end - end. - --file("src/gleam/time/calendar.gleam", 313). -?DOC( - " Checks if a time of day is valid.\n" - "\n" - " Validates that hours are 0-23, minutes are 0-59, seconds are 0-59,\n" - " and nanoseconds are 0-999,999,999.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " is_valid_time_of_day(TimeOfDay(12, 30, 45, 123456789))\n" - " // -> True\n" - " ```\n" -). --spec is_valid_time_of_day(time_of_day()) -> boolean(). -is_valid_time_of_day(Time) -> - {time_of_day, Hours, Minutes, Seconds, Nanoseconds} = Time, - (((((((Hours >= 0) andalso (Hours =< 23)) andalso (Minutes >= 0)) andalso (Minutes - =< 59)) - andalso (Seconds >= 0)) - andalso (Seconds =< 59)) - andalso (Nanoseconds >= 0)) - andalso (Nanoseconds =< 999999999). - --file("src/gleam/time/calendar.gleam", 340). -?DOC( - " Naively compares two dates without any time zone information, returning an\n" - " order.\n" - "\n" - " ## Correctness\n" - "\n" - " This function compares dates without any time zone information, only using\n" - " the rules for the gregorian calendar. This is typically sufficient, but be\n" - " aware that in reality some time zones will change their calendar date\n" - " occasionally. This can result in days being skipped, out of order, or\n" - " happening multiple times.\n" - "\n" - " If you need real-world correct time ordering then use the\n" - " `gleam/time/timestamp` module instead.\n" -). --spec naive_date_compare(date(), date()) -> gleam@order:order(). -naive_date_compare(One, Other) -> - _pipe = gleam@int:compare(erlang:element(2, One), erlang:element(2, Other)), - _pipe@1 = gleam@order:lazy_break_tie( - _pipe, - fun() -> - gleam@int:compare( - month_to_int(erlang:element(3, One)), - month_to_int(erlang:element(3, Other)) - ) - end - ), - gleam@order:lazy_break_tie( - _pipe@1, - fun() -> - gleam@int:compare(erlang:element(4, One), erlang:element(4, Other)) - end - ). diff --git a/build/dev/javascript/gleam_time/gleam@time@duration.erl b/build/dev/javascript/gleam_time/gleam@time@duration.erl deleted file mode 100644 index 7ba7ad2..0000000 --- a/build/dev/javascript/gleam_time/gleam@time@duration.erl +++ /dev/null @@ -1,381 +0,0 @@ --module(gleam@time@duration). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/time/duration.gleam"). --export([approximate/1, compare/2, difference/2, add/2, seconds/1, minutes/1, hours/1, milliseconds/1, nanoseconds/1, to_seconds/1, to_seconds_and_nanoseconds/1, to_iso8601_string/1]). --export_type([duration/0, unit/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --opaque duration() :: {duration, integer(), integer()}. - --type unit() :: nanosecond | - microsecond | - millisecond | - second | - minute | - hour | - day | - week | - month | - year. - --file("src/gleam/time/duration.gleam", 110). -?DOC( - " Ensure the duration is represented with `nanoseconds` being positive and\n" - " less than 1 second.\n" - "\n" - " This function does not change the amount of time that the duratoin refers\n" - " to, it only adjusts the values used to represent the time.\n" -). --spec normalise(duration()) -> duration(). -normalise(Duration) -> - Multiplier = 1000000000, - Nanoseconds = case Multiplier of - 0 -> 0; - Gleam@denominator -> erlang:element(3, Duration) rem Gleam@denominator - end, - Overflow = erlang:element(3, Duration) - Nanoseconds, - Seconds = erlang:element(2, Duration) + (case Multiplier of - 0 -> 0; - Gleam@denominator@1 -> Overflow div Gleam@denominator@1 - end), - case Nanoseconds >= 0 of - true -> - {duration, Seconds, Nanoseconds}; - - false -> - {duration, Seconds - 1, Multiplier + Nanoseconds} - end. - --file("src/gleam/time/duration.gleam", 76). -?DOC( - " Convert a duration to a number of the largest number of a unit, serving as\n" - " a rough description of the duration that a human can understand.\n" - "\n" - " The size used for each unit are described in the documentation for the\n" - " `Unit` type.\n" - "\n" - " ```gleam\n" - " seconds(125)\n" - " |> approximate\n" - " // -> #(2, Minute)\n" - " ```\n" - "\n" - " This function rounds _towards zero_. This means that if a duration is just\n" - " short of 2 days then it will approximate to 1 day.\n" - "\n" - " ```gleam\n" - " hours(47)\n" - " |> approximate\n" - " // -> #(1, Day)\n" - " ```\n" -). --spec approximate(duration()) -> {integer(), unit()}. -approximate(Duration) -> - {duration, S, Ns} = Duration, - Minute = 60, - Hour = Minute * 60, - Day = Hour * 24, - Week = Day * 7, - Year = (Day * 365) + (Hour * 6), - Month = Year div 12, - Microsecond = 1000, - Millisecond = Microsecond * 1000, - case nil of - _ when S < 0 -> - {Amount, Unit} = begin - _pipe = {duration, - S, - Ns}, - _pipe@1 = normalise(_pipe), - approximate(_pipe@1) - end, - {- Amount, Unit}; - - _ when S >= Year -> - {case Year of - 0 -> 0; - Gleam@denominator -> S div Gleam@denominator - end, year}; - - _ when S >= Month -> - {case Month of - 0 -> 0; - Gleam@denominator@1 -> S div Gleam@denominator@1 - end, month}; - - _ when S >= Week -> - {case Week of - 0 -> 0; - Gleam@denominator@2 -> S div Gleam@denominator@2 - end, week}; - - _ when S >= Day -> - {case Day of - 0 -> 0; - Gleam@denominator@3 -> S div Gleam@denominator@3 - end, day}; - - _ when S >= Hour -> - {case Hour of - 0 -> 0; - Gleam@denominator@4 -> S div Gleam@denominator@4 - end, hour}; - - _ when S >= Minute -> - {case Minute of - 0 -> 0; - Gleam@denominator@5 -> S div Gleam@denominator@5 - end, minute}; - - _ when S > 0 -> - {S, second}; - - _ when Ns >= Millisecond -> - {case Millisecond of - 0 -> 0; - Gleam@denominator@6 -> Ns div Gleam@denominator@6 - end, millisecond}; - - _ when Ns >= Microsecond -> - {case Microsecond of - 0 -> 0; - Gleam@denominator@7 -> Ns div Gleam@denominator@7 - end, microsecond}; - - _ -> - {Ns, nanosecond} - end. - --file("src/gleam/time/duration.gleam", 140). -?DOC( - " Compare one duration to another, indicating whether the first spans a\n" - " larger amount of time (and so is greater) or smaller amount of time (and so\n" - " is lesser) than the second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " compare(seconds(1), seconds(2))\n" - " // -> order.Lt\n" - " ```\n" - "\n" - " Whether a duration is negative or positive doesn't matter for comparing\n" - " them, only the amount of time spanned matters.\n" - "\n" - " ```gleam\n" - " compare(seconds(-2), seconds(1))\n" - " // -> order.Gt\n" - " ```\n" -). --spec compare(duration(), duration()) -> gleam@order:order(). -compare(Left, Right) -> - Parts = fun(X) -> case erlang:element(2, X) >= 0 of - true -> - {erlang:element(2, X), erlang:element(3, X)}; - - false -> - {(erlang:element(2, X) * -1) - 1, - 1000000000 - erlang:element(3, X)} - end end, - {Ls, Lns} = Parts(Left), - {Rs, Rns} = Parts(Right), - _pipe = gleam@int:compare(Ls, Rs), - gleam@order:break_tie(_pipe, gleam@int:compare(Lns, Rns)). - --file("src/gleam/time/duration.gleam", 164). -?DOC( - " Calculate the difference between two durations.\n" - "\n" - " This is effectively substracting the first duration from the second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " difference(seconds(1), seconds(5))\n" - " // -> seconds(4)\n" - " ```\n" -). --spec difference(duration(), duration()) -> duration(). -difference(Left, Right) -> - _pipe = {duration, - erlang:element(2, Right) - erlang:element(2, Left), - erlang:element(3, Right) - erlang:element(3, Left)}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 178). -?DOC( - " Add two durations together.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " add(seconds(1), seconds(5))\n" - " // -> seconds(6)\n" - " ```\n" -). --spec add(duration(), duration()) -> duration(). -add(Left, Right) -> - _pipe = {duration, - erlang:element(2, Left) + erlang:element(2, Right), - erlang:element(3, Left) + erlang:element(3, Right)}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 225). --spec nanosecond_digits(integer(), integer(), binary()) -> binary(). -nanosecond_digits(N, Position, Acc) -> - case Position of - 9 -> - Acc; - - _ when (Acc =:= <<""/utf8>>) andalso ((N rem 10) =:= 0) -> - nanosecond_digits(N div 10, Position + 1, Acc); - - _ -> - Acc@1 = <<(erlang:integer_to_binary(N rem 10))/binary, Acc/binary>>, - nanosecond_digits(N div 10, Position + 1, Acc@1) - end. - --file("src/gleam/time/duration.gleam", 239). -?DOC(" Create a duration of a number of seconds.\n"). --spec seconds(integer()) -> duration(). -seconds(Amount) -> - {duration, Amount, 0}. - --file("src/gleam/time/duration.gleam", 244). -?DOC(" Create a duration of a number of minutes.\n"). --spec minutes(integer()) -> duration(). -minutes(Amount) -> - seconds(Amount * 60). - --file("src/gleam/time/duration.gleam", 249). -?DOC(" Create a duration of a number of hours.\n"). --spec hours(integer()) -> duration(). -hours(Amount) -> - seconds((Amount * 60) * 60). - --file("src/gleam/time/duration.gleam", 254). -?DOC(" Create a duration of a number of milliseconds.\n"). --spec milliseconds(integer()) -> duration(). -milliseconds(Amount) -> - Remainder = Amount rem 1000, - Overflow = Amount - Remainder, - Nanoseconds = Remainder * 1000000, - Seconds = Overflow div 1000, - _pipe = {duration, Seconds, Nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 273). -?DOC( - " Create a duration of a number of nanoseconds.\n" - "\n" - " # JavaScript int limitations\n" - "\n" - " Remember that JavaScript can only perfectly represent ints between positive\n" - " and negative 9,007,199,254,740,991! If you use a single call to this\n" - " function to create durations larger than that number of nanoseconds then\n" - " you will likely not get exactly the value you expect. Use `seconds` and\n" - " `milliseconds` as much as possible for large durations.\n" -). --spec nanoseconds(integer()) -> duration(). -nanoseconds(Amount) -> - _pipe = {duration, 0, Amount}, - normalise(_pipe). - --file("src/gleam/time/duration.gleam", 283). -?DOC( - " Convert the duration to a number of seconds.\n" - "\n" - " There may be some small loss of precision due to `Duration` being\n" - " nanosecond accurate and `Float` not being able to represent this.\n" -). --spec to_seconds(duration()) -> float(). -to_seconds(Duration) -> - Seconds = erlang:float(erlang:element(2, Duration)), - Nanoseconds = erlang:float(erlang:element(3, Duration)), - Seconds + (Nanoseconds / 1000000000.0). - --file("src/gleam/time/duration.gleam", 292). -?DOC( - " Convert the duration to a number of seconds and nanoseconds. There is no\n" - " loss of precision with this conversion on any target.\n" -). --spec to_seconds_and_nanoseconds(duration()) -> {integer(), integer()}. -to_seconds_and_nanoseconds(Duration) -> - {erlang:element(2, Duration), erlang:element(3, Duration)}. - --file("src/gleam/time/duration.gleam", 192). -?DOC( - " Convert the duration to an [ISO8601][1] formatted duration string.\n" - "\n" - " The ISO8601 duration format is ambiguous without context due to months and\n" - " years having different lengths, and because of leap seconds. This function\n" - " encodes the duration as days, hours, and seconds without any leap seconds.\n" - " Be sure to take this into account when using the duration strings.\n" - "\n" - " [1]: https://en.wikipedia.org/wiki/ISO_8601#Durations\n" -). --spec to_iso8601_string(duration()) -> binary(). -to_iso8601_string(Duration) -> - gleam@bool:guard( - Duration =:= {duration, 0, 0}, - <<"PT0S"/utf8>>, - fun() -> - Split = fun(Total, Limit) -> - Amount = case Limit of - 0 -> 0; - Gleam@denominator -> Total rem Gleam@denominator - end, - Remainder = case Limit of - 0 -> 0; - Gleam@denominator@1 -> (Total - Amount) div Gleam@denominator@1 - end, - {Amount, Remainder} - end, - {Seconds, Rest} = Split(erlang:element(2, Duration), 60), - {Minutes, Rest@1} = Split(Rest, 60), - {Hours, Rest@2} = Split(Rest@1, 24), - Days = Rest@2, - Add = fun(Out, Value, Unit) -> case Value of - 0 -> - Out; - - _ -> - <<<>/binary, - Unit/binary>> - end end, - Output = begin - _pipe = <<"P"/utf8>>, - _pipe@1 = Add(_pipe, Days, <<"D"/utf8>>), - _pipe@2 = gleam@string:append(_pipe@1, <<"T"/utf8>>), - _pipe@3 = Add(_pipe@2, Hours, <<"H"/utf8>>), - Add(_pipe@3, Minutes, <<"M"/utf8>>) - end, - case {Seconds, erlang:element(3, Duration)} of - {0, 0} -> - Output; - - {_, 0} -> - <<<>/binary, - "S"/utf8>>; - - {_, _} -> - F = nanosecond_digits( - erlang:element(3, Duration), - 0, - <<""/utf8>> - ), - <<<<<<<>/binary, - "."/utf8>>/binary, - F/binary>>/binary, - "S"/utf8>> - end - end - ). diff --git a/build/dev/javascript/gleam_time/gleam@time@timestamp.erl b/build/dev/javascript/gleam_time/gleam@time@timestamp.erl deleted file mode 100644 index 0d7413a..0000000 --- a/build/dev/javascript/gleam_time/gleam@time@timestamp.erl +++ /dev/null @@ -1,1188 +0,0 @@ --module(gleam@time@timestamp). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/time/timestamp.gleam"). --export([compare/2, system_time/0, difference/2, add/2, to_calendar/2, to_rfc3339/2, from_unix_seconds/1, from_unix_seconds_and_nanoseconds/2, to_unix_seconds/1, to_unix_seconds_and_nanoseconds/1, from_calendar/3, parse_rfc3339/1]). --export_type([timestamp/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Welcome to the timestamp module! This module and its `Timestamp` type are\n" - " what you will be using most commonly when working with time in Gleam.\n" - "\n" - " A timestamp represents a moment in time, represented as an amount of time\n" - " since the calendar time 00:00:00 UTC on 1 January 1970, also known as the\n" - " _Unix epoch_.\n" - "\n" - " # Wall clock time and monotonicity\n" - "\n" - " Time is very complicated, especially on computers! While they generally do\n" - " a good job of keeping track of what the time is, computers can get\n" - " out-of-sync and start to report a time that is too late or too early. Most\n" - " computers use \"network time protocol\" to tell each other what they think\n" - " the time is, and computers that realise they are running too fast or too\n" - " slow will adjust their clock to correct it. When this happens it can seem\n" - " to your program that the current time has changed, and it may have even\n" - " jumped backwards in time!\n" - "\n" - " This measure of time is called _wall clock time_, and it is what people\n" - " commonly think of when they think of time. It is important to be aware that\n" - " it can go backwards, and your program must not rely on it only ever going\n" - " forwards at a steady rate. For example, for tracking what order events happen\n" - " in. \n" - "\n" - " This module uses wall clock time. If your program needs time values to always\n" - " increase you will need a _monotonic_ time instead. It's uncommon that you\n" - " would need monotonic time, one example might be if you're making a\n" - " benchmarking framework.\n" - "\n" - " The exact way that time works will depend on what runtime you use. The\n" - " Erlang documentation on time has a lot of detail about time generally as well\n" - " as how it works on the BEAM, it is worth reading.\n" - " .\n" - "\n" - " # Converting to local calendar time\n" - "\n" - " Timestamps don't take into account time zones, so a moment in time will\n" - " have the same timestamp value regardless of where you are in the world. To\n" - " convert them to local time you will need to know the offset for the time\n" - " zone you wish to use, likely from a time zone database. See the\n" - " `gleam/time/calendar` module for more information.\n" - "\n" -). - --opaque timestamp() :: {timestamp, integer(), integer()}. - --file("src/gleam/time/timestamp.gleam", 119). -?DOC( - " Ensure the time is represented with `nanoseconds` being positive and less\n" - " than 1 second.\n" - "\n" - " This function does not change the time that the timestamp refers to, it\n" - " only adjusts the values used to represent the time.\n" -). --spec normalise(timestamp()) -> timestamp(). -normalise(Timestamp) -> - Multiplier = 1000000000, - Nanoseconds = case Multiplier of - 0 -> 0; - Gleam@denominator -> erlang:element(3, Timestamp) rem Gleam@denominator - end, - Overflow = erlang:element(3, Timestamp) - Nanoseconds, - Seconds = erlang:element(2, Timestamp) + (case Multiplier of - 0 -> 0; - Gleam@denominator@1 -> Overflow div Gleam@denominator@1 - end), - case Nanoseconds >= 0 of - true -> - {timestamp, Seconds, Nanoseconds}; - - false -> - {timestamp, Seconds - 1, Multiplier + Nanoseconds} - end. - --file("src/gleam/time/timestamp.gleam", 141). -?DOC( - " Compare one timestamp to another, indicating whether the first is further\n" - " into the future (greater) or further into the past (lesser) than the\n" - " second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " compare(from_unix_seconds(1), from_unix_seconds(2))\n" - " // -> order.Lt\n" - " ```\n" -). --spec compare(timestamp(), timestamp()) -> gleam@order:order(). -compare(Left, Right) -> - gleam@order:break_tie( - gleam@int:compare(erlang:element(2, Left), erlang:element(2, Right)), - gleam@int:compare(erlang:element(3, Left), erlang:element(3, Right)) - ). - --file("src/gleam/time/timestamp.gleam", 160). -?DOC( - " Get the current system time.\n" - "\n" - " Note this time is not unique or monotonic, it could change at any time or\n" - " even go backwards! The exact behaviour will depend on the runtime used. See\n" - " the module documentation for more information.\n" - "\n" - " On Erlang this uses [`erlang:system_time/1`][1]. On JavaScript this uses\n" - " [`Date.now`][2].\n" - "\n" - " [1]: https://www.erlang.org/doc/apps/erts/erlang#system_time/1\n" - " [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now\n" -). --spec system_time() -> timestamp(). -system_time() -> - {Seconds, Nanoseconds} = gleam_time_ffi:system_time(), - normalise({timestamp, Seconds, Nanoseconds}). - --file("src/gleam/time/timestamp.gleam", 180). -?DOC( - " Calculate the difference between two timestamps.\n" - "\n" - " This is effectively substracting the first timestamp from the second.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " difference(from_unix_seconds(1), from_unix_seconds(5))\n" - " // -> duration.seconds(4)\n" - " ```\n" -). --spec difference(timestamp(), timestamp()) -> gleam@time@duration:duration(). -difference(Left, Right) -> - Seconds = gleam@time@duration:seconds( - erlang:element(2, Right) - erlang:element(2, Left) - ), - Nanoseconds = gleam@time@duration:nanoseconds( - erlang:element(3, Right) - erlang:element(3, Left) - ), - gleam@time@duration:add(Seconds, Nanoseconds). - --file("src/gleam/time/timestamp.gleam", 195). -?DOC( - " Add a duration to a timestamp.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " add(from_unix_seconds(1000), duration.seconds(5))\n" - " // -> from_unix_seconds(1005)\n" - " ```\n" -). --spec add(timestamp(), gleam@time@duration:duration()) -> timestamp(). -add(Timestamp, Duration) -> - {Seconds, Nanoseconds} = gleam@time@duration:to_seconds_and_nanoseconds( - Duration - ), - _pipe = {timestamp, - erlang:element(2, Timestamp) + Seconds, - erlang:element(3, Timestamp) + Nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/timestamp.gleam", 262). --spec pad_digit(integer(), integer()) -> binary(). -pad_digit(Digit, Desired_length) -> - _pipe = erlang:integer_to_binary(Digit), - gleam@string:pad_start(_pipe, Desired_length, <<"0"/utf8>>). - --file("src/gleam/time/timestamp.gleam", 308). --spec duration_to_minutes(gleam@time@duration:duration()) -> integer(). -duration_to_minutes(Duration) -> - erlang:round(gleam@time@duration:to_seconds(Duration) / 60.0). - --file("src/gleam/time/timestamp.gleam", 370). --spec modulo(integer(), integer()) -> integer(). -modulo(N, M) -> - case gleam@int:modulo(N, M) of - {ok, N@1} -> - N@1; - - {error, _} -> - 0 - end. - --file("src/gleam/time/timestamp.gleam", 377). --spec floored_div(integer(), float()) -> integer(). -floored_div(Numerator, Denominator) -> - N = case Denominator of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> erlang:float(Numerator) / Gleam@denominator - end, - erlang:round(math:floor(N)). - --file("src/gleam/time/timestamp.gleam", 383). --spec to_civil(integer()) -> {integer(), integer(), integer()}. -to_civil(Minutes) -> - Raw_day = floored_div(Minutes, (60.0 * 24.0)) + 719468, - Era = case Raw_day >= 0 of - true -> - Raw_day div 146097; - - false -> - (Raw_day - 146096) div 146097 - end, - Day_of_era = Raw_day - (Era * 146097), - Year_of_era = (((Day_of_era - (Day_of_era div 1460)) + (Day_of_era div 36524)) - - (Day_of_era div 146096)) - div 365, - Year = Year_of_era + (Era * 400), - Day_of_year = Day_of_era - (((365 * Year_of_era) + (Year_of_era div 4)) - (Year_of_era - div 100)), - Mp = ((5 * Day_of_year) + 2) div 153, - Month = case Mp < 10 of - true -> - Mp + 3; - - false -> - Mp - 9 - end, - Day = (Day_of_year - (((153 * Mp) + 2) div 5)) + 1, - Year@1 = case Month =< 2 of - true -> - Year + 1; - - false -> - Year - end, - {Year@1, Month, Day}. - --file("src/gleam/time/timestamp.gleam", 312). --spec to_calendar_from_offset(timestamp(), integer()) -> {integer(), - integer(), - integer(), - integer(), - integer(), - integer()}. -to_calendar_from_offset(Timestamp, Offset) -> - Total = erlang:element(2, Timestamp) + (Offset * 60), - Seconds = modulo(Total, 60), - Total_minutes = floored_div(Total, 60.0), - Minutes = modulo(Total, 60 * 60) div 60, - Hours = case (60 * 60) of - 0 -> 0; - Gleam@denominator -> modulo(Total, (24 * 60) * 60) div Gleam@denominator - end, - {Year, Month, Day} = to_civil(Total_minutes), - {Year, Month, Day, Hours, Minutes, Seconds}. - --file("src/gleam/time/timestamp.gleam", 281). -?DOC( - " Convert a `Timestamp` to calendar time, suitable for presenting to a human\n" - " to read.\n" - "\n" - " If you want a machine to use the time value then you should not use this\n" - " function and should instead keep it as a timestamp. See the documentation\n" - " for the `gleam/time/calendar` module for more information.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " timestamp.from_unix_seconds(0)\n" - " |> timestamp.to_calendar(calendar.utc_offset)\n" - " // -> #(Date(1970, January, 1), TimeOfDay(0, 0, 0, 0))\n" - " ```\n" -). --spec to_calendar(timestamp(), gleam@time@duration:duration()) -> {gleam@time@calendar:date(), - gleam@time@calendar:time_of_day()}. -to_calendar(Timestamp, Offset) -> - Offset@1 = duration_to_minutes(Offset), - {Year, Month, Day, Hours, Minutes, Seconds} = to_calendar_from_offset( - Timestamp, - Offset@1 - ), - Month@1 = case Month of - 1 -> - january; - - 2 -> - february; - - 3 -> - march; - - 4 -> - april; - - 5 -> - may; - - 6 -> - june; - - 7 -> - july; - - 8 -> - august; - - 9 -> - september; - - 10 -> - october; - - 11 -> - november; - - _ -> - december - end, - Nanoseconds = erlang:element(3, Timestamp), - Date = {date, Year, Month@1, Day}, - Time = {time_of_day, Hours, Minutes, Seconds, Nanoseconds}, - {Date, Time}. - --file("src/gleam/time/timestamp.gleam", 446). --spec do_remove_trailing_zeros(list(integer())) -> list(integer()). -do_remove_trailing_zeros(Reversed_digits) -> - case Reversed_digits of - [] -> - []; - - [Digit | Digits] when Digit =:= 0 -> - do_remove_trailing_zeros(Digits); - - Reversed_digits@1 -> - lists:reverse(Reversed_digits@1) - end. - --file("src/gleam/time/timestamp.gleam", 440). -?DOC(" Given a list of digits, return new list with any trailing zeros removed.\n"). --spec remove_trailing_zeros(list(integer())) -> list(integer()). -remove_trailing_zeros(Digits) -> - Reversed_digits = lists:reverse(Digits), - do_remove_trailing_zeros(Reversed_digits). - --file("src/gleam/time/timestamp.gleam", 461). --spec do_get_zero_padded_digits(integer(), list(integer()), integer()) -> list(integer()). -do_get_zero_padded_digits(Number, Digits, Count) -> - case Number of - Number@1 when (Number@1 =< 0) andalso (Count >= 9) -> - Digits; - - Number@2 when Number@2 =< 0 -> - do_get_zero_padded_digits(Number@2, [0 | Digits], Count + 1); - - Number@3 -> - Digit = Number@3 rem 10, - Number@4 = floored_div(Number@3, 10.0), - do_get_zero_padded_digits(Number@4, [Digit | Digits], Count + 1) - end. - --file("src/gleam/time/timestamp.gleam", 457). -?DOC( - " Returns the list of digits of `number`. If the number of digits is less \n" - " than 9, the result is zero-padded at the front.\n" -). --spec get_zero_padded_digits(integer()) -> list(integer()). -get_zero_padded_digits(Number) -> - do_get_zero_padded_digits(Number, [], 0). - --file("src/gleam/time/timestamp.gleam", 420). -?DOC( - " Converts nanoseconds into a `String` representation of fractional seconds.\n" - " \n" - " Assumes that `nanoseconds < 1_000_000_000`, which will be true for any \n" - " normalised timestamp.\n" -). --spec show_second_fraction(integer()) -> binary(). -show_second_fraction(Nanoseconds) -> - case gleam@int:compare(Nanoseconds, 0) of - lt -> - <<""/utf8>>; - - eq -> - <<""/utf8>>; - - gt -> - Second_fraction_part = begin - _pipe = Nanoseconds, - _pipe@1 = get_zero_padded_digits(_pipe), - _pipe@2 = remove_trailing_zeros(_pipe@1), - _pipe@3 = gleam@list:map( - _pipe@2, - fun erlang:integer_to_binary/1 - ), - gleam@string:join(_pipe@3, <<""/utf8>>) - end, - <<"."/utf8, Second_fraction_part/binary>> - end. - --file("src/gleam/time/timestamp.gleam", 240). -?DOC( - " Convert a timestamp to a RFC 3339 formatted time string, with an offset\n" - " supplied as an additional argument.\n" - "\n" - " The output of this function is also ISO 8601 compatible so long as the\n" - " offset not negative. Offsets have at-most minute precision, so an offset\n" - " with higher precision will be rounded to the nearest minute.\n" - "\n" - " If you are making an API such as a HTTP JSON API you are encouraged to use\n" - " Unix timestamps instead of this format or ISO 8601. Unix timestamps are a\n" - " better choice as they don't contain offset information. Consider:\n" - "\n" - " - UTC offsets are not time zones. This does not and cannot tell us the time\n" - " zone in which the date was recorded. So what are we supposed to do with\n" - " this information?\n" - " - Users typically want dates formatted according to their local time zone.\n" - " What if the provided UTC offset is different from the current user's time\n" - " zone? What are we supposed to do with it then?\n" - " - Despite it being useless (or worse, a source of bugs), the UTC offset\n" - " creates a larger payload to transfer.\n" - "\n" - " They also uses more memory than a unix timestamp. The way they are better\n" - " than Unix timestamp is that it is easier for a human to read them, but\n" - " this is a hinderance that tooling can remedy, and APIs are not primarily\n" - " for humans.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " timestamp.from_unix_seconds_and_nanoseconds(1000, 123_000_000)\n" - " |> to_rfc3339(calendar.utc_offset)\n" - " // -> \"1970-01-01T00:16:40.123Z\"\n" - " ```\n" - "\n" - " ```gleam\n" - " timestamp.from_unix_seconds(1000)\n" - " |> to_rfc3339(duration.seconds(3600))\n" - " // -> \"1970-01-01T01:16:40+01:00\"\n" - " ```\n" -). --spec to_rfc3339(timestamp(), gleam@time@duration:duration()) -> binary(). -to_rfc3339(Timestamp, Offset) -> - Offset@1 = duration_to_minutes(Offset), - {Years, Months, Days, Hours, Minutes, Seconds} = to_calendar_from_offset( - Timestamp, - Offset@1 - ), - Offset_minutes = modulo(Offset@1, 60), - Offset_hours = gleam@int:absolute_value(floored_div(Offset@1, 60.0)), - N2 = fun(_capture) -> pad_digit(_capture, 2) end, - N4 = fun(_capture@1) -> pad_digit(_capture@1, 4) end, - Out = <<""/utf8>>, - Out@1 = <<<<<<<<<>/binary, "-"/utf8>>/binary, - (N2(Months))/binary>>/binary, - "-"/utf8>>/binary, - (N2(Days))/binary>>, - Out@2 = <>, - Out@3 = <<<<<<<<<>/binary, ":"/utf8>>/binary, - (N2(Minutes))/binary>>/binary, - ":"/utf8>>/binary, - (N2(Seconds))/binary>>, - Out@4 = <>, - case gleam@int:compare(Offset@1, 0) of - eq -> - <>; - - gt -> - <<<<<<<>/binary, (N2(Offset_hours))/binary>>/binary, - ":"/utf8>>/binary, - (N2(Offset_minutes))/binary>>; - - lt -> - <<<<<<<>/binary, (N2(Offset_hours))/binary>>/binary, - ":"/utf8>>/binary, - (N2(Offset_minutes))/binary>> - end. - --file("src/gleam/time/timestamp.gleam", 611). --spec is_leap_year(integer()) -> boolean(). -is_leap_year(Year) -> - ((Year rem 4) =:= 0) andalso (((Year rem 100) /= 0) orelse ((Year rem 400) - =:= 0)). - --file("src/gleam/time/timestamp.gleam", 715). --spec parse_sign(bitstring()) -> {ok, {binary(), bitstring()}} | {error, nil}. -parse_sign(Bytes) -> - case Bytes of - <<"+"/utf8, Remaining_bytes/binary>> -> - {ok, {<<"+"/utf8>>, Remaining_bytes}}; - - <<"-"/utf8, Remaining_bytes@1/binary>> -> - {ok, {<<"-"/utf8>>, Remaining_bytes@1}}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 762). -?DOC(" Accept the given value from `bytes` and move past it if found.\n"). --spec accept_byte(bitstring(), integer()) -> {ok, bitstring()} | {error, nil}. -accept_byte(Bytes, Value) -> - case Bytes of - <> when Byte =:= Value -> - {ok, Remaining_bytes}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 780). --spec accept_empty(bitstring()) -> {ok, nil} | {error, nil}. -accept_empty(Bytes) -> - case Bytes of - <<>> -> - {ok, nil}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 840). -?DOC( - " Note: It is the callers responsibility to ensure the inputs are valid.\n" - " \n" - " See https://www.tondering.dk/claus/cal/julperiod.php#formula\n" -). --spec julian_day_from_ymd(integer(), integer(), integer()) -> integer(). -julian_day_from_ymd(Year, Month, Day) -> - Adjustment = (14 - Month) div 12, - Adjusted_year = (Year + 4800) - Adjustment, - Adjusted_month = (Month + (12 * Adjustment)) - 3, - (((((Day + (((153 * Adjusted_month) + 2) div 5)) + (365 * Adjusted_year)) + (Adjusted_year - div 4)) - - (Adjusted_year div 100)) - + (Adjusted_year div 400)) - - 32045. - --file("src/gleam/time/timestamp.gleam", 859). -?DOC( - " Create a timestamp from a number of seconds since 00:00:00 UTC on 1 January\n" - " 1970.\n" -). --spec from_unix_seconds(integer()) -> timestamp(). -from_unix_seconds(Seconds) -> - {timestamp, Seconds, 0}. - --file("src/gleam/time/timestamp.gleam", 874). -?DOC( - " Create a timestamp from a number of seconds and nanoseconds since 00:00:00\n" - " UTC on 1 January 1970.\n" - "\n" - " # JavaScript int limitations\n" - "\n" - " Remember that JavaScript can only perfectly represent ints between positive\n" - " and negative 9,007,199,254,740,991! If you only use the nanosecond field\n" - " then you will almost certainly not get the date value you want due to this\n" - " loss of precision. Always use seconds primarily and then use nanoseconds\n" - " for the final sub-second adjustment.\n" -). --spec from_unix_seconds_and_nanoseconds(integer(), integer()) -> timestamp(). -from_unix_seconds_and_nanoseconds(Seconds, Nanoseconds) -> - _pipe = {timestamp, Seconds, Nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/timestamp.gleam", 888). -?DOC( - " Convert the timestamp to a number of seconds since 00:00:00 UTC on 1\n" - " January 1970.\n" - "\n" - " There may be some small loss of precision due to `Timestamp` being\n" - " nanosecond accurate and `Float` not being able to represent this.\n" -). --spec to_unix_seconds(timestamp()) -> float(). -to_unix_seconds(Timestamp) -> - Seconds = erlang:float(erlang:element(2, Timestamp)), - Nanoseconds = erlang:float(erlang:element(3, Timestamp)), - Seconds + (Nanoseconds / 1000000000.0). - --file("src/gleam/time/timestamp.gleam", 897). -?DOC( - " Convert the timestamp to a number of seconds and nanoseconds since 00:00:00\n" - " UTC on 1 January 1970. There is no loss of precision with this conversion\n" - " on any target.\n" -). --spec to_unix_seconds_and_nanoseconds(timestamp()) -> {integer(), integer()}. -to_unix_seconds_and_nanoseconds(Timestamp) -> - {erlang:element(2, Timestamp), erlang:element(3, Timestamp)}. - --file("src/gleam/time/timestamp.gleam", 723). --spec offset_to_seconds(binary(), integer(), integer()) -> integer(). -offset_to_seconds(Sign, Hours, Minutes) -> - Abs_seconds = (Hours * 3600) + (Minutes * 60), - case Sign of - <<"-"/utf8>> -> - - Abs_seconds; - - _ -> - Abs_seconds - end. - --file("src/gleam/time/timestamp.gleam", 819). -?DOC( - " `julian_seconds_from_parts(year, month, day, hours, minutes, seconds)` \n" - " returns the number of Julian \n" - " seconds represented by the given arguments.\n" - " \n" - " Note: It is the callers responsibility to ensure the inputs are valid.\n" - " \n" - " See https://www.tondering.dk/claus/cal/julperiod.php#formula\n" -). --spec julian_seconds_from_parts( - integer(), - integer(), - integer(), - integer(), - integer(), - integer() -) -> integer(). -julian_seconds_from_parts(Year, Month, Day, Hours, Minutes, Seconds) -> - Julian_day_seconds = julian_day_from_ymd(Year, Month, Day) * 86400, - ((Julian_day_seconds + (Hours * 3600)) + (Minutes * 60)) + Seconds. - --file("src/gleam/time/timestamp.gleam", 662). --spec do_parse_second_fraction_as_nanoseconds(bitstring(), integer(), integer()) -> {ok, - {integer(), bitstring()}} | - {error, any()}. -do_parse_second_fraction_as_nanoseconds(Bytes, Acc, Power) -> - Power@1 = Power div 10, - case Bytes of - <> when ((16#30 =< Byte) andalso (Byte =< 16#39)) andalso (Power@1 < 1) -> - do_parse_second_fraction_as_nanoseconds( - Remaining_bytes, - Acc, - Power@1 - ); - - <> when (16#30 =< Byte@1) andalso (Byte@1 =< 16#39) -> - Digit = Byte@1 - 16#30, - do_parse_second_fraction_as_nanoseconds( - Remaining_bytes@1, - Acc + (Digit * Power@1), - Power@1 - ); - - _ -> - {ok, {Acc, Bytes}} - end. - --file("src/gleam/time/timestamp.gleam", 642). --spec parse_second_fraction_as_nanoseconds(bitstring()) -> {ok, - {integer(), bitstring()}} | - {error, nil}. -parse_second_fraction_as_nanoseconds(Bytes) -> - case Bytes of - <<"."/utf8, Byte, Remaining_bytes/binary>> when (16#30 =< Byte) andalso (Byte =< 16#39) -> - do_parse_second_fraction_as_nanoseconds( - <>, - 0, - 1000000000 - ); - - <<"."/utf8, _/binary>> -> - {error, nil}; - - _ -> - {ok, {0, Bytes}} - end. - --file("src/gleam/time/timestamp.gleam", 741). --spec do_parse_digits(bitstring(), integer(), integer(), integer()) -> {ok, - {integer(), bitstring()}} | - {error, nil}. -do_parse_digits(Bytes, Count, Acc, K) -> - case Bytes of - _ when K >= Count -> - {ok, {Acc, Bytes}}; - - <> when (16#30 =< Byte) andalso (Byte =< 16#39) -> - do_parse_digits( - Remaining_bytes, - Count, - (Acc * 10) + (Byte - 16#30), - K + 1 - ); - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 734). -?DOC(" Parse and return the given number of digits from the given bytes.\n"). --spec parse_digits(bitstring(), integer()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_digits(Bytes, Count) -> - do_parse_digits(Bytes, Count, 0, 0). - --file("src/gleam/time/timestamp.gleam", 573). --spec parse_year(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_year(Bytes) -> - parse_digits(Bytes, 4). - --file("src/gleam/time/timestamp.gleam", 577). --spec parse_month(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_month(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Month, Bytes@1} = _use0, - case (1 =< Month) andalso (Month =< 12) of - true -> - {ok, {Month, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 585). --spec parse_day(bitstring(), integer(), integer()) -> {ok, - {integer(), bitstring()}} | - {error, nil}. -parse_day(Bytes, Year, Month) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Day, Bytes@1} = _use0, - gleam@result:'try'(case Month of - 1 -> - {ok, 31}; - - 3 -> - {ok, 31}; - - 5 -> - {ok, 31}; - - 7 -> - {ok, 31}; - - 8 -> - {ok, 31}; - - 10 -> - {ok, 31}; - - 12 -> - {ok, 31}; - - 4 -> - {ok, 30}; - - 6 -> - {ok, 30}; - - 9 -> - {ok, 30}; - - 11 -> - {ok, 30}; - - 2 -> - case is_leap_year(Year) of - true -> - {ok, 29}; - - false -> - {ok, 28} - end; - - _ -> - {error, nil} - end, fun(Max_day) -> case (1 =< Day) andalso (Day =< Max_day) of - true -> - {ok, {Day, Bytes@1}}; - - false -> - {error, nil} - end end) - end - ). - --file("src/gleam/time/timestamp.gleam", 615). --spec parse_hours(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_hours(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Hours, Bytes@1} = _use0, - case (0 =< Hours) andalso (Hours =< 23) of - true -> - {ok, {Hours, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 623). --spec parse_minutes(bitstring()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_minutes(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Minutes, Bytes@1} = _use0, - case (0 =< Minutes) andalso (Minutes =< 59) of - true -> - {ok, {Minutes, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 631). --spec parse_seconds(bitstring()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_seconds(Bytes) -> - gleam@result:'try'( - parse_digits(Bytes, 2), - fun(_use0) -> - {Seconds, Bytes@1} = _use0, - case (0 =< Seconds) andalso (Seconds =< 60) of - true -> - {ok, {Seconds, Bytes@1}}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/time/timestamp.gleam", 704). --spec parse_numeric_offset(bitstring()) -> {ok, {integer(), bitstring()}} | - {error, nil}. -parse_numeric_offset(Bytes) -> - gleam@result:'try'( - parse_sign(Bytes), - fun(_use0) -> - {Sign, Bytes@1} = _use0, - gleam@result:'try'( - parse_hours(Bytes@1), - fun(_use0@1) -> - {Hours, Bytes@2} = _use0@1, - gleam@result:'try'( - accept_byte(Bytes@2, 16#3A), - fun(Bytes@3) -> - gleam@result:'try'( - parse_minutes(Bytes@3), - fun(_use0@2) -> - {Minutes, Bytes@4} = _use0@2, - Offset_seconds = offset_to_seconds( - Sign, - Hours, - Minutes - ), - {ok, {Offset_seconds, Bytes@4}} - end - ) - end - ) - end - ) - end - ). - --file("src/gleam/time/timestamp.gleam", 696). --spec parse_offset(bitstring()) -> {ok, {integer(), bitstring()}} | {error, nil}. -parse_offset(Bytes) -> - case Bytes of - <<"Z"/utf8, Remaining_bytes/binary>> -> - {ok, {0, Remaining_bytes}}; - - <<"z"/utf8, Remaining_bytes/binary>> -> - {ok, {0, Remaining_bytes}}; - - _ -> - parse_numeric_offset(Bytes) - end. - --file("src/gleam/time/timestamp.gleam", 769). --spec accept_date_time_separator(bitstring()) -> {ok, bitstring()} | - {error, nil}. -accept_date_time_separator(Bytes) -> - case Bytes of - <> when ((Byte =:= 16#54) orelse (Byte =:= 16#74)) orelse (Byte =:= 16#20) -> - {ok, Remaining_bytes}; - - _ -> - {error, nil} - end. - --file("src/gleam/time/timestamp.gleam", 789). -?DOC(" Note: The caller of this function must ensure that all inputs are valid.\n"). --spec from_date_time( - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer() -) -> timestamp(). -from_date_time( - Year, - Month, - Day, - Hours, - Minutes, - Seconds, - Second_fraction_as_nanoseconds, - Offset_seconds -) -> - Julian_seconds = julian_seconds_from_parts( - Year, - Month, - Day, - Hours, - Minutes, - Seconds - ), - Julian_seconds_since_epoch = Julian_seconds - 210866803200, - _pipe = {timestamp, - Julian_seconds_since_epoch - Offset_seconds, - Second_fraction_as_nanoseconds}, - normalise(_pipe). - --file("src/gleam/time/timestamp.gleam", 339). -?DOC( - " Create a `Timestamp` from a human-readable calendar time.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " timestamp.from_calendar(\n" - " date: calendar.Date(2024, calendar.December, 25),\n" - " time: calendar.TimeOfDay(12, 30, 50, 0),\n" - " offset: calendar.utc_offset,\n" - " )\n" - " |> timestamp.to_rfc3339(calendar.utc_offset)\n" - " // -> \"2024-12-25T12:30:50Z\"\n" - " ```\n" -). --spec from_calendar( - gleam@time@calendar:date(), - gleam@time@calendar:time_of_day(), - gleam@time@duration:duration() -) -> timestamp(). -from_calendar(Date, Time, Offset) -> - Month = case erlang:element(3, Date) of - january -> - 1; - - february -> - 2; - - march -> - 3; - - april -> - 4; - - may -> - 5; - - june -> - 6; - - july -> - 7; - - august -> - 8; - - september -> - 9; - - october -> - 10; - - november -> - 11; - - december -> - 12 - end, - from_date_time( - erlang:element(2, Date), - Month, - erlang:element(4, Date), - erlang:element(2, Time), - erlang:element(3, Time), - erlang:element(4, Time), - erlang:element(5, Time), - erlang:round(gleam@time@duration:to_seconds(Offset)) - ). - --file("src/gleam/time/timestamp.gleam", 533). -?DOC( - " Parses an [RFC 3339 formatted time string][spec] into a `Timestamp`.\n" - "\n" - " [spec]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6\n" - " \n" - " # Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(ts) = timestamp.parse_rfc3339(\"1970-01-01T00:00:01Z\")\n" - " timestamp.to_unix_seconds_and_nanoseconds(ts)\n" - " // -> #(1, 0)\n" - " ```\n" - " \n" - " Parsing an invalid timestamp returns an error.\n" - " \n" - " ```gleam\n" - " let assert Error(Nil) = timestamp.parse_rfc3339(\"1995-10-31\")\n" - " ```\n" - "\n" - " ## Time zones\n" - "\n" - " It may at first seem that the RFC 3339 format includes timezone\n" - " information, as it can specify an offset such as `Z` or `+3`, so why does\n" - " this function not return calendar time with a time zone? There are multiple\n" - " reasons:\n" - "\n" - " - RFC 3339's timestamp format is based on calendar time, but it is\n" - " unambigous, so it can be converted into epoch time when being parsed. It\n" - " is always better to internally use epoch time to represent unambiguous\n" - " points in time, so we perform that conversion as a convenience and to\n" - " ensure that programmers with less time experience don't accidentally use\n" - " a less suitable time representation.\n" - "\n" - " - RFC 3339's contains _calendar time offset_ information, not time zone\n" - " information. This is enough to convert it to an unambiguous timestamp,\n" - " but it is not enough information to reliably work with calendar time.\n" - " Without the time zone and the time zone database it's not possible to\n" - " know what time period that offset is valid for, so it cannot be used\n" - " without risk of bugs.\n" - "\n" - " ## Behaviour details\n" - " \n" - " - Follows the grammar specified in section 5.6 Internet Date/Time Format of \n" - " RFC 3339 .\n" - " - The `T` and `Z` characters may alternatively be lower case `t` or `z`, \n" - " respectively.\n" - " - Full dates and full times must be separated by `T` or `t`. A space is also \n" - " permitted.\n" - " - Leap seconds rules are not considered. That is, any timestamp may \n" - " specify digts `00` - `60` for the seconds.\n" - " - Any part of a fractional second that cannot be represented in the \n" - " nanosecond precision is tructated. That is, for the time string, \n" - " `\"1970-01-01T00:00:00.1234567899Z\"`, the fractional second `.1234567899` \n" - " will be represented as `123_456_789` in the `Timestamp`.\n" -). --spec parse_rfc3339(binary()) -> {ok, timestamp()} | {error, nil}. -parse_rfc3339(Input) -> - Bytes = gleam_stdlib:identity(Input), - gleam@result:'try'( - parse_year(Bytes), - fun(_use0) -> - {Year, Bytes@1} = _use0, - gleam@result:'try'( - accept_byte(Bytes@1, 16#2D), - fun(Bytes@2) -> - gleam@result:'try'( - parse_month(Bytes@2), - fun(_use0@1) -> - {Month, Bytes@3} = _use0@1, - gleam@result:'try'( - accept_byte(Bytes@3, 16#2D), - fun(Bytes@4) -> - gleam@result:'try'( - parse_day(Bytes@4, Year, Month), - fun(_use0@2) -> - {Day, Bytes@5} = _use0@2, - gleam@result:'try'( - accept_date_time_separator( - Bytes@5 - ), - fun(Bytes@6) -> - gleam@result:'try'( - parse_hours(Bytes@6), - fun(_use0@3) -> - {Hours, Bytes@7} = _use0@3, - gleam@result:'try'( - accept_byte( - Bytes@7, - 16#3A - ), - fun(Bytes@8) -> - gleam@result:'try'( - parse_minutes( - Bytes@8 - ), - fun( - _use0@4 - ) -> - {Minutes, - Bytes@9} = _use0@4, - gleam@result:'try'( - accept_byte( - Bytes@9, - 16#3A - ), - fun( - Bytes@10 - ) -> - gleam@result:'try'( - parse_seconds( - Bytes@10 - ), - fun( - _use0@5 - ) -> - {Seconds, - Bytes@11} = _use0@5, - gleam@result:'try'( - parse_second_fraction_as_nanoseconds( - Bytes@11 - ), - fun( - _use0@6 - ) -> - {Second_fraction_as_nanoseconds, - Bytes@12} = _use0@6, - gleam@result:'try'( - parse_offset( - Bytes@12 - ), - fun( - _use0@7 - ) -> - {Offset_seconds, - Bytes@13} = _use0@7, - gleam@result:'try'( - accept_empty( - Bytes@13 - ), - fun( - _use0@8 - ) -> - nil = _use0@8, - {ok, - from_date_time( - Year, - Month, - Day, - Hours, - Minutes, - Seconds, - Second_fraction_as_nanoseconds, - Offset_seconds - )} - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ) - end - ). diff --git a/build/dev/javascript/gleam_time/gleam_time_ffi.erl b/build/dev/javascript/gleam_time/gleam_time_ffi.erl deleted file mode 100644 index 34d8c88..0000000 --- a/build/dev/javascript/gleam_time/gleam_time_ffi.erl +++ /dev/null @@ -1,12 +0,0 @@ --module(gleam_time_ffi). --export([system_time/0, local_time_offset_seconds/0]). - -system_time() -> - {0, erlang:system_time(nanosecond)}. - -local_time_offset_seconds() -> - Utc = calendar:universal_time(), - Local = calendar:local_time(), - UtcSeconds = calendar:datetime_to_gregorian_seconds(Utc), - LocalSeconds = calendar:datetime_to_gregorian_seconds(Local), - LocalSeconds - UtcSeconds. diff --git a/build/dev/javascript/gleam_time/gleam_time_ffi.mjs b/build/dev/javascript/gleam_time/gleam_time_ffi.mjs deleted file mode 100644 index 27d09aa..0000000 --- a/build/dev/javascript/gleam_time/gleam_time_ffi.mjs +++ /dev/null @@ -1,11 +0,0 @@ -export function system_time() { - const now = Date.now(); - const milliseconds = now % 1_000; - const nanoseconds = milliseconds * 1000_000; - const seconds = (now - milliseconds) / 1_000; - return [seconds, nanoseconds]; -} - -export function local_time_offset_seconds() { - return new Date().getTimezoneOffset() * -60; -} diff --git a/build/dev/javascript/gleam_version b/build/dev/javascript/gleam_version deleted file mode 100644 index f88cf52..0000000 --- a/build/dev/javascript/gleam_version +++ /dev/null @@ -1 +0,0 @@ -1.13.0 \ No newline at end of file diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache deleted file mode 100644 index b2264149d868b0e47176c36d1ee6bde3be23ad2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8472 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 diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_inline b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_meta b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_meta deleted file mode 100644 index 5c75cc992e83eca70e609b683e4827f800e34f78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479 zcmbQ@$ezgn1&qv41{ai0&q+SvM?}+vNAA8vNAA8vobKqure_Cure@AVP#;L z%F4hnpOt}O0V@N;237`!?W_z8J6RbRcCj)rykKQu&|_m@&}U;{aA#v+h+<=4h+$)3 zh-G77sAgke=w@SJ=w)MI=woAGSjfh}u$qm5VKW;8!+SOc1{QV(1~zsE26lD^1~YaB MhAJoqg)ayL04$6@YybcN diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache deleted file mode 100644 index 1f02d4328d69d8f36971b5f2780a955d293d782f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14778 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 diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_inline b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta deleted file mode 100644 index 8e2ed2a9188b90091516c49c2dadd3cbab677088..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 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 X1!aagpk+La#*al_fRZu4sE8;4cDgf3 diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_inline b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta b/build/dev/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta deleted file mode 100644 index 34ab986f3e8d6df32e28b332821560cc8a7c04bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1277 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 diff --git a/build/dev/javascript/gleeunit/gleam.mjs b/build/dev/javascript/gleeunit/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/build/dev/javascript/gleeunit/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/build/dev/javascript/gleeunit/gleeunit.erl b/build/dev/javascript/gleeunit/gleeunit.erl deleted file mode 100644 index bcb58b6..0000000 --- a/build/dev/javascript/gleeunit/gleeunit.erl +++ /dev/null @@ -1,89 +0,0 @@ --module(gleeunit). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit.gleam"). --export([main/0]). --export_type([atom_/0, encoding/0, report_module_name/0, gleeunit_progress_option/0, eunit_option/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type atom_() :: any(). - --type encoding() :: utf8. - --type report_module_name() :: gleeunit_progress. - --type gleeunit_progress_option() :: {colored, boolean()}. - --type eunit_option() :: verbose | - no_tty | - {report, {report_module_name(), list(gleeunit_progress_option())}} | - {scale_timeouts, integer()}. - --file("src/gleeunit.gleam", 42). --spec gleam_to_erlang_module_name(binary()) -> binary(). -gleam_to_erlang_module_name(Path) -> - case gleam_stdlib:string_ends_with(Path, <<".gleam"/utf8>>) of - true -> - _pipe = Path, - _pipe@1 = gleam@string:replace( - _pipe, - <<".gleam"/utf8>>, - <<""/utf8>> - ), - gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"@"/utf8>>); - - false -> - _pipe@2 = Path, - _pipe@3 = gleam@string:split(_pipe@2, <<"/"/utf8>>), - _pipe@4 = gleam@list:last(_pipe@3), - _pipe@5 = gleam@result:unwrap(_pipe@4, Path), - gleam@string:replace(_pipe@5, <<".erl"/utf8>>, <<""/utf8>>) - end. - --file("src/gleeunit.gleam", 18). --spec do_main() -> nil. -do_main() -> - Options = [verbose, - no_tty, - {report, {gleeunit_progress, [{colored, true}]}}, - {scale_timeouts, 10}], - Result = begin - _pipe = gleeunit_ffi:find_files( - <<"**/*.{erl,gleam}"/utf8>>, - <<"test"/utf8>> - ), - _pipe@1 = gleam@list:map(_pipe, fun gleam_to_erlang_module_name/1), - _pipe@2 = gleam@list:map( - _pipe@1, - fun(_capture) -> erlang:binary_to_atom(_capture, utf8) end - ), - gleeunit_ffi:run_eunit(_pipe@2, Options) - end, - Code = case Result of - {ok, _} -> - 0; - - {error, _} -> - 1 - end, - erlang:halt(Code). - --file("src/gleeunit.gleam", 13). -?DOC( - " Find and run all test functions for the current project using Erlang's EUnit\n" - " test framework, or a custom JavaScript test runner.\n" - "\n" - " Any Erlang or Gleam function in the `test` directory with a name ending in\n" - " `_test` is considered a test function and will be run.\n" - "\n" - " A test that panics is considered a failure.\n" -). --spec main() -> nil. -main() -> - do_main(). diff --git a/build/dev/javascript/gleeunit/gleeunit.mjs b/build/dev/javascript/gleeunit/gleeunit.mjs deleted file mode 100644 index 83018dd..0000000 --- a/build/dev/javascript/gleeunit/gleeunit.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $result from "../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../gleam_stdlib/gleam/string.mjs"; -import { CustomType as $CustomType } from "./gleam.mjs"; -import { main as do_main } from "./gleeunit_ffi.mjs"; - -class Utf8 extends $CustomType {} - -class GleeunitProgress extends $CustomType {} - -class Colored extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class Verbose extends $CustomType {} - -class NoTty extends $CustomType {} - -class Report extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class ScaleTimeouts extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -function gleam_to_erlang_module_name(path) { - let $ = $string.ends_with(path, ".gleam"); - if ($) { - let _pipe = path; - let _pipe$1 = $string.replace(_pipe, ".gleam", ""); - return $string.replace(_pipe$1, "/", "@"); - } else { - let _pipe = path; - let _pipe$1 = $string.split(_pipe, "/"); - let _pipe$2 = $list.last(_pipe$1); - let _pipe$3 = $result.unwrap(_pipe$2, path); - return $string.replace(_pipe$3, ".erl", ""); - } -} - -/** - * Find and run all test functions for the current project using Erlang's EUnit - * test framework, or a custom JavaScript test runner. - * - * Any Erlang or Gleam function in the `test` directory with a name ending in - * `_test` is considered a test function and will be run. - * - * A test that panics is considered a failure. - */ -export function main() { - return do_main(); -} diff --git a/build/dev/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs b/build/dev/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs deleted file mode 100644 index f6af89d..0000000 --- a/build/dev/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs +++ /dev/null @@ -1,180 +0,0 @@ -import * as $dynamic from "../../../gleam_stdlib/gleam/dynamic.mjs"; -import { CustomType as $CustomType } from "../../gleam.mjs"; -import { from_dynamic } from "./gleeunit_gleam_panic_ffi.mjs"; - -export { from_dynamic }; - -export class GleamPanic extends $CustomType { - constructor(message, file, module, function$, line, kind) { - super(); - this.message = message; - this.file = file; - this.module = module; - this.function = function$; - this.line = line; - this.kind = kind; - } -} -export const GleamPanic$GleamPanic = (message, file, module, function$, line, kind) => - new GleamPanic(message, file, module, function$, line, kind); -export const GleamPanic$isGleamPanic = (value) => value instanceof GleamPanic; -export const GleamPanic$GleamPanic$message = (value) => value.message; -export const GleamPanic$GleamPanic$0 = (value) => value.message; -export const GleamPanic$GleamPanic$file = (value) => value.file; -export const GleamPanic$GleamPanic$1 = (value) => value.file; -export const GleamPanic$GleamPanic$module = (value) => value.module; -export const GleamPanic$GleamPanic$2 = (value) => value.module; -export const GleamPanic$GleamPanic$function = (value) => value.function; -export const GleamPanic$GleamPanic$3 = (value) => value.function; -export const GleamPanic$GleamPanic$line = (value) => value.line; -export const GleamPanic$GleamPanic$4 = (value) => value.line; -export const GleamPanic$GleamPanic$kind = (value) => value.kind; -export const GleamPanic$GleamPanic$5 = (value) => value.kind; - -export class Todo extends $CustomType {} -export const PanicKind$Todo = () => new Todo(); -export const PanicKind$isTodo = (value) => value instanceof Todo; - -export class Panic extends $CustomType {} -export const PanicKind$Panic = () => new Panic(); -export const PanicKind$isPanic = (value) => value instanceof Panic; - -export class LetAssert extends $CustomType { - constructor(start, end, pattern_start, pattern_end, value) { - super(); - this.start = start; - this.end = end; - this.pattern_start = pattern_start; - this.pattern_end = pattern_end; - this.value = value; - } -} -export const PanicKind$LetAssert = (start, end, pattern_start, pattern_end, value) => - new LetAssert(start, end, pattern_start, pattern_end, value); -export const PanicKind$isLetAssert = (value) => value instanceof LetAssert; -export const PanicKind$LetAssert$start = (value) => value.start; -export const PanicKind$LetAssert$0 = (value) => value.start; -export const PanicKind$LetAssert$end = (value) => value.end; -export const PanicKind$LetAssert$1 = (value) => value.end; -export const PanicKind$LetAssert$pattern_start = (value) => value.pattern_start; -export const PanicKind$LetAssert$2 = (value) => value.pattern_start; -export const PanicKind$LetAssert$pattern_end = (value) => value.pattern_end; -export const PanicKind$LetAssert$3 = (value) => value.pattern_end; -export const PanicKind$LetAssert$value = (value) => value.value; -export const PanicKind$LetAssert$4 = (value) => value.value; - -export class Assert extends $CustomType { - constructor(start, end, expression_start, kind) { - super(); - this.start = start; - this.end = end; - this.expression_start = expression_start; - this.kind = kind; - } -} -export const PanicKind$Assert = (start, end, expression_start, kind) => - new Assert(start, end, expression_start, kind); -export const PanicKind$isAssert = (value) => value instanceof Assert; -export const PanicKind$Assert$start = (value) => value.start; -export const PanicKind$Assert$0 = (value) => value.start; -export const PanicKind$Assert$end = (value) => value.end; -export const PanicKind$Assert$1 = (value) => value.end; -export const PanicKind$Assert$expression_start = (value) => - value.expression_start; -export const PanicKind$Assert$2 = (value) => value.expression_start; -export const PanicKind$Assert$kind = (value) => value.kind; -export const PanicKind$Assert$3 = (value) => value.kind; - -export class BinaryOperator extends $CustomType { - constructor(operator, left, right) { - super(); - this.operator = operator; - this.left = left; - this.right = right; - } -} -export const AssertKind$BinaryOperator = (operator, left, right) => - new BinaryOperator(operator, left, right); -export const AssertKind$isBinaryOperator = (value) => - value instanceof BinaryOperator; -export const AssertKind$BinaryOperator$operator = (value) => value.operator; -export const AssertKind$BinaryOperator$0 = (value) => value.operator; -export const AssertKind$BinaryOperator$left = (value) => value.left; -export const AssertKind$BinaryOperator$1 = (value) => value.left; -export const AssertKind$BinaryOperator$right = (value) => value.right; -export const AssertKind$BinaryOperator$2 = (value) => value.right; - -export class FunctionCall extends $CustomType { - constructor(arguments$) { - super(); - this.arguments = arguments$; - } -} -export const AssertKind$FunctionCall = (arguments$) => - new FunctionCall(arguments$); -export const AssertKind$isFunctionCall = (value) => - value instanceof FunctionCall; -export const AssertKind$FunctionCall$arguments = (value) => value.arguments; -export const AssertKind$FunctionCall$0 = (value) => value.arguments; - -export class OtherExpression extends $CustomType { - constructor(expression) { - super(); - this.expression = expression; - } -} -export const AssertKind$OtherExpression = (expression) => - new OtherExpression(expression); -export const AssertKind$isOtherExpression = (value) => - value instanceof OtherExpression; -export const AssertKind$OtherExpression$expression = (value) => - value.expression; -export const AssertKind$OtherExpression$0 = (value) => value.expression; - -export class AssertedExpression extends $CustomType { - constructor(start, end, kind) { - super(); - this.start = start; - this.end = end; - this.kind = kind; - } -} -export const AssertedExpression$AssertedExpression = (start, end, kind) => - new AssertedExpression(start, end, kind); -export const AssertedExpression$isAssertedExpression = (value) => - value instanceof AssertedExpression; -export const AssertedExpression$AssertedExpression$start = (value) => - value.start; -export const AssertedExpression$AssertedExpression$0 = (value) => value.start; -export const AssertedExpression$AssertedExpression$end = (value) => value.end; -export const AssertedExpression$AssertedExpression$1 = (value) => value.end; -export const AssertedExpression$AssertedExpression$kind = (value) => value.kind; -export const AssertedExpression$AssertedExpression$2 = (value) => value.kind; - -export class Literal extends $CustomType { - constructor(value) { - super(); - this.value = value; - } -} -export const ExpressionKind$Literal = (value) => new Literal(value); -export const ExpressionKind$isLiteral = (value) => value instanceof Literal; -export const ExpressionKind$Literal$value = (value) => value.value; -export const ExpressionKind$Literal$0 = (value) => value.value; - -export class Expression extends $CustomType { - constructor(value) { - super(); - this.value = value; - } -} -export const ExpressionKind$Expression = (value) => new Expression(value); -export const ExpressionKind$isExpression = (value) => - value instanceof Expression; -export const ExpressionKind$Expression$value = (value) => value.value; -export const ExpressionKind$Expression$0 = (value) => value.value; - -export class Unevaluated extends $CustomType {} -export const ExpressionKind$Unevaluated = () => new Unevaluated(); -export const ExpressionKind$isUnevaluated = (value) => - value instanceof Unevaluated; diff --git a/build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl b/build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl deleted file mode 100644 index d78f5e5..0000000 --- a/build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(gleeunit_gleam_panic_ffi). --export([from_dynamic/1]). - -from_dynamic(#{ - gleam_error := assert, - start := Start, - 'end' := End, - expression_start := EStart -} = E) -> - wrap(E, {assert, Start, End, EStart, assert_kind(E)}); -from_dynamic(#{ - gleam_error := let_assert, - start := Start, - 'end' := End, - pattern_start := PStart, - pattern_end := PEnd, - value := Value -} = E) -> - wrap(E, {let_assert, Start, End, PStart, PEnd, Value}); -from_dynamic(#{gleam_error := panic} = E) -> - wrap(E, panic); -from_dynamic(#{gleam_error := todo} = E) -> - wrap(E, todo); -from_dynamic(_) -> - {error, nil}. - -assert_kind(#{kind := binary_operator, left := L, right := R, operator := O}) -> - {binary_operator, atom_to_binary(O), expression(L), expression(R)}; -assert_kind(#{kind := function_call, arguments := Arguments}) -> - {function_call, lists:map(fun expression/1, Arguments)}; -assert_kind(#{kind := expression, expression := Expression}) -> - {other_expression, expression(Expression)}. - -expression(#{start := S, 'end' := E, kind := literal, value := Value}) -> - {asserted_expression, S, E, {literal, Value}}; -expression(#{start := S, 'end' := E, kind := expression, value := Value}) -> - {asserted_expression, S, E, {expression, Value}}; -expression(#{start := S, 'end' := E, kind := unevaluated}) -> - {asserted_expression, S, E, unevaluated}. - -wrap(#{ - gleam_error := _, - file := File, - message := Message, - module := Module, - function := Function, - line := Line -}, Kind) -> - {ok, {gleam_panic, Message, File, Module, Function, Line, Kind}}. diff --git a/build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs b/build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs deleted file mode 100644 index 03f6025..0000000 --- a/build/dev/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import { Result$Ok, Result$Error, List$Empty, List$NonEmpty } from "../../gleam.mjs"; -import { - GleamPanic$GleamPanic, - PanicKind$Todo, - PanicKind$Panic, - PanicKind$LetAssert, - PanicKind$Assert, - AssertKind$BinaryOperator, - AssertKind$FunctionCall, - AssertKind$OtherExpression, - AssertedExpression$AssertedExpression, - ExpressionKind$Literal, - ExpressionKind$Expression, - ExpressionKind$Unevaluated, -} from "./gleam_panic.mjs"; - -export function from_dynamic(error) { - if (!(error instanceof globalThis.Error) || !error.gleam_error) { - return Result$Error(undefined); - } - - if (error.gleam_error === "todo") { - return wrap(error, PanicKind$Todo()); - } - - if (error.gleam_error === "panic") { - return wrap(error, PanicKind$Panic()); - } - - if (error.gleam_error === "let_assert") { - let kind = PanicKind$LetAssert( - error.start, - error.end, - error.pattern_start, - error.pattern_end, - error.value, - ); - return wrap(error, kind); - } - - if (error.gleam_error === "assert") { - let kind = PanicKind$Assert( - error.start, - error.end, - error.expression_start, - assert_kind(error), - ); - return wrap(error, kind); - } - - return Result$Error(undefined); -} - -function assert_kind(error) { - if (error.kind == "binary_operator") { - return AssertKind$BinaryOperator( - error.operator, - expression(error.left), - expression(error.right), - ); - } - - if (error.kind == "function_call") { - let list = List$Empty(); - let i = error.arguments.length; - while (i--) { - list = List$NonEmpty(expression(error.arguments[i]), list); - } - return AssertKind$FunctionCall(list); - } - - return AssertKind$OtherExpression(expression(error.expression)); -} - -function expression(data) { - const expression = AssertedExpression$AssertedExpression(data.start, data.end, undefined); - if (data.kind == "literal") { - expression.kind = ExpressionKind$Literal(data.value); - } else if (data.kind == "expression") { - expression.kind = ExpressionKind$Expression(data.value); - } else { - expression.kind = ExpressionKind$Unevaluated(); - } - return expression; -} - -function wrap(e, kind) { - return Result$Ok( - GleamPanic$GleamPanic(e.message, e.file, e.module, e.function, e.line, kind), - ); -} diff --git a/build/dev/javascript/gleeunit/gleeunit/internal/reporting.mjs b/build/dev/javascript/gleeunit/gleeunit/internal/reporting.mjs deleted file mode 100644 index 8ebf9a2..0000000 --- a/build/dev/javascript/gleeunit/gleeunit/internal/reporting.mjs +++ /dev/null @@ -1,256 +0,0 @@ -import * as $bit_array from "../../../gleam_stdlib/gleam/bit_array.mjs"; -import * as $dynamic from "../../../gleam_stdlib/gleam/dynamic.mjs"; -import * as $int from "../../../gleam_stdlib/gleam/int.mjs"; -import * as $io from "../../../gleam_stdlib/gleam/io.mjs"; -import * as $list from "../../../gleam_stdlib/gleam/list.mjs"; -import * as $option from "../../../gleam_stdlib/gleam/option.mjs"; -import * as $result from "../../../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../../../gleam_stdlib/gleam/string.mjs"; -import { Ok, Error, toList, CustomType as $CustomType } from "../../gleam.mjs"; -import * as $gleam_panic from "../../gleeunit/internal/gleam_panic.mjs"; -import { read_file as read_file_text } from "../../gleeunit_ffi.mjs"; - -export class State extends $CustomType { - constructor(passed, failed, skipped) { - super(); - this.passed = passed; - this.failed = failed; - this.skipped = skipped; - } -} -export const State$State = (passed, failed, skipped) => - new State(passed, failed, skipped); -export const State$isState = (value) => value instanceof State; -export const State$State$passed = (value) => value.passed; -export const State$State$0 = (value) => value.passed; -export const State$State$failed = (value) => value.failed; -export const State$State$1 = (value) => value.failed; -export const State$State$skipped = (value) => value.skipped; -export const State$State$2 = (value) => value.skipped; - -export function new_state() { - return new State(0, 0, 0); -} - -function bold(text) { - return ("\u{001b}[1m" + text) + "\u{001b}[22m"; -} - -function cyan(text) { - return ("\u{001b}[36m" + text) + "\u{001b}[39m"; -} - -function code_snippet(src, start, end) { - let _pipe = $result.try$( - $option.to_result(src, undefined), - (src) => { - return $result.try$( - $bit_array.slice(src, start, end - start), - (snippet) => { - return $result.try$( - $bit_array.to_string(snippet), - (snippet) => { - let snippet$1 = ((cyan(" code") + ": ") + snippet) + "\n"; - return new Ok(snippet$1); - }, - ); - }, - ); - }, - ); - return $result.unwrap(_pipe, ""); -} - -function yellow(text) { - return ("\u{001b}[33m" + text) + "\u{001b}[39m"; -} - -export function test_skipped(state, module, function$) { - $io.print(((("\n" + module) + ".") + function$) + yellow(" skipped")); - return new State(state.passed, state.failed, state.skipped + 1); -} - -function green(text) { - return ("\u{001b}[32m" + text) + "\u{001b}[39m"; -} - -export function test_passed(state) { - $io.print(green(".")); - return new State(state.passed + 1, state.failed, state.skipped); -} - -function red(text) { - return ("\u{001b}[31m" + text) + "\u{001b}[39m"; -} - -export function finished(state) { - let $ = state.failed; - if ($ === 0) { - let $1 = state.skipped; - if ($1 === 0) { - let $2 = state.passed; - if ($2 === 0) { - $io.println("\nNo tests found!"); - return 1; - } else { - let message = ("\n" + $int.to_string(state.passed)) + " passed, no failures"; - $io.println(green(message)); - return 0; - } - } else { - let message = ((("\n" + $int.to_string(state.passed)) + " passed, 0 failures, ") + $int.to_string( - state.skipped, - )) + " skipped"; - $io.println(yellow(message)); - return 1; - } - } else { - let $1 = state.skipped; - if ($1 === 0) { - let message = ((("\n" + $int.to_string(state.passed)) + " passed, ") + $int.to_string( - state.failed, - )) + " failures"; - $io.println(red(message)); - return 1; - } else { - let message = ((((("\n" + $int.to_string(state.passed)) + " passed, ") + $int.to_string( - state.failed, - )) + " failures, ") + $int.to_string(state.skipped)) + " skipped"; - $io.println(red(message)); - return 1; - } - } -} - -export function eunit_missing() { - let message = bold(red("Error")) + ": EUnit libraries not found.\n\nYour Erlang installation seems to be incomplete. If you installed Erlang using\na package manager ensure that you have installed the full Erlang\ndistribution instead of a stripped-down version.\n"; - $io.print_error(message); - return new Error(undefined); -} - -function grey(text) { - return ("\u{001b}[90m" + text) + "\u{001b}[39m"; -} - -function format_unknown(module, function$, error) { - return $string.concat( - toList([ - grey((module + ".") + function$) + "\n", - "An unexpected error occurred:\n", - "\n", - (" " + $string.inspect(error)) + "\n", - ]), - ); -} - -function inspect_value(value) { - let $ = value.kind; - if ($ instanceof $gleam_panic.Literal) { - return grey("literal"); - } else if ($ instanceof $gleam_panic.Expression) { - let value$1 = $.value; - return $string.inspect(value$1); - } else { - return grey("unevaluated"); - } -} - -function assert_value(name, value) { - return ((cyan(name) + ": ") + inspect_value(value)) + "\n"; -} - -function assert_info(kind) { - if (kind instanceof $gleam_panic.BinaryOperator) { - let left = kind.left; - let right = kind.right; - return $string.concat( - toList([assert_value(" left", left), assert_value("right", right)]), - ); - } else if (kind instanceof $gleam_panic.FunctionCall) { - let arguments$ = kind.arguments; - let _pipe = arguments$; - let _pipe$1 = $list.index_map( - _pipe, - (e, i) => { - let number = $string.pad_start($int.to_string(i), 5, " "); - return assert_value(number, e); - }, - ); - return $string.concat(_pipe$1); - } else { - return ""; - } -} - -function format_gleam_error(error, module, function$, src) { - let location = grey((error.file + ":") + $int.to_string(error.line)); - let $ = error.kind; - if ($ instanceof $gleam_panic.Todo) { - return $string.concat( - toList([ - ((bold(yellow("todo")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } else if ($ instanceof $gleam_panic.Panic) { - return $string.concat( - toList([ - ((bold(red("panic")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } else if ($ instanceof $gleam_panic.LetAssert) { - let start = $.start; - let end = $.end; - let value = $.value; - return $string.concat( - toList([ - ((bold(red("let assert")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - code_snippet(src, start, end), - ((cyan("value") + ": ") + $string.inspect(value)) + "\n", - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } else { - let start = $.start; - let end = $.end; - let kind = $.kind; - return $string.concat( - toList([ - ((bold(red("assert")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - code_snippet(src, start, end), - assert_info(kind), - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } -} - -function read_file(path) { - let $ = read_file_text(path); - if ($ instanceof Ok) { - let text = $[0]; - return new Ok($bit_array.from_string(text)); - } else { - return $; - } -} - -export function test_failed(state, module, function$, error) { - let _block; - let $ = $gleam_panic.from_dynamic(error); - if ($ instanceof Ok) { - let error$1 = $[0]; - let src = $option.from_result(read_file(error$1.file)); - _block = format_gleam_error(error$1, module, function$, src); - } else { - _block = format_unknown(module, function$, error); - } - let message = _block; - $io.print("\n" + message); - return new State(state.passed, state.failed + 1, state.skipped); -} diff --git a/build/dev/javascript/gleeunit/gleeunit/should.mjs b/build/dev/javascript/gleeunit/gleeunit/should.mjs deleted file mode 100644 index c34c700..0000000 --- a/build/dev/javascript/gleeunit/gleeunit/should.mjs +++ /dev/null @@ -1,135 +0,0 @@ -import * as $option from "../../gleam_stdlib/gleam/option.mjs"; -import { None, Some } from "../../gleam_stdlib/gleam/option.mjs"; -import * as $string from "../../gleam_stdlib/gleam/string.mjs"; -import { Ok, Error, toList, makeError, isEqual } from "../gleam.mjs"; - -const FILEPATH = "src/gleeunit/should.gleam"; - -export function equal(a, b) { - let $ = isEqual(a, b); - if ($) { - return undefined; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 10, - "equal", - $string.concat( - toList([ - "\n", - $string.inspect(a), - "\nshould equal\n", - $string.inspect(b), - ]), - ), - {} - ) - } -} - -export function not_equal(a, b) { - let $ = !isEqual(a, b); - if ($) { - return undefined; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 23, - "not_equal", - $string.concat( - toList([ - "\n", - $string.inspect(a), - "\nshould not equal\n", - $string.inspect(b), - ]), - ), - {} - ) - } -} - -export function be_ok(a) { - if (a instanceof Ok) { - let value = a[0]; - return value; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 35, - "be_ok", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be ok"])), - {} - ) - } -} - -export function be_error(a) { - if (a instanceof Error) { - let error = a[0]; - return error; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 42, - "be_error", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be error"])), - {} - ) - } -} - -export function be_some(a) { - if (a instanceof Some) { - let value = a[0]; - return value; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 49, - "be_some", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be some"])), - {} - ) - } -} - -export function be_none(a) { - if (a instanceof None) { - return undefined; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 56, - "be_none", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be none"])), - {} - ) - } -} - -export function be_true(actual) { - let _pipe = actual; - return equal(_pipe, true); -} - -export function be_false(actual) { - let _pipe = actual; - return equal(_pipe, false); -} - -export function fail() { - return be_true(false); -} diff --git a/build/dev/javascript/gleeunit/gleeunit@internal@gleam_panic.erl b/build/dev/javascript/gleeunit/gleeunit@internal@gleam_panic.erl deleted file mode 100644 index 398ea7d..0000000 --- a/build/dev/javascript/gleeunit/gleeunit@internal@gleam_panic.erl +++ /dev/null @@ -1,56 +0,0 @@ --module(gleeunit@internal@gleam_panic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/internal/gleam_panic.gleam"). --export([from_dynamic/1]). --export_type([gleam_panic/0, panic_kind/0, assert_kind/0, asserted_expression/0, expression_kind/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(false). - --type gleam_panic() :: {gleam_panic, - binary(), - binary(), - binary(), - binary(), - integer(), - panic_kind()}. - --type panic_kind() :: todo | - panic | - {let_assert, - integer(), - integer(), - integer(), - integer(), - gleam@dynamic:dynamic_()} | - {assert, integer(), integer(), integer(), assert_kind()}. - --type assert_kind() :: {binary_operator, - binary(), - asserted_expression(), - asserted_expression()} | - {function_call, list(asserted_expression())} | - {other_expression, asserted_expression()}. - --type asserted_expression() :: {asserted_expression, - integer(), - integer(), - expression_kind()}. - --type expression_kind() :: {literal, gleam@dynamic:dynamic_()} | - {expression, gleam@dynamic:dynamic_()} | - unevaluated. - --file("src/gleeunit/internal/gleam_panic.gleam", 49). -?DOC(false). --spec from_dynamic(gleam@dynamic:dynamic_()) -> {ok, gleam_panic()} | - {error, nil}. -from_dynamic(Data) -> - gleeunit_gleam_panic_ffi:from_dynamic(Data). diff --git a/build/dev/javascript/gleeunit/gleeunit@internal@reporting.erl b/build/dev/javascript/gleeunit/gleeunit@internal@reporting.erl deleted file mode 100644 index 8c37c79..0000000 --- a/build/dev/javascript/gleeunit/gleeunit@internal@reporting.erl +++ /dev/null @@ -1,343 +0,0 @@ --module(gleeunit@internal@reporting). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/internal/reporting.gleam"). --export([new_state/0, test_skipped/3, test_passed/1, finished/1, eunit_missing/0, test_failed/4]). --export_type([state/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(false). - --type state() :: {state, integer(), integer(), integer()}. - --file("src/gleeunit/internal/reporting.gleam", 15). -?DOC(false). --spec new_state() -> state(). -new_state() -> - {state, 0, 0, 0}. - --file("src/gleeunit/internal/reporting.gleam", 207). -?DOC(false). --spec bold(binary()) -> binary(). -bold(Text) -> - <<<<"\x{001b}[1m"/utf8, Text/binary>>/binary, "\x{001b}[22m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 211). -?DOC(false). --spec cyan(binary()) -> binary(). -cyan(Text) -> - <<<<"\x{001b}[36m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 191). -?DOC(false). --spec code_snippet(gleam@option:option(bitstring()), integer(), integer()) -> binary(). -code_snippet(Src, Start, End) -> - _pipe = begin - gleam@result:'try'( - gleam@option:to_result(Src, nil), - fun(Src@1) -> - gleam@result:'try'( - gleam_stdlib:bit_array_slice(Src@1, Start, End - Start), - fun(Snippet) -> - gleam@result:'try'( - gleam@bit_array:to_string(Snippet), - fun(Snippet@1) -> - Snippet@2 = <<<<<<(cyan(<<" code"/utf8>>))/binary, - ": "/utf8>>/binary, - Snippet@1/binary>>/binary, - "\n"/utf8>>, - {ok, Snippet@2} - end - ) - end - ) - end - ) - end, - gleam@result:unwrap(_pipe, <<""/utf8>>). - --file("src/gleeunit/internal/reporting.gleam", 215). -?DOC(false). --spec yellow(binary()) -> binary(). -yellow(Text) -> - <<<<"\x{001b}[33m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 202). -?DOC(false). --spec test_skipped(state(), binary(), binary()) -> state(). -test_skipped(State, Module, Function) -> - gleam_stdlib:print( - <<<<<<<<"\n"/utf8, Module/binary>>/binary, "."/utf8>>/binary, - Function/binary>>/binary, - (yellow(<<" skipped"/utf8>>))/binary>> - ), - {state, - erlang:element(2, State), - erlang:element(3, State), - erlang:element(4, State) + 1}. - --file("src/gleeunit/internal/reporting.gleam", 219). -?DOC(false). --spec green(binary()) -> binary(). -green(Text) -> - <<<<"\x{001b}[32m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 66). -?DOC(false). --spec test_passed(state()) -> state(). -test_passed(State) -> - gleam_stdlib:print(green(<<"."/utf8>>)), - {state, - erlang:element(2, State) + 1, - erlang:element(3, State), - erlang:element(4, State)}. - --file("src/gleeunit/internal/reporting.gleam", 223). -?DOC(false). --spec red(binary()) -> binary(). -red(Text) -> - <<<<"\x{001b}[31m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 19). -?DOC(false). --spec finished(state()) -> integer(). -finished(State) -> - case State of - {state, 0, 0, 0} -> - gleam_stdlib:println(<<"\nNo tests found!"/utf8>>), - 1; - - {state, _, 0, 0} -> - Message = <<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, no failures"/utf8>>, - gleam_stdlib:println(green(Message)), - 0; - - {state, _, _, 0} -> - Message@1 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures"/utf8>>, - gleam_stdlib:println(red(Message@1)), - 1; - - {state, _, 0, _} -> - Message@2 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, 0 failures, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(4, State)))/binary>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(yellow(Message@2)), - 1; - - {state, _, _, _} -> - Message@3 = <<<<<<<<<<<<"\n"/utf8, - (erlang:integer_to_binary( - erlang:element(2, State) - ))/binary>>/binary, - " passed, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(4, State)))/binary>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(red(Message@3)), - 1 - end. - --file("src/gleeunit/internal/reporting.gleam", 89). -?DOC(false). --spec eunit_missing() -> {ok, any()} | {error, nil}. -eunit_missing() -> - Message = <<(bold(red(<<"Error"/utf8>>)))/binary, - ": EUnit libraries not found. - -Your Erlang installation seems to be incomplete. If you installed Erlang using -a package manager ensure that you have installed the full Erlang -distribution instead of a stripped-down version. -"/utf8>>, - gleam_stdlib:print_error(Message), - {error, nil}. - --file("src/gleeunit/internal/reporting.gleam", 227). -?DOC(false). --spec grey(binary()) -> binary(). -grey(Text) -> - <<<<"\x{001b}[90m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 100). -?DOC(false). --spec format_unknown(binary(), binary(), gleam@dynamic:dynamic_()) -> binary(). -format_unknown(Module, Function, Error) -> - erlang:list_to_binary( - [<<(grey(<<<>/binary, Function/binary>>))/binary, - "\n"/utf8>>, - <<"An unexpected error occurred:\n"/utf8>>, - <<"\n"/utf8>>, - <<<<" "/utf8, (gleam@string:inspect(Error))/binary>>/binary, - "\n"/utf8>>] - ). - --file("src/gleeunit/internal/reporting.gleam", 183). -?DOC(false). --spec inspect_value(gleeunit@internal@gleam_panic:asserted_expression()) -> binary(). -inspect_value(Value) -> - case erlang:element(4, Value) of - unevaluated -> - grey(<<"unevaluated"/utf8>>); - - {literal, _} -> - grey(<<"literal"/utf8>>); - - {expression, Value@1} -> - gleam@string:inspect(Value@1) - end. - --file("src/gleeunit/internal/reporting.gleam", 179). -?DOC(false). --spec assert_value( - binary(), - gleeunit@internal@gleam_panic:asserted_expression() -) -> binary(). -assert_value(Name, Value) -> - <<<<<<(cyan(Name))/binary, ": "/utf8>>/binary, - (inspect_value(Value))/binary>>/binary, - "\n"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 160). -?DOC(false). --spec assert_info(gleeunit@internal@gleam_panic:assert_kind()) -> binary(). -assert_info(Kind) -> - case Kind of - {binary_operator, _, Left, Right} -> - erlang:list_to_binary( - [assert_value(<<" left"/utf8>>, Left), - assert_value(<<"right"/utf8>>, Right)] - ); - - {function_call, Arguments} -> - _pipe = Arguments, - _pipe@1 = gleam@list:index_map( - _pipe, - fun(E, I) -> - Number = gleam@string:pad_start( - erlang:integer_to_binary(I), - 5, - <<" "/utf8>> - ), - assert_value(Number, E) - end - ), - erlang:list_to_binary(_pipe@1); - - {other_expression, _} -> - <<""/utf8>> - end. - --file("src/gleeunit/internal/reporting.gleam", 113). -?DOC(false). --spec format_gleam_error( - gleeunit@internal@gleam_panic:gleam_panic(), - binary(), - binary(), - gleam@option:option(bitstring()) -) -> binary(). -format_gleam_error(Error, Module, Function, Src) -> - Location = grey( - <<<<(erlang:element(3, Error))/binary, ":"/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(6, Error)))/binary>> - ), - case erlang:element(7, Error) of - panic -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"panic"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - todo -> - erlang:list_to_binary( - [<<<<<<(bold(yellow(<<"todo"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - {assert, Start, End, _, Kind} -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"assert"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - code_snippet(Src, Start, End), - assert_info(Kind), - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - {let_assert, Start@1, End@1, _, _, Value} -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"let assert"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - code_snippet(Src, Start@1, End@1), - <<<<<<(cyan(<<"value"/utf8>>))/binary, ": "/utf8>>/binary, - (gleam@string:inspect(Value))/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ) - end. - --file("src/gleeunit/internal/reporting.gleam", 71). -?DOC(false). --spec test_failed(state(), binary(), binary(), gleam@dynamic:dynamic_()) -> state(). -test_failed(State, Module, Function, Error) -> - Message = case gleeunit_gleam_panic_ffi:from_dynamic(Error) of - {ok, Error@1} -> - Src = gleam@option:from_result( - file:read_file(erlang:element(3, Error@1)) - ), - format_gleam_error(Error@1, Module, Function, Src); - - {error, _} -> - format_unknown(Module, Function, Error) - end, - gleam_stdlib:print(<<"\n"/utf8, Message/binary>>), - {state, - erlang:element(2, State), - erlang:element(3, State) + 1, - erlang:element(4, State)}. diff --git a/build/dev/javascript/gleeunit/gleeunit@should.erl b/build/dev/javascript/gleeunit/gleeunit@should.erl deleted file mode 100644 index 81048de..0000000 --- a/build/dev/javascript/gleeunit/gleeunit@should.erl +++ /dev/null @@ -1,153 +0,0 @@ --module(gleeunit@should). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/should.gleam"). --export([equal/2, not_equal/2, be_ok/1, be_error/1, be_some/1, be_none/1, be_true/1, be_false/1, fail/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(" Use the `assert` keyword instead of this module.\n"). - --file("src/gleeunit/should.gleam", 6). --spec equal(DOF, DOF) -> nil. -equal(A, B) -> - case A =:= B of - true -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould equal\n"/utf8>>, - gleam@string:inspect(B)] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"equal"/utf8>>, - line => 10}) - end. - --file("src/gleeunit/should.gleam", 19). --spec not_equal(DOG, DOG) -> nil. -not_equal(A, B) -> - case A /= B of - true -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould not equal\n"/utf8>>, - gleam@string:inspect(B)] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"not_equal"/utf8>>, - line => 23}) - end. - --file("src/gleeunit/should.gleam", 32). --spec be_ok({ok, DOH} | {error, any()}) -> DOH. -be_ok(A) -> - case A of - {ok, Value} -> - Value; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be ok"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_ok"/utf8>>, - line => 35}) - end. - --file("src/gleeunit/should.gleam", 39). --spec be_error({ok, any()} | {error, DOM}) -> DOM. -be_error(A) -> - case A of - {error, Error} -> - Error; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be error"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_error"/utf8>>, - line => 42}) - end. - --file("src/gleeunit/should.gleam", 46). --spec be_some(gleam@option:option(DOP)) -> DOP. -be_some(A) -> - case A of - {some, Value} -> - Value; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be some"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_some"/utf8>>, - line => 49}) - end. - --file("src/gleeunit/should.gleam", 53). --spec be_none(gleam@option:option(any())) -> nil. -be_none(A) -> - case A of - none -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be none"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_none"/utf8>>, - line => 56}) - end. - --file("src/gleeunit/should.gleam", 60). --spec be_true(boolean()) -> nil. -be_true(Actual) -> - _pipe = Actual, - equal(_pipe, true). - --file("src/gleeunit/should.gleam", 65). --spec be_false(boolean()) -> nil. -be_false(Actual) -> - _pipe = Actual, - equal(_pipe, false). - --file("src/gleeunit/should.gleam", 70). --spec fail() -> nil. -fail() -> - be_true(false). diff --git a/build/dev/javascript/gleeunit/gleeunit_ffi.erl b/build/dev/javascript/gleeunit/gleeunit_ffi.erl deleted file mode 100644 index 05c7490..0000000 --- a/build/dev/javascript/gleeunit/gleeunit_ffi.erl +++ /dev/null @@ -1,21 +0,0 @@ --module(gleeunit_ffi). - --export([find_files/2, run_eunit/2]). - -find_files(Pattern, In) -> - Results = filelib:wildcard(binary_to_list(Pattern), binary_to_list(In)), - lists:map(fun list_to_binary/1, Results). - -run_eunit(Tests, Options) -> - case code:which(eunit) of - non_existing -> - gleeunit@internal@reporting:eunit_missing(); - - _ -> - case eunit:test(Tests, Options) of - ok -> {ok, nil}; - error -> {error, nil}; - {error, Term} -> {error, Term} - end - end. - diff --git a/build/dev/javascript/gleeunit/gleeunit_ffi.mjs b/build/dev/javascript/gleeunit/gleeunit_ffi.mjs deleted file mode 100644 index 7bdc071..0000000 --- a/build/dev/javascript/gleeunit/gleeunit_ffi.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import { readFileSync } from "node:fs"; -import { Result$Ok, Result$Error } from "./gleam.mjs"; -import * as reporting from "./gleeunit/internal/reporting.mjs"; - -export function read_file(path) { - try { - return Result$Ok(readFileSync(path)); - } catch { - return Result$Error(undefined); - } -} - -async function* gleamFiles(directory) { - for (let entry of await read_dir(directory)) { - let path = join_path(directory, entry); - if (path.endsWith(".gleam")) { - yield path; - } else { - try { - yield* gleamFiles(path); - } catch (error) { - // Could not read directory, assume it's a file - } - } - } -} - -async function readRootPackageName() { - let toml = await async_read_file("gleam.toml", "utf-8"); - for (let line of toml.split("\n")) { - let matches = line.match(/\s*name\s*=\s*"([a-z][a-z0-9_]*)"/); // Match regexp in compiler-cli/src/new.rs in validate_name() - if (matches) return matches[1]; - } - throw new Error("Could not determine package name from gleam.toml"); -} - -export async function main() { - let state = reporting.new_state(); - - let packageName = await readRootPackageName(); - let dist = `../${packageName}/`; - - for await (let path of await gleamFiles("test")) { - let js_path = path.slice("test/".length).replace(".gleam", ".mjs"); - let module = await import(join_path(dist, js_path)); - for (let fnName of Object.keys(module)) { - if (!fnName.endsWith("_test")) continue; - try { - await module[fnName](); - state = reporting.test_passed(state); - } catch (error) { - let moduleName = js_path.slice(0, -4); - state = reporting.test_failed(state, moduleName, fnName, error); - } - } - } - - const status = reporting.finished(state); - exit(status); -} - -export function crash(message) { - throw new Error(message); -} - -function exit(code) { - if (globalThis.Deno) { - Deno.exit(code); - } else { - process.exit(code); - } -} - -async function read_dir(path) { - if (globalThis.Deno) { - let items = []; - for await (let item of Deno.readDir(path, { withFileTypes: true })) { - items.push(item.name); - } - return items; - } else { - let { readdir } = await import("node:fs/promises"); - return readdir(path); - } -} - -function join_path(a, b) { - if (a.endsWith("/")) return a + b; - return a + "/" + b; -} - -async function async_read_file(path) { - if (globalThis.Deno) { - return Deno.readTextFile(path); - } else { - let { readFile } = await import("node:fs/promises"); - let contents = await readFile(path); - return contents.toString(); - } -} diff --git a/build/dev/javascript/gleeunit/gleeunit_progress.erl b/build/dev/javascript/gleeunit/gleeunit_progress.erl deleted file mode 100644 index e6576a5..0000000 --- a/build/dev/javascript/gleeunit/gleeunit_progress.erl +++ /dev/null @@ -1,72 +0,0 @@ -%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters - --module(gleeunit_progress). --define(NOTEST, true). - -%% eunit_listener callbacks --export([ - init/1, handle_begin/3, handle_end/3, handle_cancel/3, terminate/2, - start/0, start/1 -]). - --define(reporting, gleeunit@internal@reporting). - -start() -> - start([]). - -start(Options) -> - eunit_listener:start(?MODULE, Options). - -init(_Options) -> - ?reporting:new_state(). - -handle_begin(_test_or_group, _data, State) -> - State. - -handle_end(group, _data, State) -> - State; -handle_end(test, Data, State) -> - {AtomModule, AtomFunction, _Arity} = proplists:get_value(source, Data), - Module = erlang:atom_to_binary(AtomModule), - Function = erlang:atom_to_binary(AtomFunction), - - % EUnit swallows stdout, so print it to make debugging easier. - case proplists:get_value(output, Data) of - undefined -> ok; - <<>> -> ok; - Out -> gleam@io:print(Out) - end, - - case proplists:get_value(status, Data) of - ok -> - ?reporting:test_passed(State); - {skipped, _Reason} -> - ?reporting:test_skipped(State, Module, Function); - {error, {_, Exception, _Stack}} -> - ?reporting:test_failed(State, Module, Function, Exception) - end. - - -handle_cancel(_test_or_group, Data, State) -> - ?reporting:test_failed(State, <<"gleeunit">>, <<"main">>, Data). - -terminate({ok, _Data}, State) -> - ?reporting:finished(State), - ok; -terminate({error, Reason}, State) -> - ?reporting:finished(State), - io:fwrite(" -Eunit failed: - -~80p - -This is probably a bug in gleeunit. Please report it. -", [Reason]), - sync_end(error). - -sync_end(Result) -> - receive - {stop, Reference, ReplyTo} -> - ReplyTo ! {result, Reference, Result}, - ok - end. diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint.cache b/build/dev/javascript/paint/_gleam_artefacts/paint.cache deleted file mode 100644 index 18552154b4a7fe4b9f32ad9e44d493d6d0ef7cd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18173 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 diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@canvas.cache b/build/dev/javascript/paint/_gleam_artefacts/paint@canvas.cache deleted file mode 100644 index 315922bc999f3e705a373271cab134b26ba56169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20428 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 I}l28PFs3=Cq( za`DOexw)lznI)C_$@w|?rA1E|85kIu7#LWgstOV_^GcYQ7#L)k5XOQ9^;7eb^HWmg zm>3ugnHU(jku~V2mZj#E7%?$01Trx&NTEn&=9Q!t!o~Jl`Saty(tCe}onwS5W?*2jW?*2bWnf@9!@$50$;iO4 zgpq*(6c!*qgM0+?0LY;r7lG^onKg-tf#CrY1A_)L1A{3u1A{p;1A_%K14A4$1498b z1H&|C28J2T3=A`w85o{2GcdemW?=Zw%)p?|!oZ-*!oc9h!oU#3!oX0#!oYBvg@NHd z3j@PT76yioEDQ`^Sr{1DSQ!|ySs57Cure?_WMyFBVq;*?V`E?lXJcSUV`E?_U}In? zV`E_GVq;)9%*Md*nvH?sBO3$5S2hL)Ms@}UW_AV!7Ip>(8+HZ;7j_1QSat@6$?Oaa zGuas!7P2!iEM;e4*v8JlAkD$R5W~U1(8a;Pu#$s;;VcIO!#55F23Af627XQk22oB1 z22D-|hGG#LvL+jGuvlSAc;*MSy`pLx6$7QhF9aAEz6mfe=m|0~mU(aLvaR%5OD^EHgN`qrQ!?>tHl`@)`&AO91~|?cq-1o zz$n4Mpd!J*5GKLEP%6Q|P%Xj0P$R*>FkOOyVXXuM!+r?{hHDZG3_Owy3_g+!3}KQC z3~`bS3@MTf4D%%!7*0ttFfd6mFgQptFt|xEFjPu0Fie$VV7Mv8z`!WYz@RG4z@R71 zz>px#z)&yEz|bnqz|bkpz|bwtz|bSjz;Iidfx%OTfgw$Xfgw+ZfuUZ8fuU1|fuUE1 zfnl2r1H(QU28JUt3=Ah^7#Nsk85qQ585k^O85n$I85lxj85p8u85rVZ85mk+85q{e zGB9kGWnkDY%fN74mVx2BECa(|Sq27HIR*wXIR*w}IR=IZIR=I@IR=I{OL6L#MN0EUcNs)meN0EV{RFQ$9T9JXFUXg)en<4|lYefczH;N1l z>`Dv_T1pHI)=CTv$w~|iGnE(^ZYwb`NGmfi_$o6ngex;J#3?f{Bq=j6Br7v8)G9MD zoKt3C_^iypz^cN)ps&Kf5U;|(uvUeE;fo3b1HUQ*gNG^ugQqG3L%%8m!zNV*hC8YZ z4DVGL7`W9K7^Kt~7);d|7#!6Y7`)XO7<|+i7|PTb81|?!F#J_xU@%r^V6atZV6anX zU}#lmU^u7F!0=0*fk9G(fgwdF)(;*F))N^F)+kw zF)(ClF)&nUF)-9>F)-9?F)%b}F)-}VVqiF>#lY}Vi-Cbhn}I=Bn}H!vn}MN3n}MNU zn}K1KHUq;^Z3c!1+6)Z8wHX-1bQl;6br=`|bQl;4bQl;W=`b)X&|zR$qQk(jOoxGC zxef!v104p2KROHyI=T!DmbwfKwYm%pb-D};D|Hzdp6W6%i0Uygi0Lsf80axD1nDs_ z1nV&{RO>M?Ow(gvxTD9wz^%`~prFsd5Twt*5TVb&5Tnn)5U0<;5U~vh73anhB<}|4DSpX7+8!L7^ICD7;=pm7%Gey z80w7}7+Q=N7785o|LGBBu^F)(PDF)(PEF)(PGF)*Z>F)%DJV_;Zs#=vmR UjDdmQoPj~uoPj|UieWV<0Po;R8UO$Q diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache b/build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache deleted file mode 100644 index ab7aec2e5a668a73355d739a315c5daa685ac78a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10664 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 diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache_inline b/build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache_meta b/build/dev/javascript/paint/_gleam_artefacts/paint@encode.cache_meta deleted file mode 100644 index a0d85838d8b2e138a7eb7105dbb930644955e7bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1250 zcmZ>H^gn|E3K&_T3=t@uo|BrGtDjPtmzbNGte=vaoS%{klG0*eVBi8V7#J8JYO;#+ z^RyWl7(5sl7{rie;*;}pb4&9wODgq~^KSyMaq!#5R=IEDH7Niz8GcYjlF)}b@+I1=1(ReVOl@V$W0|NudYLLMob3p1A zGB7Z_W?*38Wn^IBXJlXyU}Ru0XJlZoW@KPE$;iN9$;7}gm5G62CKCgLFf#)~Br^j; z2Qvf1N@fOzoy-gj51APlcv%=2gjg6D)L0l8G*}oIG+7uJ0$3OrN?8~f+F2MFj<7H= zJYZp9c*4TKz{JYHz{1MFz{<+NAj!(W5Wvd7P|V7}P|C`{P{zu@uz;0;VHYa{!z)$> zhS#hN4BuH97}(et80^^?7%JEp7}l~eFg#{sV0g*Kz#ziTz@W~~z~If!z!1;Qz|h6c zz%YrOf#Co<1H&Hv>a3 zHv_{YZU%;9+zbq7xEUDka5FFn@h~uW@h~t{@Gvmc@h~t<=3!ts#KXYwk%xi7fR}+G zgO`CJkC%a=o|l1PBQFEP8(szmO+E&Oay|xzT0RDb1$+z)5BL}uNAxwaQp-X^)VUhp?!wdlih7$q| z3}*xw7|sbWFq{`)VE8M*z+foIz)&E_z_3z~fnl{E1H&3Y28Mfr3=HBz3=BF#3=H8y z3=DZf3=FG<7#Lm&F)+vrGcc$MGcZI8Gcd#pGcY6yGcY6xGcZgPW?U;4iZU>;h%qqmiZL)4h%qp@h%qqah%qqC5My9CA;!RPQH+7%yBGrlw>SfX znK%Q3qc{UYs5k>dhd2Yn3ULO858@0A|HK&>I3*Yu3?&#CtRxs1;v^UtiX<2q=14Fw z9Ft&R_$I-?@Lz&~K}C{*!9tROAyJZnp+S;?VZI~-!+A*th8vO$41XmV7zCvl7_6lj z7&4?77-mQ@Ff5c}U^pbjz;I29f#IJN1A~e*1B0(L14EcJ14F$u1H)u#28ILD3=H?B z85sUaGcf4MFff?QFfdfeFfjDUFfeSDVPLo}!@$5K%fO&7%fMhE%fMhK%fL`7%fQen z%fN6%mVx2CECa(cSq27PIR*xMIR=JoIR=JGIR=InIR=I;atsW6I!Zpt$-NGmWfI4UqO zgeovFv?wqzY*1iexUay#@Irxs;f(?V!#f2AhW82#3=)bA491EK3`vR%3@K0yD;)q; C!?~*f diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@event.cache b/build/dev/javascript/paint/_gleam_artefacts/paint@event.cache deleted file mode 100644 index 787d70de55eca5d48fdd80fc7795bed9f199ffdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9101 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 diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache b/build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache deleted file mode 100644 index f7d3a724dfe6868290a132205977c0dee90e914c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16937 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 Q4Wgd%z64QUd4KW(043g-GXMYp diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache_inline b/build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache_meta b/build/dev/javascript/paint/_gleam_artefacts/paint@internal@impl_canvas.cache_meta deleted file mode 100644 index db2fae1046593a2b093df03f6ce20e110850a64e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 525 zcmcC}{6B*M3K*d@L-6a*C$~w;R+qyB7#J927#J9285kJy85kI*FfcGoWnf@9#=yX! z$jHEu$;iNv#mK<0myv;iiHU)MnTdfRh>3w=J`)4O0wxBA?Mw^|JD3<4n3x$DjF}l2 zOqdxMJeV06Jee67CNMKFJYZ&Ec*xAaV93J2;KRbekjTQo(8I#Ou#km;;TQ`8!vz)w zhKno=3}UPd44$kE3|_1Z3=>!x7>=+qFdSuNVBltBV6bCjV6bOnU}$AyVA#pVz_5#r zf#EkB1A_)T1A`_z14AY|1H)8y28L zax*Y^aWgPX;bvgC!Og&MlbeCTfQNyhfro*ik%xid01pGh86F0P=R6DyKX@1zICvQt z#CRDPRCpN}On4a>Y^X;WaM23I}?hCV(9hJHQE%m4)dKM+Jn diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache b/build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache deleted file mode 100644 index 72e9025e695d3aa96a89732ed095dd1d5353ac67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14729 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 Biv$1w diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache_inline b/build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache_meta b/build/dev/javascript/paint/_gleam_artefacts/paint@internal@types.cache_meta deleted file mode 100644 index b521eaed65924bcf0341f2511db397d836e1910a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 283 zcmZ>H^gn|E3K$uo3^6F3o|BrG8=st?n_HTfSyHK=oS&0lS_G2RW?*2bIQfdt{jo71d=rS-cI503U_%JXqgn-mBFfc4C6la8O#g} tP0S1o+n5;`b}%zA>||zOIK|AsaGRNd;Vv@+!#!pOhIh;$$3ZdFF948hC&&N* diff --git a/build/dev/javascript/paint/gleam.mjs b/build/dev/javascript/paint/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/build/dev/javascript/paint/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/build/dev/javascript/paint/impl_canvas_bindings.mjs b/build/dev/javascript/paint/impl_canvas_bindings.mjs deleted file mode 100644 index 5fed16a..0000000 --- a/build/dev/javascript/paint/impl_canvas_bindings.mjs +++ /dev/null @@ -1,271 +0,0 @@ -import { Ok, Error } from "./gleam.mjs"; - -class PaintCanvas extends HTMLElement { - // Open an issue if you are in need of any other attributes :) - static observedAttributes = ["width", "height", "style", "picture"]; - - constructor() { - super(); - // Create a canvas - this.canvas = document.createElement("canvas"); - const style = document.createElement("style"); - style.textContent = ` - :host { - display: inline-block; - } - `; - this.shadow = this.attachShadow({ mode: "open" }); - this.shadow.appendChild(style); - this.shadow.appendChild(this.canvas); - this.ctx = this.canvas.getContext("2d"); - } - - attributeChangedCallback(name, _oldValue, newValue) { - if (name === "picture") { - this.picture = newValue; - return; - } else if (name === "width") { - this.width = newValue; - } else if (name === "height") { - this.height = newValue; - } - } - - drawPicture() { - if (!this.pictureString) { - return; - } - - this.ctx.reset(); - const display = - window.PAINT_STATE[ - "display_on_rendering_context_with_default_drawing_state" - ]; - - display(this.pictureString, this.ctx); - } - - set picture(value) { - this.pictureString = value; - this.drawPicture(); - } - - set width(value) { - this.canvas.width = value; - this.drawPicture(); - } - - set height(value) { - this.canvas.height = value; - this.drawPicture(); - } - - get width() { - return this.canvas.width; - } - - get height() { - return this.canvas.height; - } -} - -export function define_web_component() { - window.customElements.define("paint-canvas", PaintCanvas); -} - -export function get_rendering_context(selector) { - // TODO: Handle the case where the canvas element is not found. - return document.querySelector(selector).getContext("2d"); -} - -export function setup_request_animation_frame(callback) { - window.requestAnimationFrame((time) => { - callback(time); - }); -} - -export function setup_input_handler(event_name, callback) { - window.addEventListener(event_name, callback); -} - -export function get_key_code(event) { - return event.keyCode; -} - -export function set_global(state, id) { - if (typeof window.PAINT_STATE == "undefined") { - window.PAINT_STATE = {}; - } - window.PAINT_STATE[id] = state; -} - -export function get_global(id) { - if (!window.PAINT_STATE) { - return new Error(undefined); - } - if (!(id in window.PAINT_STATE)) { - return new Error(undefined); - } - return new Ok(window.PAINT_STATE[id]); -} - -export function get_width(ctx) { - return ctx.canvas.clientWidth; -} - -export function get_height(ctx) { - return ctx.canvas.clientHeight; -} - -// Based on https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas -export function mouse_pos(ctx, event) { - // Calculate the scaling of the canvas vs its content - const rect = ctx.canvas.getBoundingClientRect(); - const scaleX = ctx.canvas.width / rect.width; - const scaleY = ctx.canvas.height / rect.height; - - return [ - (event.clientX - rect.left) * scaleX, - (event.clientY - rect.top) * scaleY, - ]; -} - -// if check_pressed is true, the function will return true if the button was pressed -// if check_pressed is false, the function will return true if the button was released -export function check_mouse_button( - event, - previous_event, - button_index, - check_pressed, -) { - let previous_buttons = previous_event?.buttons ?? 0; - let current_buttons = event.buttons; - - // ~001 && - // 011 - // ----- - // 010 found the newly pressed! - // - // 011 && - // ~001 - // ----- - // 010 found the newly released! - if (check_pressed) { - previous_buttons = ~previous_buttons; - } else { - current_buttons = ~current_buttons; - } - - let button = previous_buttons & current_buttons & (1 << button_index); - return !!button; -} - -export function reset(ctx) { - ctx.reset(); -} - -export function arc(ctx, radius, start, end, fill, stroke) { - ctx.beginPath(); - ctx.arc(0, 0, radius, start, end); - if (fill) { - ctx.fill(); - } - if (stroke) { - ctx.stroke(); - } -} - -export function polygon(ctx, points, closed, fill, stroke) { - ctx.beginPath(); - ctx.moveTo(0, 0); - let started = false; - for (const point of points) { - let x = point[0]; - let y = point[1]; - if (started) { - ctx.lineTo(x, y); - } else { - ctx.moveTo(x, y); - started = true; - } - } - - if (closed) { - ctx.closePath(); - } - - if (fill && closed) { - ctx.fill(); - } - - if (stroke) { - ctx.stroke(); - } -} - -export function text(ctx, text, style) { - ctx.font = style; - ctx.fillText(text, 0, 0); -} - -export function save(ctx) { - ctx.save(); -} - -export function restore(ctx) { - ctx.restore(); -} - -export function set_fill_colour(ctx, css_colour) { - ctx.fillStyle = css_colour; -} - -export function set_stroke_color(ctx, css_color) { - ctx.strokeStyle = css_color; -} - -export function set_line_width(ctx, width) { - ctx.lineWidth = width; -} - -export function translate(ctx, x, y) { - ctx.translate(x, y); -} - -export function scale(ctx, x, y) { - ctx.scale(x, y); -} - -export function rotate(ctx, radians) { - ctx.rotate(radians); -} - -export function reset_transform(ctx) { - ctx.resetTransform(); -} - -export function draw_image(ctx, image, width_px, height_px) { - ctx.drawImage(image, 0, 0, width_px, height_px); -} - -export function image_from_query(selector) { - return document.querySelector(selector); -} - -export function image_from_src(src) { - const image = new Image(); - image.src = src; - return image; -} - -export function on_image_load(image, callback) { - if (image.complete) { - callback(); - } else { - image.addEventListener("load", callback); - } -} - -export function set_image_smoothing_enabled(ctx, value) { - ctx.imageSmoothingEnabled = value; -} diff --git a/build/dev/javascript/paint/numbers_ffi.mjs b/build/dev/javascript/paint/numbers_ffi.mjs deleted file mode 100644 index 0e6e6d3..0000000 --- a/build/dev/javascript/paint/numbers_ffi.mjs +++ /dev/null @@ -1,3 +0,0 @@ -export function pi() { - return Math.PI; -} diff --git a/build/dev/javascript/paint/paint.mjs b/build/dev/javascript/paint/paint.mjs deleted file mode 100644 index ba06945..0000000 --- a/build/dev/javascript/paint/paint.mjs +++ /dev/null @@ -1,246 +0,0 @@ -import * as $colour from "../gleam_community_colour/gleam_community/colour.mjs"; -import * as $result from "../gleam_stdlib/gleam/result.mjs"; -import { toList, makeError } from "./gleam.mjs"; -import { pi } from "./numbers_ffi.mjs"; -import * as $internal_implementation from "./paint/internal/types.mjs"; - -const FILEPATH = "src/paint.gleam"; - -/** - * Create an angle expressed in radians - */ -export function angle_rad(radians) { - return new $internal_implementation.Radians(radians); -} - -/** - * A utility around [colour.from_rgb_hex_string](https://hexdocs.pm/gleam_community_colour/gleam_community/colour.html#from_rgb_hex_string) - * (from `gleam_community/colour`) that **panics** on an invalid hex code. - */ -export function colour_hex(string) { - return $result.lazy_unwrap( - $colour.from_rgb_hex_string(string), - () => { - throw makeError( - "panic", - FILEPATH, - "paint", - 47, - "colour_hex", - "Failed to parse hex code", - {} - ) - }, - ); -} - -/** - * A utility around [colour.from_rgb255](https://hexdocs.pm/gleam_community_colour/gleam_community/colour.html#from_rgb255) - * (from `gleam_community/colour`) that **panics** if the values are outside of the allowed range. - */ -export function colour_rgb(red, green, blue) { - return $result.lazy_unwrap( - $colour.from_rgb255(red, green, blue), - () => { - throw makeError( - "panic", - FILEPATH, - "paint", - 55, - "colour_rgb", - "The value was not inside of the valid range [0-255]", - {} - ) - }, - ); -} - -/** - * A blank picture - */ -export function blank() { - return new $internal_implementation.Blank(); -} - -/** - * An arc with some radius going from some - * starting angle to some other angle in clock-wise direction - */ -export function arc(radius, start, end) { - return new $internal_implementation.Arc(radius, start, end); -} - -/** - * A polygon consisting of a list of 2d points - */ -export function polygon(points) { - return new $internal_implementation.Polygon(points, true); -} - -/** - * Lines (same as a polygon but not a closed shape) - */ -export function lines(points) { - return new $internal_implementation.Polygon(points, false); -} - -/** - * A rectangle with some given width and height - */ -export function rectangle(width, height) { - return polygon( - toList([[0.0, 0.0], [width, 0.0], [width, height], [0.0, height]]), - ); -} - -/** - * A square - */ -export function square(length) { - return rectangle(length, length); -} - -/** - * Draw an image such as a PNG, JPEG or an SVG. See the `canvas` back-end for more details on how to load images. - */ -export function image(image, width_px, height_px) { - return new $internal_implementation.ImageRef(image, width_px, height_px); -} - -/** - * Set image scaling to be smooth (this is the default behaviour) - */ -export function image_scaling_smooth(picture) { - return new $internal_implementation.ImageScalingBehaviour( - picture, - new $internal_implementation.ScalingSmooth(), - ); -} - -/** - * Disable smooth image scaling, suitable for pixel art. - */ -export function image_scaling_pixelated(picture) { - return new $internal_implementation.ImageScalingBehaviour( - picture, - new $internal_implementation.ScalingPixelated(), - ); -} - -/** - * Text with some given font size - */ -export function text(text, font_size) { - return new $internal_implementation.Text( - text, - new $internal_implementation.FontProperties(font_size, "sans-serif"), - ); -} - -/** - * Translate a picture in horizontal and vertical direction - */ -export function translate_xy(picture, x, y) { - return new $internal_implementation.Translate(picture, [x, y]); -} - -/** - * Translate a picture in the horizontal direction - */ -export function translate_x(picture, x) { - return translate_xy(picture, x, 0.0); -} - -/** - * Translate a picture in the vertical direction - */ -export function translate_y(picture, y) { - return translate_xy(picture, 0.0, y); -} - -/** - * Scale the picture in the horizontal direction - */ -export function scale_x(picture, factor) { - return new $internal_implementation.Scale(picture, [factor, 1.0]); -} - -/** - * Scale the picture in the vertical direction - */ -export function scale_y(picture, factor) { - return new $internal_implementation.Scale(picture, [1.0, factor]); -} - -/** - * Scale the picture uniformly in horizontal and vertical direction - */ -export function scale_uniform(picture, factor) { - return new $internal_implementation.Scale(picture, [factor, factor]); -} - -/** - * Rotate the picture in a clock-wise direction - */ -export function rotate(picture, angle) { - return new $internal_implementation.Rotate(picture, angle); -} - -/** - * Fill a picture with some given colour, see `Colour`. - */ -export function fill(picture, colour) { - return new $internal_implementation.Fill(picture, colour); -} - -/** - * Set a solid stroke with some given colour and width - */ -export function stroke(picture, colour, width) { - return new $internal_implementation.Stroke( - picture, - new $internal_implementation.SolidStroke(colour, width), - ); -} - -/** - * Remove the stroke of the given picture - */ -export function stroke_none(picture) { - return new $internal_implementation.Stroke( - picture, - new $internal_implementation.NoStroke(), - ); -} - -/** - * Combine multiple pictures into one - */ -export function combine(pictures) { - return new $internal_implementation.Combine(pictures); -} - -/** - * Concatenate two pictures - */ -export function concat(picture, another_picture) { - return combine(toList([picture, another_picture])); -} - -/** - * Create an angle expressed in degrees - */ -export function angle_deg(degrees) { - return new $internal_implementation.Radians(((degrees * pi())) / 180.0); -} - -/** - * A circle with some given radius - */ -export function circle(radius) { - return new $internal_implementation.Arc( - radius, - new $internal_implementation.Radians(0.0), - new $internal_implementation.Radians(2.0 * pi()), - ); -} diff --git a/build/dev/javascript/paint/paint/canvas.mjs b/build/dev/javascript/paint/paint/canvas.mjs deleted file mode 100644 index 1bb61c7..0000000 --- a/build/dev/javascript/paint/paint/canvas.mjs +++ /dev/null @@ -1,655 +0,0 @@ -import * as $colour from "../../gleam_community_colour/gleam_community/colour.mjs"; -import * as $int from "../../gleam_stdlib/gleam/int.mjs"; -import * as $option from "../../gleam_stdlib/gleam/option.mjs"; -import { None, Some } from "../../gleam_stdlib/gleam/option.mjs"; -import { Ok, Empty as $Empty, CustomType as $CustomType, makeError } from "../gleam.mjs"; -import * as $paint from "../paint.mjs"; -import { translate_xy } from "../paint.mjs"; -import * as $encode from "../paint/encode.mjs"; -import * as $event from "../paint/event.mjs"; -import * as $impl_canvas from "../paint/internal/impl_canvas.mjs"; -import * as $types from "../paint/internal/types.mjs"; -import { - Arc, - Blank, - Combine, - Fill, - FontProperties, - Image, - NoStroke, - Polygon, - Radians, - Rotate, - Scale, - SolidStroke, - Stroke, - Text, - Translate, -} from "../paint/internal/types.mjs"; - -const FILEPATH = "src/paint/canvas.gleam"; - -export class Config extends $CustomType { - constructor(width, height) { - super(); - this.width = width; - this.height = height; - } -} -export const Config$Config = (width, height) => new Config(width, height); -export const Config$isConfig = (value) => value instanceof Config; -export const Config$Config$width = (value) => value.width; -export const Config$Config$0 = (value) => value.width; -export const Config$Config$height = (value) => value.height; -export const Config$Config$1 = (value) => value.height; - -class DrawingState extends $CustomType { - constructor(fill, stroke) { - super(); - this.fill = fill; - this.stroke = stroke; - } -} - -/** - * Create a reference to an image using a CSS query selector. For example: - * ``` - * fn kitten() { - * canvas.image_from_query("#kitten") - * } - * // In the HTML file: - * // - * ``` - * - * > [!WARNING] - * > **Important**: Make sure the image has loaded before trying to draw a pictures referencing it. - * > You can do this using `canvas.wait_until_loaded` function. - */ -export function image_from_query(selector) { - let id = "image-selector-" + selector; - let $ = $impl_canvas.get_global(id); - if ($ instanceof Ok) { - undefined - } else { - let image = $impl_canvas.image_from_query(selector); - $impl_canvas.set_global(image, id) - } - return new Image(id); -} - -/** - * Create a reference to an image using a source path. - * ``` - * fn my_logo_image() { - * canvas.image_from_src("./priv/static/logo.svg") - * } - * ``` - * - * > [!WARNING] - * > **Important**: Make sure the image has loaded before trying to draw a pictures referencing it. - * > You can do this using `canvas.wait_until_loaded` function. - */ -export function image_from_src(src) { - let id = "image-src-" + src; - let $ = $impl_canvas.get_global(id); - if ($ instanceof Ok) { - undefined - } else { - let image = $impl_canvas.image_from_src(src); - $impl_canvas.set_global(image, id) - } - return new Image(id); -} - -/** - * Wait until a list of images have all been loaded, for example: - * ``` - * fn lucy() { - * canvas.image_from_query("#lucy") - * } - * - * fn cat() { - * canvas.image_from_src("./path/to/kitten.png") - * } - * - * pub fn main() { - * use <- canvas.wait_until_loaded([lucy(), kitten()]) - * // It is now safe to draw Pictures containing the images lucy and kitten :) - * } - * ``` - */ -export function wait_until_loaded(images, on_loaded) { - if (images instanceof $Empty) { - return on_loaded(); - } else { - let image = images.head; - let rest = images.tail; - let id; - id = image.id; - let $ = $impl_canvas.get_global(id); - let js_image; - if ($ instanceof Ok) { - js_image = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 101, - "wait_until_loaded", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 3025, - end: 3077, - pattern_start: 3036, - pattern_end: 3048 - } - ) - } - return $impl_canvas.on_image_load( - js_image, - () => { return wait_until_loaded(rest, on_loaded); }, - ); - } -} - -function display_on_rendering_context(loop$picture, loop$ctx, loop$state) { - while (true) { - let picture = loop$picture; - let ctx = loop$ctx; - let state = loop$state; - if (picture instanceof Blank) { - return undefined; - } else if (picture instanceof Polygon) { - let points = picture[0]; - let closed = picture.closed; - return $impl_canvas.polygon(ctx, points, closed, state.fill, state.stroke); - } else if (picture instanceof Arc) { - let radius = picture.radius; - let start = picture.start; - let end = picture.end; - let start_radians; - start_radians = start[0]; - let end_radians; - end_radians = end[0]; - return $impl_canvas.arc( - ctx, - radius, - start_radians, - end_radians, - state.fill, - state.stroke, - ); - } else if (picture instanceof Text) { - let text = picture.text; - let properties = picture.style; - let size_px; - let font_family; - size_px = properties.size_px; - font_family = properties.font_family; - $impl_canvas.save(ctx); - $impl_canvas.text( - ctx, - text, - ($int.to_string(size_px) + "px ") + font_family, - ); - return $impl_canvas.restore(ctx); - } else if (picture instanceof $types.ImageRef) { - let width_px = picture.width_px; - let height_px = picture.height_px; - let id = picture[0].id; - let $ = $impl_canvas.get_global(id); - let image; - if ($ instanceof Ok) { - image = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 231, - "display_on_rendering_context", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 6608, - end: 6657, - pattern_start: 6619, - pattern_end: 6628 - } - ) - } - return $impl_canvas.draw_image(ctx, image, width_px, height_px); - } else if (picture instanceof Fill) { - let p = picture[0]; - let colour = picture[1]; - $impl_canvas.save(ctx); - $impl_canvas.set_fill_colour(ctx, $colour.to_css_rgba_string(colour)); - display_on_rendering_context(p, ctx, new DrawingState(true, state.stroke)); - return $impl_canvas.restore(ctx); - } else if (picture instanceof Stroke) { - let p = picture[0]; - let stroke = picture[1]; - if (stroke instanceof NoStroke) { - loop$picture = p; - loop$ctx = ctx; - loop$state = new DrawingState(state.fill, false); - } else { - let color = stroke[0]; - let width = stroke[1]; - $impl_canvas.save(ctx); - $impl_canvas.set_stroke_color(ctx, $colour.to_css_rgba_string(color)); - $impl_canvas.set_line_width(ctx, width); - display_on_rendering_context(p, ctx, new DrawingState(state.fill, true)); - return $impl_canvas.restore(ctx); - } - } else if (picture instanceof $types.ImageScalingBehaviour) { - let p = picture[0]; - let behaviour = picture[1]; - $impl_canvas.save(ctx); - $impl_canvas.set_image_smoothing_enabled( - ctx, - (() => { - if (behaviour instanceof $types.ScalingSmooth) { - return true; - } else { - return false; - } - })(), - ); - display_on_rendering_context(p, ctx, state); - return $impl_canvas.restore(ctx); - } else if (picture instanceof Translate) { - let p = picture[0]; - let vec = picture[1]; - let x; - let y; - x = vec[0]; - y = vec[1]; - $impl_canvas.save(ctx); - $impl_canvas.translate(ctx, x, y); - display_on_rendering_context(p, ctx, state); - return $impl_canvas.restore(ctx); - } else if (picture instanceof Scale) { - let p = picture[0]; - let vec = picture[1]; - let x; - let y; - x = vec[0]; - y = vec[1]; - $impl_canvas.save(ctx); - $impl_canvas.scale(ctx, x, y); - display_on_rendering_context(p, ctx, state); - return $impl_canvas.restore(ctx); - } else if (picture instanceof Rotate) { - let p = picture[0]; - let angle = picture[1]; - let rad; - rad = angle[0]; - $impl_canvas.save(ctx); - $impl_canvas.rotate(ctx, rad); - display_on_rendering_context(p, ctx, state); - return $impl_canvas.restore(ctx); - } else { - let pictures = picture[0]; - if (pictures instanceof $Empty) { - return undefined; - } else { - let p = pictures.head; - let ps = pictures.tail; - display_on_rendering_context(p, ctx, state); - loop$picture = new Combine(ps); - loop$ctx = ctx; - loop$state = state; - } - } - } -} - -function parse_key_code(key_code) { - if (key_code === 32) { - return new Some(new $event.KeySpace()); - } else if (key_code === 37) { - return new Some(new $event.KeyLeftArrow()); - } else if (key_code === 38) { - return new Some(new $event.KeyUpArrow()); - } else if (key_code === 39) { - return new Some(new $event.KeyRightArrow()); - } else if (key_code === 40) { - return new Some(new $event.KeyDownArrow()); - } else if (key_code === 87) { - return new Some(new $event.KeyW()); - } else if (key_code === 65) { - return new Some(new $event.KeyA()); - } else if (key_code === 83) { - return new Some(new $event.KeyS()); - } else if (key_code === 68) { - return new Some(new $event.KeyD()); - } else if (key_code === 90) { - return new Some(new $event.KeyZ()); - } else if (key_code === 88) { - return new Some(new $event.KeyX()); - } else if (key_code === 67) { - return new Some(new $event.KeyC()); - } else if (key_code === 18) { - return new Some(new $event.KeyEnter()); - } else if (key_code === 27) { - return new Some(new $event.KeyEscape()); - } else if (key_code === 8) { - return new Some(new $event.KeyBackspace()); - } else { - return new None(); - } -} - -/** - * Utility to set the origin in the center of the canvas - */ -export function center(picture) { - return (config) => { - let width; - let height; - width = config.width; - height = config.height; - let _pipe = picture; - return translate_xy(_pipe, width * 0.5, height * 0.5); - }; -} - -const default_drawing_state = /* @__PURE__ */ new DrawingState(false, true); - -/** - * Display a picture on a HTML canvas element - * (specified by some [CSS Selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)). - * ``` - * canvas.display(fn (_: canvas.Config) { circle(50.0) }, "#mycanvas") - * ``` - */ -export function display(init, selector) { - let ctx = $impl_canvas.get_rendering_context(selector); - $impl_canvas.reset(ctx); - let picture = init( - new Config($impl_canvas.get_width(ctx), $impl_canvas.get_height(ctx)), - ); - return display_on_rendering_context(picture, ctx, default_drawing_state); -} - -function get_tick_func(ctx, view, update, selector) { - return (time) => { - let $ = $impl_canvas.get_global(selector); - let current_state; - if ($ instanceof Ok) { - current_state = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 399, - "get_tick_func", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 11581, - end: 11644, - pattern_start: 11592, - pattern_end: 11609 - } - ) - } - let new_state = update(current_state, new $event.Tick(time)); - $impl_canvas.set_global(new_state, selector); - let picture = view(new_state); - $impl_canvas.reset(ctx); - display_on_rendering_context(picture, ctx, default_drawing_state); - return $impl_canvas.setup_request_animation_frame( - get_tick_func(ctx, view, update, selector), - ); - }; -} - -/** - * Animations, interactive applications and tiny games can be built using the - * `interact` function. It roughly follows the [Elm architecture](https://guide.elm-lang.org/architecture/). - * Here is a short example: - * ``` - * type State = - * Int - * - * fn init(_: canvas.Config) -> State { - * 0 - * } - * - * fn update(state: State, event: event.Event) -> State { - * case event { - * event.Tick(_) -> state + 1 - * _ -> state - * } - * } - * - * fn view(state: State) -> Picture { - * paint.circle(int.to_float(state)) - * } - * - * fn main() { - * interact(init, update, view, "#mycanvas") - * } - * ``` - */ -export function interact(init, update, view, selector) { - let ctx = $impl_canvas.get_rendering_context(selector); - let initial_state = init( - new Config($impl_canvas.get_width(ctx), $impl_canvas.get_height(ctx)), - ); - $impl_canvas.set_global(initial_state, selector); - let create_key_handler = (event_name, constructor) => { - return $impl_canvas.setup_input_handler( - event_name, - (event) => { - let key = parse_key_code($impl_canvas.get_key_code(event)); - if (key instanceof Some) { - let key$1 = key[0]; - let $ = $impl_canvas.get_global(selector); - let old_state; - if ($ instanceof Ok) { - old_state = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 292, - "interact", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 8332, - end: 8391, - pattern_start: 8343, - pattern_end: 8356 - } - ) - } - let new_state = update(old_state, constructor(key$1)); - return $impl_canvas.set_global(new_state, selector); - } else { - return undefined; - } - }, - ); - }; - create_key_handler( - "keydown", - (var0) => { return new $event.KeyboardPressed(var0); }, - ); - create_key_handler( - "keyup", - (var0) => { return new $event.KeyboardRelased(var0); }, - ); - $impl_canvas.setup_input_handler( - "mousemove", - (event) => { - let $ = $impl_canvas.mouse_pos(ctx, event); - let x; - let y; - x = $[0]; - y = $[1]; - let $1 = $impl_canvas.get_global(selector); - let old_state; - if ($1 instanceof Ok) { - old_state = $1[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 309, - "interact", - "Pattern match failed, no pattern matched the value.", - { - value: $1, - start: 8863, - end: 8922, - pattern_start: 8874, - pattern_end: 8887 - } - ) - } - let new_state = update(old_state, new $event.MouseMoved(x, y)); - $impl_canvas.set_global(new_state, selector); - return undefined; - }, - ); - let create_mouse_button_handler = (event_name, constructor, check_pressed) => { - return $impl_canvas.setup_input_handler( - event_name, - (event) => { - let previous_event_id = "PAINT_PREVIOUS_MOUSE_INPUT_FOR_" + selector; - let previous_event = $impl_canvas.get_global(previous_event_id); - $impl_canvas.set_global(event, previous_event_id); - let check_button = (i) => { - return $impl_canvas.check_mouse_button( - event, - previous_event, - i, - check_pressed, - ); - }; - let trigger_update = (button) => { - let $ = $impl_canvas.get_global(selector); - let old_state; - if ($ instanceof Ok) { - old_state = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 338, - "interact", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 9856, - end: 9915, - pattern_start: 9867, - pattern_end: 9880 - } - ) - } - let new_state = update(old_state, constructor(button)); - return $impl_canvas.set_global(new_state, selector); - }; - let $ = check_button(0); - if ($) { - trigger_update(new $event.MouseButtonLeft()) - } else { - undefined - } - let $1 = check_button(1); - if ($1) { - trigger_update(new $event.MouseButtonRight()) - } else { - undefined - } - let $2 = check_button(2); - if ($2) { - trigger_update(new $event.MouseButtonMiddle()) - } else { - undefined - } - return undefined; - }, - ); - }; - create_mouse_button_handler( - "mousedown", - (var0) => { return new $event.MousePressed(var0); }, - true, - ); - create_mouse_button_handler( - "mouseup", - (var0) => { return new $event.MouseReleased(var0); }, - false, - ); - return $impl_canvas.setup_request_animation_frame( - get_tick_func(ctx, view, update, selector), - ); -} - -/** - * If you are using [Lustre](https://github.com/lustre-labs/lustre) or some other framework to build - * your web application you may prefer to use the [web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) API - * and the `define_web_component` function. - * ``` - * // Call this function once to register a custom HTML element - * canvas.define_web_component() - * // You can then display your picture by setting the "picture" - * // property or attribute on the element. - * - * // In Lustre it would look something like this: - * fn canvas(picture: paint.Picture, attributes: List(attribute.Attribute(a))) { - * element.element( - * "paint-canvas", - * [attribute.attribute("picture", encode.to_string(picture)), ..attributes], - * [], - * ) - *} - * ``` - * A more detailed example for using this API can be found in the `demos/with_lustre` directory. - */ -export function define_web_component() { - $impl_canvas.define_web_component(); - return $impl_canvas.set_global( - (encoded_picture, ctx) => { - let $ = $encode.from_string(encoded_picture); - let picture; - if ($ instanceof Ok) { - picture = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "paint/canvas", - 447, - "define_web_component", - "Invalid picture provided to web component", - { - value: $, - start: 13602, - end: 13662, - pattern_start: 13613, - pattern_end: 13624 - } - ) - } - return display_on_rendering_context(picture, ctx, default_drawing_state); - }, - "display_on_rendering_context_with_default_drawing_state", - ); -} diff --git a/build/dev/javascript/paint/paint/encode.mjs b/build/dev/javascript/paint/paint/encode.mjs deleted file mode 100644 index f9b88f3..0000000 --- a/build/dev/javascript/paint/paint/encode.mjs +++ /dev/null @@ -1,506 +0,0 @@ -import * as $colour from "../../gleam_community_colour/gleam_community/colour.mjs"; -import * as $json from "../../gleam_json/gleam/json.mjs"; -import * as $decode from "../../gleam_stdlib/gleam/dynamic/decode.mjs"; -import { toList } from "../gleam.mjs"; -import * as $paint from "../paint.mjs"; -import * as $types from "../paint/internal/types.mjs"; -import { FontProperties, NoStroke, Radians, SolidStroke } from "../paint/internal/types.mjs"; - -function decode_angle() { - return $decode.field( - "radians", - $decode.float, - (radians) => { return $decode.success(new Radians(radians)); }, - ); -} - -function decode_font() { - return $decode.field( - "sizePx", - $decode.int, - (size_px) => { - return $decode.field( - "fontFamily", - $decode.string, - (font_family) => { - return $decode.success(new FontProperties(size_px, font_family)); - }, - ); - }, - ); -} - -function decode_stroke() { - return $decode.field( - "type", - $decode.string, - (stroke_type) => { - if (stroke_type === "noStroke") { - return $decode.success(new NoStroke()); - } else if (stroke_type === "solidStroke") { - return $decode.field( - "colour", - $colour.decoder(), - (colour) => { - return $decode.field( - "thickness", - $decode.float, - (thickness) => { - return $decode.success(new SolidStroke(colour, thickness)); - }, - ); - }, - ); - } else { - return $decode.failure(new NoStroke(), "StrokeProperties"); - } - }, - ); -} - -function decode_vec2() { - return $decode.field( - "x", - $decode.float, - (x) => { - return $decode.field( - "y", - $decode.float, - (y) => { return $decode.success([x, y]); }, - ); - }, - ); -} - -function decode_picture() { - return $decode.recursive( - () => { - return $decode.field( - "type", - $decode.string, - (ty) => { - if (ty === "arc") { - return $decode.field( - "radius", - $decode.float, - (radius) => { - return $decode.field( - "start", - decode_angle(), - (start) => { - return $decode.field( - "end", - decode_angle(), - (end) => { - return $decode.success( - new $types.Arc(radius, start, end), - ); - }, - ); - }, - ); - }, - ); - } else if (ty === "blank") { - return $decode.success(new $types.Blank()); - } else if (ty === "combine") { - return $decode.field( - "pictures", - $decode.list(decode_picture()), - (pictures) => { - return $decode.success(new $types.Combine(pictures)); - }, - ); - } else if (ty === "fill") { - return $decode.field( - "picture", - decode_picture(), - (picture) => { - return $decode.field( - "colour", - $colour.decoder(), - (colour) => { - return $decode.success(new $types.Fill(picture, colour)); - }, - ); - }, - ); - } else if (ty === "polygon") { - return $decode.field( - "points", - $decode.list(decode_vec2()), - (points) => { - return $decode.field( - "closed", - $decode.bool, - (closed) => { - return $decode.success(new $types.Polygon(points, closed)); - }, - ); - }, - ); - } else if (ty === "rotate") { - return $decode.field( - "angle", - decode_angle(), - (angle) => { - return $decode.field( - "picture", - decode_picture(), - (picture) => { - return $decode.success(new $types.Rotate(picture, angle)); - }, - ); - }, - ); - } else if (ty === "scale") { - return $decode.field( - "x", - $decode.float, - (x) => { - return $decode.field( - "y", - $decode.float, - (y) => { - return $decode.field( - "picture", - decode_picture(), - (picture) => { - return $decode.success( - new $types.Scale(picture, [x, y]), - ); - }, - ); - }, - ); - }, - ); - } else if (ty === "stroke") { - return $decode.field( - "stroke", - decode_stroke(), - (stroke) => { - return $decode.field( - "picture", - decode_picture(), - (picture) => { - return $decode.success(new $types.Stroke(picture, stroke)); - }, - ); - }, - ); - } else if (ty === "text") { - return $decode.field( - "text", - $decode.string, - (text) => { - return $decode.field( - "style", - decode_font(), - (style) => { - return $decode.success(new $types.Text(text, style)); - }, - ); - }, - ); - } else if (ty === "translate") { - return $decode.field( - "x", - $decode.float, - (x) => { - return $decode.field( - "y", - $decode.float, - (y) => { - return $decode.field( - "picture", - decode_picture(), - (picture) => { - return $decode.success( - new $types.Translate(picture, [x, y]), - ); - }, - ); - }, - ); - }, - ); - } else if (ty === "image") { - return $decode.field( - "id", - $decode.string, - (id) => { - return $decode.field( - "width_px", - $decode.int, - (width_px) => { - return $decode.field( - "height_px", - $decode.int, - (height_px) => { - return $decode.success( - new $types.ImageRef( - new $types.Image(id), - width_px, - height_px, - ), - ); - }, - ); - }, - ); - }, - ); - } else if (ty === "image_scaling_behaviour") { - return $decode.field( - "behaviour", - $decode.string, - (behaviour) => { - return $decode.field( - "picture", - decode_picture(), - (picture) => { - if (behaviour === "smooth") { - return $decode.success( - new $types.ImageScalingBehaviour( - picture, - new $types.ScalingSmooth(), - ), - ); - } else if (behaviour === "pixelated") { - return $decode.success( - new $types.ImageScalingBehaviour( - picture, - new $types.ScalingPixelated(), - ), - ); - } else { - return $decode.failure(new $types.Blank(), "Picture"); - } - }, - ); - }, - ); - } else { - return $decode.failure(new $types.Blank(), "Picture"); - } - }, - ); - }, - ); -} - -/** - * Attempt to deserialize a `Picture` - */ -export function from_string(string) { - let decoder = $decode.field( - "picture", - decode_picture(), - (picture) => { return $decode.success(picture); }, - ); - return $json.parse(string, decoder); -} - -function font_to_json(font) { - let size_px; - let font_family; - size_px = font.size_px; - font_family = font.font_family; - return $json.object( - toList([ - ["sizePx", $json.int(size_px)], - ["fontFamily", $json.string(font_family)], - ]), - ); -} - -function stroke_to_json(stroke) { - if (stroke instanceof NoStroke) { - return $json.object(toList([["type", $json.string("noStroke")]])); - } else { - let colour = stroke[0]; - let thickness = stroke[1]; - return $json.object( - toList([ - ["type", $json.string("solidStroke")], - ["colour", $colour.encode(colour)], - ["thickness", $json.float(thickness)], - ]), - ); - } -} - -function angle_to_json(angle) { - let rad; - rad = angle[0]; - return $json.object(toList([["radians", $json.float(rad)]])); -} - -function picture_to_json(picture) { - if (picture instanceof $types.Blank) { - return $json.object(toList([["type", $json.string("blank")]])); - } else if (picture instanceof $types.Polygon) { - let points = picture[0]; - let closed = picture.closed; - return $json.object( - toList([ - ["type", $json.string("polygon")], - [ - "points", - $json.array( - points, - (point) => { - let x; - let y; - x = point[0]; - y = point[1]; - return $json.object( - toList([["x", $json.float(x)], ["y", $json.float(y)]]), - ); - }, - ), - ], - ["closed", $json.bool(closed)], - ]), - ); - } else if (picture instanceof $types.Arc) { - let radius = picture.radius; - let start = picture.start; - let end = picture.end; - return $json.object( - toList([ - ["type", $json.string("arc")], - ["radius", $json.float(radius)], - ["start", angle_to_json(start)], - ["end", angle_to_json(end)], - ]), - ); - } else if (picture instanceof $types.Text) { - let text = picture.text; - let style = picture.style; - return $json.object( - toList([ - ["type", $json.string("text")], - ["text", $json.string(text)], - ["style", font_to_json(style)], - ]), - ); - } else if (picture instanceof $types.ImageRef) { - let width_px = picture.width_px; - let height_px = picture.height_px; - let id = picture[0].id; - return $json.object( - toList([ - ["type", $json.string("image")], - ["id", $json.string(id)], - ["width_px", $json.int(width_px)], - ["height_px", $json.int(height_px)], - ]), - ); - } else if (picture instanceof $types.Fill) { - let picture$1 = picture[0]; - let colour = picture[1]; - return $json.object( - toList([ - ["type", $json.string("fill")], - ["colour", $colour.encode(colour)], - ["picture", picture_to_json(picture$1)], - ]), - ); - } else if (picture instanceof $types.Stroke) { - let picture$1 = picture[0]; - let stroke = picture[1]; - return $json.object( - toList([ - ["type", $json.string("stroke")], - ["stroke", stroke_to_json(stroke)], - ["picture", picture_to_json(picture$1)], - ]), - ); - } else if (picture instanceof $types.ImageScalingBehaviour) { - let picture$1 = picture[0]; - let behaviour = picture[1]; - return $json.object( - toList([ - ["type", $json.string("image_scaling_behaviour")], - [ - "behaviour", - $json.string( - (() => { - if (behaviour instanceof $types.ScalingSmooth) { - return "smooth"; - } else { - return "pixelated"; - } - })(), - ), - ], - ["picture", picture_to_json(picture$1)], - ]), - ); - } else if (picture instanceof $types.Translate) { - let picture$1 = picture[0]; - let x = picture[1][0]; - let y = picture[1][1]; - return $json.object( - toList([ - ["type", $json.string("translate")], - ["x", $json.float(x)], - ["y", $json.float(y)], - ["picture", picture_to_json(picture$1)], - ]), - ); - } else if (picture instanceof $types.Scale) { - let picture$1 = picture[0]; - let x = picture[1][0]; - let y = picture[1][1]; - return $json.object( - toList([ - ["type", $json.string("scale")], - ["x", $json.float(x)], - ["y", $json.float(y)], - ["picture", picture_to_json(picture$1)], - ]), - ); - } else if (picture instanceof $types.Rotate) { - let picture$1 = picture[0]; - let angle = picture[1]; - return $json.object( - toList([ - ["type", $json.string("rotate")], - ["angle", angle_to_json(angle)], - ["picture", picture_to_json(picture$1)], - ]), - ); - } else { - let from = picture[0]; - return $json.object( - toList([ - ["type", $json.string("combine")], - ["pictures", $json.array(from, picture_to_json)], - ]), - ); - } -} - -/** - * Serialize a `Picture` to a string. - * - * Note, serializing an `Image` texture will only store an ID referencing the image. This means that if you deserialize a Picture containing - * references to images, you are responsible for making sure all images are loaded before drawing the picture. - * More advanced APIs to support use cases such as these are planned for a future release. - * - * Also, if you wish to store the serialized data, remember that the library currently makes no stability guarantee that - * the data can be deserialized by *future* versions of the library. - */ -export function to_string(picture) { - let version = "paint:unstable"; - let _pipe = $json.object( - toList([ - ["version", $json.string(version)], - ["picture", picture_to_json(picture)], - ]), - ); - return $json.to_string(_pipe); -} diff --git a/build/dev/javascript/paint/paint/event.mjs b/build/dev/javascript/paint/paint/event.mjs deleted file mode 100644 index 86faa42..0000000 --- a/build/dev/javascript/paint/paint/event.mjs +++ /dev/null @@ -1,163 +0,0 @@ -import { CustomType as $CustomType } from "../gleam.mjs"; - -/** - * Triggered before drawing. Contains the number of milliseconds elapsed. - */ -export class Tick extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Event$Tick = ($0) => new Tick($0); -export const Event$isTick = (value) => value instanceof Tick; -export const Event$Tick$0 = (value) => value[0]; - -/** - * Triggered when a key is pressed - */ -export class KeyboardPressed extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Event$KeyboardPressed = ($0) => new KeyboardPressed($0); -export const Event$isKeyboardPressed = (value) => - value instanceof KeyboardPressed; -export const Event$KeyboardPressed$0 = (value) => value[0]; - -/** - * Triggered when a key is released - */ -export class KeyboardRelased extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Event$KeyboardRelased = ($0) => new KeyboardRelased($0); -export const Event$isKeyboardRelased = (value) => - value instanceof KeyboardRelased; -export const Event$KeyboardRelased$0 = (value) => value[0]; - -/** - * Triggered when the mouse is moved. Contains - * the `x` and `y` value for the mouse position. - */ -export class MouseMoved extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Event$MouseMoved = ($0, $1) => new MouseMoved($0, $1); -export const Event$isMouseMoved = (value) => value instanceof MouseMoved; -export const Event$MouseMoved$0 = (value) => value[0]; -export const Event$MouseMoved$1 = (value) => value[1]; - -/** - * Triggered when a mouse button is pressed - */ -export class MousePressed extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Event$MousePressed = ($0) => new MousePressed($0); -export const Event$isMousePressed = (value) => value instanceof MousePressed; -export const Event$MousePressed$0 = (value) => value[0]; - -/** - * Triggered when a mouse button is released. - * - * Note, on the web you might encounter issues where the - * release event for the right mouse button is not triggered - * because of the context menu. - */ -export class MouseReleased extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Event$MouseReleased = ($0) => new MouseReleased($0); -export const Event$isMouseReleased = (value) => value instanceof MouseReleased; -export const Event$MouseReleased$0 = (value) => value[0]; - -export class KeyLeftArrow extends $CustomType {} -export const Key$KeyLeftArrow = () => new KeyLeftArrow(); -export const Key$isKeyLeftArrow = (value) => value instanceof KeyLeftArrow; - -export class KeyRightArrow extends $CustomType {} -export const Key$KeyRightArrow = () => new KeyRightArrow(); -export const Key$isKeyRightArrow = (value) => value instanceof KeyRightArrow; - -export class KeyUpArrow extends $CustomType {} -export const Key$KeyUpArrow = () => new KeyUpArrow(); -export const Key$isKeyUpArrow = (value) => value instanceof KeyUpArrow; - -export class KeyDownArrow extends $CustomType {} -export const Key$KeyDownArrow = () => new KeyDownArrow(); -export const Key$isKeyDownArrow = (value) => value instanceof KeyDownArrow; - -export class KeySpace extends $CustomType {} -export const Key$KeySpace = () => new KeySpace(); -export const Key$isKeySpace = (value) => value instanceof KeySpace; - -export class KeyW extends $CustomType {} -export const Key$KeyW = () => new KeyW(); -export const Key$isKeyW = (value) => value instanceof KeyW; - -export class KeyA extends $CustomType {} -export const Key$KeyA = () => new KeyA(); -export const Key$isKeyA = (value) => value instanceof KeyA; - -export class KeyS extends $CustomType {} -export const Key$KeyS = () => new KeyS(); -export const Key$isKeyS = (value) => value instanceof KeyS; - -export class KeyD extends $CustomType {} -export const Key$KeyD = () => new KeyD(); -export const Key$isKeyD = (value) => value instanceof KeyD; - -export class KeyZ extends $CustomType {} -export const Key$KeyZ = () => new KeyZ(); -export const Key$isKeyZ = (value) => value instanceof KeyZ; - -export class KeyX extends $CustomType {} -export const Key$KeyX = () => new KeyX(); -export const Key$isKeyX = (value) => value instanceof KeyX; - -export class KeyC extends $CustomType {} -export const Key$KeyC = () => new KeyC(); -export const Key$isKeyC = (value) => value instanceof KeyC; - -export class KeyEnter extends $CustomType {} -export const Key$KeyEnter = () => new KeyEnter(); -export const Key$isKeyEnter = (value) => value instanceof KeyEnter; - -export class KeyEscape extends $CustomType {} -export const Key$KeyEscape = () => new KeyEscape(); -export const Key$isKeyEscape = (value) => value instanceof KeyEscape; - -export class KeyBackspace extends $CustomType {} -export const Key$KeyBackspace = () => new KeyBackspace(); -export const Key$isKeyBackspace = (value) => value instanceof KeyBackspace; - -export class MouseButtonLeft extends $CustomType {} -export const MouseButton$MouseButtonLeft = () => new MouseButtonLeft(); -export const MouseButton$isMouseButtonLeft = (value) => - value instanceof MouseButtonLeft; - -export class MouseButtonRight extends $CustomType {} -export const MouseButton$MouseButtonRight = () => new MouseButtonRight(); -export const MouseButton$isMouseButtonRight = (value) => - value instanceof MouseButtonRight; - -export class MouseButtonMiddle extends $CustomType {} -export const MouseButton$MouseButtonMiddle = () => new MouseButtonMiddle(); -export const MouseButton$isMouseButtonMiddle = (value) => - value instanceof MouseButtonMiddle; diff --git a/build/dev/javascript/paint/paint/internal/impl_canvas.mjs b/build/dev/javascript/paint/paint/internal/impl_canvas.mjs deleted file mode 100644 index 10ddff7..0000000 --- a/build/dev/javascript/paint/paint/internal/impl_canvas.mjs +++ /dev/null @@ -1,65 +0,0 @@ -import { - setup_input_handler, - get_width, - get_height, - set_global, - get_global, - reset, - save, - restore, - translate, - scale, - rotate, - reset_transform, - set_fill_colour, - set_stroke_color, - set_line_width, - set_image_smoothing_enabled, - arc, - polygon, - text, - draw_image, - image_from_query, - image_from_src, - on_image_load, -} from "../../impl_canvas_bindings.mjs"; -import { - define_web_component, - setup_request_animation_frame, - get_rendering_context, - get_key_code, - mouse_pos, - check_mouse_button, -} from "./../../impl_canvas_bindings.mjs"; - -export { - arc, - check_mouse_button, - define_web_component, - draw_image, - get_global, - get_height, - get_key_code, - get_rendering_context, - get_width, - image_from_query, - image_from_src, - mouse_pos, - on_image_load, - polygon, - reset, - reset_transform, - restore, - rotate, - save, - scale, - set_fill_colour, - set_global, - set_image_smoothing_enabled, - set_line_width, - set_stroke_color, - setup_input_handler, - setup_request_animation_frame, - text, - translate, -}; diff --git a/build/dev/javascript/paint/paint/internal/types.mjs b/build/dev/javascript/paint/paint/internal/types.mjs deleted file mode 100644 index 7e53029..0000000 --- a/build/dev/javascript/paint/paint/internal/types.mjs +++ /dev/null @@ -1,217 +0,0 @@ -import * as $colour from "../../../gleam_community_colour/gleam_community/colour.mjs"; -import { CustomType as $CustomType } from "../../gleam.mjs"; - -export class Blank extends $CustomType {} -export const Picture$Blank = () => new Blank(); -export const Picture$isBlank = (value) => value instanceof Blank; - -export class Polygon extends $CustomType { - constructor($0, closed) { - super(); - this[0] = $0; - this.closed = closed; - } -} -export const Picture$Polygon = ($0, closed) => new Polygon($0, closed); -export const Picture$isPolygon = (value) => value instanceof Polygon; -export const Picture$Polygon$0 = (value) => value[0]; -export const Picture$Polygon$closed = (value) => value.closed; -export const Picture$Polygon$1 = (value) => value.closed; - -export class Arc extends $CustomType { - constructor(radius, start, end) { - super(); - this.radius = radius; - this.start = start; - this.end = end; - } -} -export const Picture$Arc = (radius, start, end) => new Arc(radius, start, end); -export const Picture$isArc = (value) => value instanceof Arc; -export const Picture$Arc$radius = (value) => value.radius; -export const Picture$Arc$0 = (value) => value.radius; -export const Picture$Arc$start = (value) => value.start; -export const Picture$Arc$1 = (value) => value.start; -export const Picture$Arc$end = (value) => value.end; -export const Picture$Arc$2 = (value) => value.end; - -export class Text extends $CustomType { - constructor(text, style) { - super(); - this.text = text; - this.style = style; - } -} -export const Picture$Text = (text, style) => new Text(text, style); -export const Picture$isText = (value) => value instanceof Text; -export const Picture$Text$text = (value) => value.text; -export const Picture$Text$0 = (value) => value.text; -export const Picture$Text$style = (value) => value.style; -export const Picture$Text$1 = (value) => value.style; - -export class ImageRef extends $CustomType { - constructor($0, width_px, height_px) { - super(); - this[0] = $0; - this.width_px = width_px; - this.height_px = height_px; - } -} -export const Picture$ImageRef = ($0, width_px, height_px) => - new ImageRef($0, width_px, height_px); -export const Picture$isImageRef = (value) => value instanceof ImageRef; -export const Picture$ImageRef$0 = (value) => value[0]; -export const Picture$ImageRef$width_px = (value) => value.width_px; -export const Picture$ImageRef$1 = (value) => value.width_px; -export const Picture$ImageRef$height_px = (value) => value.height_px; -export const Picture$ImageRef$2 = (value) => value.height_px; - -export class Fill extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Picture$Fill = ($0, $1) => new Fill($0, $1); -export const Picture$isFill = (value) => value instanceof Fill; -export const Picture$Fill$0 = (value) => value[0]; -export const Picture$Fill$1 = (value) => value[1]; - -export class Stroke extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Picture$Stroke = ($0, $1) => new Stroke($0, $1); -export const Picture$isStroke = (value) => value instanceof Stroke; -export const Picture$Stroke$0 = (value) => value[0]; -export const Picture$Stroke$1 = (value) => value[1]; - -export class ImageScalingBehaviour extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Picture$ImageScalingBehaviour = ($0, $1) => - new ImageScalingBehaviour($0, $1); -export const Picture$isImageScalingBehaviour = (value) => - value instanceof ImageScalingBehaviour; -export const Picture$ImageScalingBehaviour$0 = (value) => value[0]; -export const Picture$ImageScalingBehaviour$1 = (value) => value[1]; - -export class Translate extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Picture$Translate = ($0, $1) => new Translate($0, $1); -export const Picture$isTranslate = (value) => value instanceof Translate; -export const Picture$Translate$0 = (value) => value[0]; -export const Picture$Translate$1 = (value) => value[1]; - -export class Scale extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Picture$Scale = ($0, $1) => new Scale($0, $1); -export const Picture$isScale = (value) => value instanceof Scale; -export const Picture$Scale$0 = (value) => value[0]; -export const Picture$Scale$1 = (value) => value[1]; - -export class Rotate extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const Picture$Rotate = ($0, $1) => new Rotate($0, $1); -export const Picture$isRotate = (value) => value instanceof Rotate; -export const Picture$Rotate$0 = (value) => value[0]; -export const Picture$Rotate$1 = (value) => value[1]; - -export class Combine extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Picture$Combine = ($0) => new Combine($0); -export const Picture$isCombine = (value) => value instanceof Combine; -export const Picture$Combine$0 = (value) => value[0]; - -export class Image extends $CustomType { - constructor(id) { - super(); - this.id = id; - } -} -export const Image$Image = (id) => new Image(id); -export const Image$isImage = (value) => value instanceof Image; -export const Image$Image$id = (value) => value.id; -export const Image$Image$0 = (value) => value.id; - -export class ScalingSmooth extends $CustomType {} -export const ImageScalingBehaviour$ScalingSmooth = () => new ScalingSmooth(); -export const ImageScalingBehaviour$isScalingSmooth = (value) => - value instanceof ScalingSmooth; - -export class ScalingPixelated extends $CustomType {} -export const ImageScalingBehaviour$ScalingPixelated = () => - new ScalingPixelated(); -export const ImageScalingBehaviour$isScalingPixelated = (value) => - value instanceof ScalingPixelated; - -export class NoStroke extends $CustomType {} -export const StrokeProperties$NoStroke = () => new NoStroke(); -export const StrokeProperties$isNoStroke = (value) => value instanceof NoStroke; - -export class SolidStroke extends $CustomType { - constructor($0, $1) { - super(); - this[0] = $0; - this[1] = $1; - } -} -export const StrokeProperties$SolidStroke = ($0, $1) => new SolidStroke($0, $1); -export const StrokeProperties$isSolidStroke = (value) => - value instanceof SolidStroke; -export const StrokeProperties$SolidStroke$0 = (value) => value[0]; -export const StrokeProperties$SolidStroke$1 = (value) => value[1]; - -export class FontProperties extends $CustomType { - constructor(size_px, font_family) { - super(); - this.size_px = size_px; - this.font_family = font_family; - } -} -export const FontProperties$FontProperties = (size_px, font_family) => - new FontProperties(size_px, font_family); -export const FontProperties$isFontProperties = (value) => - value instanceof FontProperties; -export const FontProperties$FontProperties$size_px = (value) => value.size_px; -export const FontProperties$FontProperties$0 = (value) => value.size_px; -export const FontProperties$FontProperties$font_family = (value) => - value.font_family; -export const FontProperties$FontProperties$1 = (value) => value.font_family; - -export class Radians extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Angle$Radians = ($0) => new Radians($0); -export const Angle$isRadians = (value) => value instanceof Radians; -export const Angle$Radians$0 = (value) => value[0]; diff --git a/build/dev/javascript/prelude.mjs b/build/dev/javascript/prelude.mjs deleted file mode 100644 index 6acd225..0000000 --- a/build/dev/javascript/prelude.mjs +++ /dev/null @@ -1,1575 +0,0 @@ -export class CustomType { - withFields(fields) { - let properties = Object.keys(this).map((label) => - label in fields ? fields[label] : this[label], - ); - return new this.constructor(...properties); - } -} - -export class List { - static fromArray(array, tail) { - let t = tail || new Empty(); - for (let i = array.length - 1; i >= 0; --i) { - t = new NonEmpty(array[i], t); - } - return t; - } - - [Symbol.iterator]() { - return new ListIterator(this); - } - - toArray() { - return [...this]; - } - - atLeastLength(desired) { - let current = this; - while (desired-- > 0 && current) current = current.tail; - return current !== undefined; - } - - hasLength(desired) { - let current = this; - while (desired-- > 0 && current) current = current.tail; - return desired === -1 && current instanceof Empty; - } - - countLength() { - let current = this; - let length = 0; - while (current) { - current = current.tail; - length++; - } - return length - 1; - } -} - -export function prepend(element, tail) { - return new NonEmpty(element, tail); -} - -export function toList(elements, tail) { - return List.fromArray(elements, tail); -} - -class ListIterator { - #current; - - constructor(current) { - this.#current = current; - } - - next() { - if (this.#current instanceof Empty) { - return { done: true }; - } else { - let { head, tail } = this.#current; - this.#current = tail; - return { value: head, done: false }; - } - } -} - -export class Empty extends List {} -export const List$Empty = () => new Empty(); -export const List$isEmpty = (value) => value instanceof Empty; - -export class NonEmpty extends List { - constructor(head, tail) { - super(); - this.head = head; - this.tail = tail; - } -} -export const List$NonEmpty = (head, tail) => new NonEmpty(head, tail); -export const List$isNonEmpty = (value) => value instanceof NonEmpty; - -export const List$NonEmpty$first = (value) => value.head; -export const List$NonEmpty$rest = (value) => value.tail; - -/** - * A bit array is a contiguous sequence of bits similar to Erlang's Binary type. - */ -export class BitArray { - /** - * The size in bits of this bit array's data. - * - * @type {number} - */ - bitSize; - - /** - * The size in bytes of this bit array's data. If this bit array doesn't store - * a whole number of bytes then this value is rounded up. - * - * @type {number} - */ - byteSize; - - /** - * The number of unused high bits in the first byte of this bit array's - * buffer prior to the start of its data. The value of any unused high bits is - * undefined. - * - * The bit offset will be in the range 0-7. - * - * @type {number} - */ - bitOffset; - - /** - * The raw bytes that hold this bit array's data. - * - * If `bitOffset` is not zero then there are unused high bits in the first - * byte of this buffer. - * - * If `bitOffset + bitSize` is not a multiple of 8 then there are unused low - * bits in the last byte of this buffer. - * - * @type {Uint8Array} - */ - rawBuffer; - - /** - * Constructs a new bit array from a `Uint8Array`, an optional size in - * bits, and an optional bit offset. - * - * If no bit size is specified it is taken as `buffer.length * 8`, i.e. all - * bytes in the buffer make up the new bit array's data. - * - * If no bit offset is specified it defaults to zero, i.e. there are no unused - * high bits in the first byte of the buffer. - * - * @param {Uint8Array} buffer - * @param {number} [bitSize] - * @param {number} [bitOffset] - */ - constructor(buffer, bitSize, bitOffset) { - if (!(buffer instanceof Uint8Array)) { - throw globalThis.Error( - "BitArray can only be constructed from a Uint8Array", - ); - } - - this.bitSize = bitSize ?? buffer.length * 8; - this.byteSize = Math.trunc((this.bitSize + 7) / 8); - this.bitOffset = bitOffset ?? 0; - - // Validate the bit size - if (this.bitSize < 0) { - throw globalThis.Error(`BitArray bit size is invalid: ${this.bitSize}`); - } - - // Validate the bit offset - if (this.bitOffset < 0 || this.bitOffset > 7) { - throw globalThis.Error( - `BitArray bit offset is invalid: ${this.bitOffset}`, - ); - } - - // Validate the length of the buffer - if (buffer.length !== Math.trunc((this.bitOffset + this.bitSize + 7) / 8)) { - throw globalThis.Error("BitArray buffer length is invalid"); - } - - this.rawBuffer = buffer; - } - - /** - * Returns a specific byte in this bit array. If the byte index is out of - * range then `undefined` is returned. - * - * When returning the final byte of a bit array with a bit size that's not a - * multiple of 8, the content of the unused low bits are undefined. - * - * @param {number} index - * @returns {number | undefined} - */ - byteAt(index) { - if (index < 0 || index >= this.byteSize) { - return undefined; - } - - return bitArrayByteAt(this.rawBuffer, this.bitOffset, index); - } - - equals(other) { - if (this.bitSize !== other.bitSize) { - return false; - } - - const wholeByteCount = Math.trunc(this.bitSize / 8); - - // If both bit offsets are zero do a byte-aligned equality check which is - // faster - if (this.bitOffset === 0 && other.bitOffset === 0) { - // Compare any whole bytes - for (let i = 0; i < wholeByteCount; i++) { - if (this.rawBuffer[i] !== other.rawBuffer[i]) { - return false; - } - } - - // Compare any trailing bits, excluding unused low bits - const trailingBitsCount = this.bitSize % 8; - if (trailingBitsCount) { - const unusedLowBitCount = 8 - trailingBitsCount; - if ( - this.rawBuffer[wholeByteCount] >> unusedLowBitCount !== - other.rawBuffer[wholeByteCount] >> unusedLowBitCount - ) { - return false; - } - } - } else { - // Compare any whole bytes - for (let i = 0; i < wholeByteCount; i++) { - const a = bitArrayByteAt(this.rawBuffer, this.bitOffset, i); - const b = bitArrayByteAt(other.rawBuffer, other.bitOffset, i); - - if (a !== b) { - return false; - } - } - - // Compare any trailing bits - const trailingBitsCount = this.bitSize % 8; - if (trailingBitsCount) { - const a = bitArrayByteAt( - this.rawBuffer, - this.bitOffset, - wholeByteCount, - ); - const b = bitArrayByteAt( - other.rawBuffer, - other.bitOffset, - wholeByteCount, - ); - - const unusedLowBitCount = 8 - trailingBitsCount; - if (a >> unusedLowBitCount !== b >> unusedLowBitCount) { - return false; - } - } - } - - return true; - } - - /** - * Returns this bit array's internal buffer. - * - * @deprecated Use `BitArray.byteAt()` or `BitArray.rawBuffer` instead. - * - * @returns {Uint8Array} - */ - get buffer() { - bitArrayPrintDeprecationWarning( - "buffer", - "Use BitArray.byteAt() or BitArray.rawBuffer instead", - ); - - if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) { - throw new globalThis.Error( - "BitArray.buffer does not support unaligned bit arrays", - ); - } - - return this.rawBuffer; - } - - /** - * Returns the length in bytes of this bit array's internal buffer. - * - * @deprecated Use `BitArray.bitSize` or `BitArray.byteSize` instead. - * - * @returns {number} - */ - get length() { - bitArrayPrintDeprecationWarning( - "length", - "Use BitArray.bitSize or BitArray.byteSize instead", - ); - - if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) { - throw new globalThis.Error( - "BitArray.length does not support unaligned bit arrays", - ); - } - - return this.rawBuffer.length; - } -} - -export const BitArray$BitArray = (buffer, bitSize, bitOffset) => - new BitArray(buffer, bitSize, bitOffset); - -/** - * Returns the nth byte in the given buffer, after applying the specified bit - * offset. If the index is out of bounds then zero is returned. - * - * @param {Uint8Array} buffer - * @param {number} bitOffset - * @param {number} index - * @returns {number} - */ -function bitArrayByteAt(buffer, bitOffset, index) { - if (bitOffset === 0) { - return buffer[index] ?? 0; - } else { - const a = (buffer[index] << bitOffset) & 0xff; - const b = buffer[index + 1] >> (8 - bitOffset); - - return a | b; - } -} - -export class UtfCodepoint { - constructor(value) { - this.value = value; - } -} - -const isBitArrayDeprecationMessagePrinted = {}; -function bitArrayPrintDeprecationWarning(name, message) { - if (isBitArrayDeprecationMessagePrinted[name]) { - return; - } - - console.warn( - `Deprecated BitArray.${name} property used in JavaScript FFI code. ${message}.`, - ); - - isBitArrayDeprecationMessagePrinted[name] = true; -} - -/** - * Slices a bit array to produce a new bit array. If `end` is not supplied then - * all bits from `start` onward are returned. - * - * If the slice is out of bounds then an exception is thrown. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} [end] - * @returns {BitArray} - */ -export function bitArraySlice(bitArray, start, end) { - end ??= bitArray.bitSize; - - bitArrayValidateRange(bitArray, start, end); - - // Handle zero-length slices - if (start === end) { - return new BitArray(new Uint8Array()); - } - - // Early return for slices that cover the whole bit array - if (start === 0 && end === bitArray.bitSize) { - return bitArray; - } - - start += bitArray.bitOffset; - end += bitArray.bitOffset; - - const startByteIndex = Math.trunc(start / 8); - const endByteIndex = Math.trunc((end + 7) / 8); - const byteLength = endByteIndex - startByteIndex; - - // Avoid creating a new Uint8Array if the view of the underlying ArrayBuffer - // is the same. This can occur when slicing off just the first or last bit of - // a bit array, i.e. when only the bit offset or bit size need to be updated. - let buffer; - if (startByteIndex === 0 && byteLength === bitArray.rawBuffer.byteLength) { - buffer = bitArray.rawBuffer; - } else { - buffer = new Uint8Array( - bitArray.rawBuffer.buffer, - bitArray.rawBuffer.byteOffset + startByteIndex, - byteLength, - ); - } - - return new BitArray(buffer, end - start, start % 8); -} - -/** - * Interprets a slice of this bit array as a floating point number, either - * 32-bit or 64-bit, with the specified endianness. - * - * The value of `end - start` must be exactly 32 or 64, otherwise an exception - * will be thrown. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @returns {number} - */ -export function bitArraySliceToFloat(bitArray, start, end, isBigEndian) { - bitArrayValidateRange(bitArray, start, end); - - const floatSize = end - start; - - // Check size is valid - if (floatSize !== 16 && floatSize !== 32 && floatSize !== 64) { - const msg = - `Sized floats must be 16-bit, 32-bit or 64-bit, got size of ` + - `${floatSize} bits`; - throw new globalThis.Error(msg); - } - - start += bitArray.bitOffset; - - const isStartByteAligned = start % 8 === 0; - - // If the bit range is byte aligned then the float can be read directly out - // of the existing buffer - if (isStartByteAligned) { - const view = new DataView( - bitArray.rawBuffer.buffer, - bitArray.rawBuffer.byteOffset + start / 8, - ); - - if (floatSize === 64) { - return view.getFloat64(0, !isBigEndian); - } else if (floatSize === 32) { - return view.getFloat32(0, !isBigEndian); - } else if (floatSize === 16) { - return fp16UintToNumber(view.getUint16(0, !isBigEndian)); - } - } - - // Copy the unaligned bytes into an aligned array so a DataView can be used - const alignedBytes = new Uint8Array(floatSize / 8); - const byteOffset = Math.trunc(start / 8); - for (let i = 0; i < alignedBytes.length; i++) { - alignedBytes[i] = bitArrayByteAt( - bitArray.rawBuffer, - start % 8, - byteOffset + i, - ); - } - - // Read the float out of the aligned buffer - const view = new DataView(alignedBytes.buffer); - if (floatSize === 64) { - return view.getFloat64(0, !isBigEndian); - } else if (floatSize === 32) { - return view.getFloat32(0, !isBigEndian); - } else { - return fp16UintToNumber(view.getUint16(0, !isBigEndian)); - } -} - -/** - * Interprets a slice of this bit array as a signed or unsigned integer with the - * specified endianness. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -export function bitArraySliceToInt( - bitArray, - start, - end, - isBigEndian, - isSigned, -) { - bitArrayValidateRange(bitArray, start, end); - - if (start === end) { - return 0; - } - - start += bitArray.bitOffset; - end += bitArray.bitOffset; - - const isStartByteAligned = start % 8 === 0; - const isEndByteAligned = end % 8 === 0; - - // If the slice is byte-aligned then there is no need to handle unaligned - // slices, meaning a simpler and faster implementation can be used instead - if (isStartByteAligned && isEndByteAligned) { - return intFromAlignedSlice( - bitArray, - start / 8, - end / 8, - isBigEndian, - isSigned, - ); - } - - const size = end - start; - - const startByteIndex = Math.trunc(start / 8); - const endByteIndex = Math.trunc((end - 1) / 8); - - // Handle the case of the slice being completely contained in a single byte - if (startByteIndex == endByteIndex) { - const mask = 0xff >> start % 8; - const unusedLowBitCount = (8 - (end % 8)) % 8; - - let value = - (bitArray.rawBuffer[startByteIndex] & mask) >> unusedLowBitCount; - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2 ** (size - 1); - if (value >= highBit) { - value -= highBit * 2; - } - } - - return value; - } - - // The integer value to be read is not aligned and crosses at least one byte - // boundary in the input array - - if (size <= 53) { - return intFromUnalignedSliceUsingNumber( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } else { - return intFromUnalignedSliceUsingBigInt( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } -} - -/** - * Joins the given segments into a new bit array, tightly packing them together. - * Each segment must be one of the following types: - * - * - A `number`: A single byte value in the range 0-255. Values outside this - * range will be wrapped. - * - A `Uint8Array`: A sequence of byte values of any length. - * - A `BitArray`: A sequence of bits of any length, which may not be byte - * aligned. - * - * The bit size of the returned bit array will be the sum of the size in bits - * of the input segments. - * - * @param {(number | Uint8Array | BitArray)[]} segments - * @returns {BitArray} - */ -export function toBitArray(segments) { - if (segments.length === 0) { - return new BitArray(new Uint8Array()); - } - - if (segments.length === 1) { - const segment = segments[0]; - - // When there is a single BitArray segment it can be returned as-is - if (segment instanceof BitArray) { - return segment; - } - - // When there is a single Uint8Array segment, pass it directly to the bit - // array constructor to avoid a copy - if (segment instanceof Uint8Array) { - return new BitArray(segment); - } - - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); - } - - // Count the total number of bits and check if all segments are numbers, i.e. - // single bytes - let bitSize = 0; - let areAllSegmentsNumbers = true; - for (const segment of segments) { - if (segment instanceof BitArray) { - bitSize += segment.bitSize; - areAllSegmentsNumbers = false; - } else if (segment instanceof Uint8Array) { - bitSize += segment.byteLength * 8; - areAllSegmentsNumbers = false; - } else { - bitSize += 8; - } - } - - // If all segments are numbers then pass the segments array directly to the - // Uint8Array constructor - if (areAllSegmentsNumbers) { - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); - } - - // Pack the segments into a Uint8Array - const buffer = new Uint8Array(Math.trunc((bitSize + 7) / 8)); - - // The current write position in bits into the above array. Byte-aligned - // segments, i.e. when the cursor is a multiple of 8, are able to be processed - // faster due to being able to copy bytes directly. - let cursor = 0; - - for (let segment of segments) { - const isCursorByteAligned = cursor % 8 === 0; - - if (segment instanceof BitArray) { - if (isCursorByteAligned && segment.bitOffset === 0) { - buffer.set(segment.rawBuffer, cursor / 8); - cursor += segment.bitSize; - - // Zero any unused bits in the last byte of the buffer. Their content is - // undefined and shouldn't be included in the output. - const trailingBitsCount = segment.bitSize % 8; - if (trailingBitsCount !== 0) { - const lastByteIndex = Math.trunc(cursor / 8); - buffer[lastByteIndex] >>= 8 - trailingBitsCount; - buffer[lastByteIndex] <<= 8 - trailingBitsCount; - } - } else { - appendUnalignedBits( - segment.rawBuffer, - segment.bitSize, - segment.bitOffset, - ); - } - } else if (segment instanceof Uint8Array) { - if (isCursorByteAligned) { - buffer.set(segment, cursor / 8); - cursor += segment.byteLength * 8; - } else { - appendUnalignedBits(segment, segment.byteLength * 8, 0); - } - } else { - if (isCursorByteAligned) { - buffer[cursor / 8] = segment; - cursor += 8; - } else { - appendUnalignedBits(new Uint8Array([segment]), 8, 0); - } - } - } - - function appendUnalignedBits(unalignedBits, size, offset) { - if (size === 0) { - return; - } - - const byteSize = Math.trunc(size + 7 / 8); - - const highBitsCount = cursor % 8; - const lowBitsCount = 8 - highBitsCount; - - let byteIndex = Math.trunc(cursor / 8); - - for (let i = 0; i < byteSize; i++) { - let byte = bitArrayByteAt(unalignedBits, offset, i); - - // If this is a partial byte then zero out the trailing bits as their - // content is undefined and shouldn't be included in the output - if (size < 8) { - byte >>= 8 - size; - byte <<= 8 - size; - } - - // Copy the high bits of the input byte to the low bits of the current - // output byte - buffer[byteIndex] |= byte >> highBitsCount; - - let appendedBitsCount = size - Math.max(0, size - lowBitsCount); - size -= appendedBitsCount; - cursor += appendedBitsCount; - - if (size === 0) { - break; - } - - // Copy the low bits of the input byte to the high bits of the next output - // byte - buffer[++byteIndex] = byte << lowBitsCount; - appendedBitsCount = size - Math.max(0, size - highBitsCount); - size -= appendedBitsCount; - cursor += appendedBitsCount; - } - } - - return new BitArray(buffer, bitSize); -} - -/** - * Encodes a floating point value into a `Uint8Array`. This is used to create - * float segments that are part of bit array expressions. - * - * @param {number} value - * @param {number} size - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function sizedFloat(value, size, isBigEndian) { - if (size !== 16 && size !== 32 && size !== 64) { - const msg = `Sized floats must be 16-bit, 32-bit or 64-bit, got size of ${size} bits`; - throw new globalThis.Error(msg); - } - - if (size === 16) { - return numberToFp16Uint(value, isBigEndian); - } - - const buffer = new Uint8Array(size / 8); - - const view = new DataView(buffer.buffer); - - if (size == 64) { - view.setFloat64(0, value, !isBigEndian); - } else { - view.setFloat32(0, value, !isBigEndian); - } - - return buffer; -} - -/** - * Encodes an integer value into a `Uint8Array`, or a `BitArray` if the size in - * bits is not a multiple of 8. This is used to create integer segments used in - * bit array expressions. - * - * @param {number} value - * @param {number} size - * @param {boolean} isBigEndian - * @returns {Uint8Array | BitArray} - */ -export function sizedInt(value, size, isBigEndian) { - if (size <= 0) { - return new Uint8Array(); - } - - // Fast path when size is 8 bits. This relies on the rounding behavior of the - // Uint8Array constructor. - if (size === 8) { - return new Uint8Array([value]); - } - - // Fast path when size is less than 8 bits: shift the value up to the high - // bits - if (size < 8) { - value <<= 8 - size; - return new BitArray(new Uint8Array([value]), size); - } - - // Allocate output buffer - const buffer = new Uint8Array(Math.trunc((size + 7) / 8)); - - // The number of trailing bits in the final byte. Will be zero if the size is - // an exact number of bytes. - const trailingBitsCount = size % 8; - - // The number of unused bits in the final byte of the buffer - const unusedBitsCount = 8 - trailingBitsCount; - - // For output sizes not exceeding 32 bits the number type is used. For larger - // output sizes the BigInt type is needed. - // - // The code in each of these two paths must be kept in sync. - if (size <= 32) { - if (isBigEndian) { - let i = buffer.length - 1; - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i--] = (value << unusedBitsCount) & 0xff; - value >>= trailingBitsCount; - } - - for (; i >= 0; i--) { - buffer[i] = value; - value >>= 8; - } - } else { - let i = 0; - - const wholeByteCount = Math.trunc(size / 8); - for (; i < wholeByteCount; i++) { - buffer[i] = value; - value >>= 8; - } - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i] = value << unusedBitsCount; - } - } - } else { - const bigTrailingBitsCount = BigInt(trailingBitsCount); - const bigUnusedBitsCount = BigInt(unusedBitsCount); - - let bigValue = BigInt(value); - - if (isBigEndian) { - let i = buffer.length - 1; - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i--] = Number(bigValue << bigUnusedBitsCount); - bigValue >>= bigTrailingBitsCount; - } - - for (; i >= 0; i--) { - buffer[i] = Number(bigValue); - bigValue >>= 8n; - } - } else { - let i = 0; - - const wholeByteCount = Math.trunc(size / 8); - for (; i < wholeByteCount; i++) { - buffer[i] = Number(bigValue); - bigValue >>= 8n; - } - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i] = Number(bigValue << bigUnusedBitsCount); - } - } - } - - // Integers that aren't a whole number of bytes are returned as a BitArray so - // their size in bits is tracked - if (trailingBitsCount) { - return new BitArray(buffer, size); - } - - return buffer; -} - -/** - * Reads an aligned slice of any size as an integer. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromAlignedSlice(bitArray, start, end, isBigEndian, isSigned) { - const byteSize = end - start; - - if (byteSize <= 6) { - return intFromAlignedSliceUsingNumber( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } else { - return intFromAlignedSliceUsingBigInt( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } -} - -/** - * Reads an aligned slice up to 48 bits in size as an integer. Uses the - * JavaScript `number` type internally. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromAlignedSliceUsingNumber( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const byteSize = end - start; - - let value = 0; - - // Read bytes as an unsigned integer - if (isBigEndian) { - for (let i = start; i < end; i++) { - value *= 256; - value += buffer[i]; - } - } else { - for (let i = end - 1; i >= start; i--) { - value *= 256; - value += buffer[i]; - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2 ** (byteSize * 8 - 1); - if (value >= highBit) { - value -= highBit * 2; - } - } - - return value; -} - -/** - * Reads an aligned slice of any size as an integer. Uses the JavaScript - * `BigInt` type internally. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromAlignedSliceUsingBigInt( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const byteSize = end - start; - - let value = 0n; - - // Read bytes as an unsigned integer value - if (isBigEndian) { - for (let i = start; i < end; i++) { - value *= 256n; - value += BigInt(buffer[i]); - } - } else { - for (let i = end - 1; i >= start; i--) { - value *= 256n; - value += BigInt(buffer[i]); - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 1n << BigInt(byteSize * 8 - 1); - if (value >= highBit) { - value -= highBit * 2n; - } - } - - // Convert the result into a JS number. This may cause quantizing/error on - // values outside JavaScript's safe integer range. - return Number(value); -} - -/** - * Reads an unaligned slice up to 53 bits in size as an integer. Uses the - * JavaScript `number` type internally. - * - * This function assumes that the slice crosses at least one byte boundary in - * the input. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromUnalignedSliceUsingNumber( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const isStartByteAligned = start % 8 === 0; - - let size = end - start; - let byteIndex = Math.trunc(start / 8); - - let value = 0; - - if (isBigEndian) { - // Read any leading bits - if (!isStartByteAligned) { - const leadingBitsCount = 8 - (start % 8); - value = buffer[byteIndex++] & ((1 << leadingBitsCount) - 1); - size -= leadingBitsCount; - } - - // Read any whole bytes - while (size >= 8) { - value *= 256; - value += buffer[byteIndex++]; - size -= 8; - } - - // Read any trailing bits - if (size > 0) { - value *= 2 ** size; - value += buffer[byteIndex] >> (8 - size); - } - } else { - // For little endian, if the start is aligned then whole bytes can be read - // directly out of the input array, with the trailing bits handled at the - // end - if (isStartByteAligned) { - let size = end - start; - let scale = 1; - - // Read whole bytes - while (size >= 8) { - value += buffer[byteIndex++] * scale; - scale *= 256; - size -= 8; - } - - // Read trailing bits - value += (buffer[byteIndex] >> (8 - size)) * scale; - } else { - // Read little endian data where the start is not byte-aligned. This is - // done by reading whole bytes that cross a byte boundary in the input - // data, then reading any trailing bits. - - const highBitsCount = start % 8; - const lowBitsCount = 8 - highBitsCount; - - let size = end - start; - let scale = 1; - - // Extract whole bytes - while (size >= 8) { - const byte = - (buffer[byteIndex] << highBitsCount) | - (buffer[byteIndex + 1] >> lowBitsCount); - - value += (byte & 0xff) * scale; - - scale *= 256; - size -= 8; - byteIndex++; - } - - // Read any trailing bits. These trailing bits may cross a byte boundary - // in the input buffer. - if (size > 0) { - const lowBitsUsed = size - Math.max(0, size - lowBitsCount); - - let trailingByte = - (buffer[byteIndex] & ((1 << lowBitsCount) - 1)) >> - (lowBitsCount - lowBitsUsed); - - size -= lowBitsUsed; - - if (size > 0) { - trailingByte *= 2 ** size; - trailingByte += buffer[byteIndex + 1] >> (8 - size); - } - - value += trailingByte * scale; - } - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2 ** (end - start - 1); - if (value >= highBit) { - value -= highBit * 2; - } - } - - return value; -} - -/** - * Reads an unaligned slice of any size as an integer. Uses the JavaScript - * `BigInt` type internally. - * - * This function assumes that the slice crosses at least one byte boundary in - * the input. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromUnalignedSliceUsingBigInt( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const isStartByteAligned = start % 8 === 0; - - let size = end - start; - let byteIndex = Math.trunc(start / 8); - - let value = 0n; - - if (isBigEndian) { - // Read any leading bits - if (!isStartByteAligned) { - const leadingBitsCount = 8 - (start % 8); - value = BigInt(buffer[byteIndex++] & ((1 << leadingBitsCount) - 1)); - size -= leadingBitsCount; - } - - // Read any whole bytes - while (size >= 8) { - value *= 256n; - value += BigInt(buffer[byteIndex++]); - size -= 8; - } - - // Read any trailing bits - if (size > 0) { - value <<= BigInt(size); - value += BigInt(buffer[byteIndex] >> (8 - size)); - } - } else { - // For little endian, if the start is aligned then whole bytes can be read - // directly out of the input array, with the trailing bits handled at the - // end - if (isStartByteAligned) { - let size = end - start; - let shift = 0n; - - // Read whole bytes - while (size >= 8) { - value += BigInt(buffer[byteIndex++]) << shift; - shift += 8n; - size -= 8; - } - - // Read trailing bits - value += BigInt(buffer[byteIndex] >> (8 - size)) << shift; - } else { - // Read little endian data where the start is not byte-aligned. This is - // done by reading whole bytes that cross a byte boundary in the input - // data, then reading any trailing bits. - - const highBitsCount = start % 8; - const lowBitsCount = 8 - highBitsCount; - - let size = end - start; - let shift = 0n; - - // Extract whole bytes - while (size >= 8) { - const byte = - (buffer[byteIndex] << highBitsCount) | - (buffer[byteIndex + 1] >> lowBitsCount); - - value += BigInt(byte & 0xff) << shift; - - shift += 8n; - size -= 8; - byteIndex++; - } - - // Read any trailing bits. These trailing bits may cross a byte boundary - // in the input buffer. - if (size > 0) { - const lowBitsUsed = size - Math.max(0, size - lowBitsCount); - - let trailingByte = - (buffer[byteIndex] & ((1 << lowBitsCount) - 1)) >> - (lowBitsCount - lowBitsUsed); - - size -= lowBitsUsed; - - if (size > 0) { - trailingByte <<= size; - trailingByte += buffer[byteIndex + 1] >> (8 - size); - } - - value += BigInt(trailingByte) << shift; - } - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2n ** BigInt(end - start - 1); - if (value >= highBit) { - value -= highBit * 2n; - } - } - - // Convert the result into a JS number. This may cause quantizing/error on - // values outside JavaScript's safe integer range. - return Number(value); -} - -/** - * Interprets a 16-bit unsigned integer value as a 16-bit floating point value. - * - * @param {number} intValue - * @returns {number} - */ -function fp16UintToNumber(intValue) { - const sign = intValue >= 0x8000 ? -1 : 1; - const exponent = (intValue & 0x7c00) >> 10; - const fraction = intValue & 0x03ff; - - let value; - if (exponent === 0) { - value = 6.103515625e-5 * (fraction / 0x400); - } else if (exponent === 0x1f) { - value = fraction === 0 ? Infinity : NaN; - } else { - value = Math.pow(2, exponent - 15) * (1 + fraction / 0x400); - } - - return sign * value; -} - -/** - * Converts a floating point number to bytes for a 16-bit floating point value. - * - * @param {number} intValue - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -function numberToFp16Uint(value, isBigEndian) { - const buffer = new Uint8Array(2); - - if (isNaN(value)) { - buffer[1] = 0x7e; - } else if (value === Infinity) { - buffer[1] = 0x7c; - } else if (value === -Infinity) { - buffer[1] = 0xfc; - } else if (value === 0) { - // Both values are already zero - } else { - const sign = value < 0 ? 1 : 0; - value = Math.abs(value); - - let exponent = Math.floor(Math.log2(value)); - let fraction = value / Math.pow(2, exponent) - 1; - - exponent += 15; - - if (exponent <= 0) { - exponent = 0; - fraction = value / Math.pow(2, -14); - } else if (exponent >= 31) { - exponent = 31; - fraction = 0; - } - - fraction = Math.round(fraction * 1024); - - buffer[1] = - (sign << 7) | ((exponent & 0x1f) << 2) | ((fraction >> 8) & 0x03); - buffer[0] = fraction & 0xff; - } - - if (isBigEndian) { - const a = buffer[0]; - buffer[0] = buffer[1]; - buffer[1] = a; - } - - return buffer; -} - -/** - * Throws an exception if the given start and end values are out of bounds for - * a bit array. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - */ -function bitArrayValidateRange(bitArray, start, end) { - if ( - start < 0 || - start > bitArray.bitSize || - end < start || - end > bitArray.bitSize - ) { - const msg = - `Invalid bit array slice: start = ${start}, end = ${end}, ` + - `bit size = ${bitArray.bitSize}`; - throw new globalThis.Error(msg); - } -} - -/** @type {TextEncoder | undefined} */ -let utf8Encoder; - -/** - * Returns the UTF-8 bytes for a string. - * - * @param {string} string - * @returns {Uint8Array} - */ -export function stringBits(string) { - utf8Encoder ??= new TextEncoder(); - return utf8Encoder.encode(string); -} - -/** - * Returns the UTF-8 bytes for a single UTF codepoint. - * - * @param {UtfCodepoint} codepoint - * @returns {Uint8Array} - */ -export function codepointBits(codepoint) { - return stringBits(String.fromCodePoint(codepoint.value)); -} - -/** - * Returns the UTF-16 bytes for a string. - * - * @param {string} string - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function stringToUtf16(string, isBigEndian) { - const buffer = new ArrayBuffer(string.length * 2); - const bufferView = new DataView(buffer); - - for (let i = 0; i < string.length; i++) { - bufferView.setUint16(i * 2, string.charCodeAt(i), !isBigEndian); - } - - return new Uint8Array(buffer); -} - -/** - * Returns the UTF-16 bytes for a single UTF codepoint. - * - * @param {UtfCodepoint} codepoint - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function codepointToUtf16(codepoint, isBigEndian) { - return stringToUtf16(String.fromCodePoint(codepoint.value), isBigEndian); -} - -/** - * Returns the UTF-32 bytes for a string. - * - * @param {string} string - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function stringToUtf32(string, isBigEndian) { - const buffer = new ArrayBuffer(string.length * 4); - const bufferView = new DataView(buffer); - let length = 0; - - for (let i = 0; i < string.length; i++) { - const codepoint = string.codePointAt(i); - - bufferView.setUint32(length * 4, codepoint, !isBigEndian); - length++; - - if (codepoint > 0xffff) { - i++; - } - } - - return new Uint8Array(buffer.slice(0, length * 4)); -} - -/** - * Returns the UTF-32 bytes for a single UTF codepoint. - * - * @param {UtfCodepoint} codepoint - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function codepointToUtf32(codepoint, isBigEndian) { - return stringToUtf32(String.fromCodePoint(codepoint.value), isBigEndian); -} - -export class Result extends CustomType { - static isResult(data) { - return data instanceof Result; - } -} - -export class Ok extends Result { - constructor(value) { - super(); - this[0] = value; - } - - isOk() { - return true; - } -} -export const Result$Ok = (value) => new Ok(value); -export const Result$isOk = (value) => value instanceof Ok; -export const Result$Ok$0 = (value) => value[0]; - -export class Error extends Result { - constructor(detail) { - super(); - this[0] = detail; - } - - isOk() { - return false; - } -} -export const Result$Error = (detail) => new Error(detail); -export const Result$isError = (value) => value instanceof Error; -export const Result$Error$0 = (value) => value[0]; - -export function isEqual(x, y) { - let values = [x, y]; - - while (values.length) { - let a = values.pop(); - let b = values.pop(); - if (a === b) continue; - - if (!isObject(a) || !isObject(b)) return false; - let unequal = - !structurallyCompatibleObjects(a, b) || - unequalDates(a, b) || - unequalBuffers(a, b) || - unequalArrays(a, b) || - unequalMaps(a, b) || - unequalSets(a, b) || - unequalRegExps(a, b); - if (unequal) return false; - - const proto = Object.getPrototypeOf(a); - if (proto !== null && typeof proto.equals === "function") { - try { - if (a.equals(b)) continue; - else return false; - } catch {} - } - - let [keys, get] = getters(a); - const ka = keys(a); - const kb = keys(b); - if (ka.length !== kb.length) return false; - for (let k of ka) { - values.push(get(a, k), get(b, k)); - } - } - - return true; -} - -function getters(object) { - if (object instanceof Map) { - return [(x) => x.keys(), (x, y) => x.get(y)]; - } else { - let extra = object instanceof globalThis.Error ? ["message"] : []; - return [(x) => [...extra, ...Object.keys(x)], (x, y) => x[y]]; - } -} - -function unequalDates(a, b) { - return a instanceof Date && (a > b || a < b); -} - -function unequalBuffers(a, b) { - return ( - !(a instanceof BitArray) && - a.buffer instanceof ArrayBuffer && - a.BYTES_PER_ELEMENT && - !(a.byteLength === b.byteLength && a.every((n, i) => n === b[i])) - ); -} - -function unequalArrays(a, b) { - return Array.isArray(a) && a.length !== b.length; -} - -function unequalMaps(a, b) { - return a instanceof Map && a.size !== b.size; -} - -function unequalSets(a, b) { - return ( - a instanceof Set && (a.size != b.size || [...a].some((e) => !b.has(e))) - ); -} - -function unequalRegExps(a, b) { - return a instanceof RegExp && (a.source !== b.source || a.flags !== b.flags); -} - -function isObject(a) { - return typeof a === "object" && a !== null; -} - -function structurallyCompatibleObjects(a, b) { - if (typeof a !== "object" && typeof b !== "object" && (!a || !b)) - return false; - - let nonstructural = [Promise, WeakSet, WeakMap, Function]; - if (nonstructural.some((c) => a instanceof c)) return false; - - return a.constructor === b.constructor; -} - -export function remainderInt(a, b) { - if (b === 0) { - return 0; - } else { - return a % b; - } -} - -export function divideInt(a, b) { - return Math.trunc(divideFloat(a, b)); -} - -export function divideFloat(a, b) { - if (b === 0) { - return 0; - } else { - return a / b; - } -} - -export function makeError(variant, file, module, line, fn, message, extra) { - let error = new globalThis.Error(message); - error.gleam_error = variant; - error.file = file; - error.module = module; - error.line = line; - error.function = fn; - // TODO: Remove this with Gleam v2.0.0 - error.fn = fn; - for (let k in extra) error[k] = extra[k]; - return error; -} diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache b/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache deleted file mode 100644 index 40230afa49fae3501e1647b40250a3ba7f51b546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14636 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 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_inline b/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_meta b/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_meta deleted file mode 100644 index 6cd0de369cbda28f29aaf0906071e5f75a227392..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1262 zcmdlVqLazMz`(HX<997ab`Xn!fq@H3r{|<5=IZBU7MFko1Q{3@m_ZB%28N8%6d?u% z1{($j23Dw0L1JcJi7f*IgC_$61I(m?jLPE7cky!2WI z28Lb+1_m~$L`h;%dTL1@0|UbWB%@0z3sQ>@GB7YGGBPmKtkIiOup#FN2P0Gu0|Nud zEg-8w_JE88830m$fq{WRfsuhhiIIUpnUR6PfsuisnvsE_mXU#>j*)?34kH7@6GjGx zXN(LC&lwpQ{xLEzm@_djSTZp%STQj$G%ztR>}6tL*vG`c@Sll+L7tg`L4lcpA)c9m zp^=$^p^2G+VG=U~!wO~whE>cA46B(L7_KriFg#^uVED$&z+lV5z~Ifoz!1;Ez|hUY zz;K0yf#Deo1H*e31_mBh1_nJ=28ME028J$H28PM33=At-85l0JGBCVgWnlQt%D^DR z#=s!W#=xM&#=v09#=sEF#=sEH#=sEC#=sE8#=x+Qje%hc8w0~vHUFf8R}VA#pcz;KqEfkBpsfkBRkfgzfQfgy&6fgy*7 zfuWIyfnhce1H(!l28JU%3=B7T7#M!@FfiEjGB9}XGBCvPGB7mpGBBLtWnj3>%fN7p zmx19PF9X8^UIvDTybKH)d<+bQd<+cx_!t=O@G&qv;A3ET#K*w!n2&)$i=TlZlAnPg zil2d@h@XLBF+T&t9exIe$NUToPxu)aGz1tJGzAzKk^~qSk_8wTY6Tb=W(hDbY!qN% zxFNv6@K=C=fmx7&fnAV+L0FK1K~0c>p+t~@p-+&3VVWQV!(u@OhHZij3@-#382E%3 z7{r7a7^H+47^H<57@UL{7@UO|7=ncu7&3$y7`lZR7`6#9FdPwLV7M>Dz+foMz~C;- zz>qD>z_3G@f#IMq1H%bn28MgW3=EHi85o`jGcY_AW?&E#VPH@dVPLQmVPMD*VPIG; z!ocuMgn{9e2m`|#5eA00A`A?yq6`coq6`eWq6`ckq6`evL>U-nh%zwD6lGwzF3Q00 zPLzQ`UW|dkRE&YaQjCGYT8x3gMvQ?WRE&Y4M2vxOVKD}V&teP=eBulY zLgEYz!r}}Jw&Dy7HR22mtHl`@){8SRY!qi;*d)%ta8{gw;h{JK!w+!=1_=oU22BYD zhI9!AhFS>*hIJAQ3=bq27@kNlFg%lBV0bRUz#u8fz~Cjxz~C*(zz`+Lz%WCSfnld4 z1H&_pg81_oa#28JXl28Ko{28M-F3=Au!7#P+{F)*x`Vqn-H#lUb;ih<#^6axc~ UGy{X1Gy{XTGy{V#6vIji0EsZRjQ{`u diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_warnings b/build/dev/javascript/stellar_prune/_gleam_artefacts/game.cache_warnings deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache b/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache deleted file mode 100644 index 7e8f2999123e7d2a0e7867270f995758f790c220..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9498 zcmY#nWMO{D7Qo2Ez#yorBpB!}oXONK+{^DSs8}T2B*7@0q{?V0yNXeGlNzJ&DK$pn zv;1trx6~NfGfGqb7nh{wOUy}0 zEz^go1gq08E=tzVC{58z=g&z^%ykrC5|lM^lwlW~XyrJ8U6_?o$(eW$Z{cP^wl7eEi7nWMk&!cygOO2?k&A(ek&%Hx zQ1p1<6(%+Y=0F}$BngIU35GfeCbA0#772zh21YP4GB65;1_?%5ff7S#kzfR4U<_C= z(nv7U2&6KU3#yVoEH&Avz96HrI5W8zM=JR5oS&0ll$eymz?f=Zl30|UT7pBRyjxCw zVu^e@D8+(P4+FEHD9Itp2ugPhjG|1;jDm_mfjW$gf+dWCvPy!oTnx;}!2^m81_nmP z07gbeWf}&1>qN_kTUD61e)9V8u zmi{kD%*-p%&&*>iNiE7t%+W95uPjI{mIn)iOGZYf08m7-GBOG(b_KdHG773H3A!)} zDsl-rFa|0xG6t$JG75@d^$O!Ku$)KFR5-FXQVPJXf*Djoqg65>FM|Axt^=OdK)GBAoYr#SX$__cBX>uE zb2li)1SPEmB^duFgG%=Jj6??J%pyicd2kA1V6X?Jx{?e=CgTN+HyHmzc=07n`LKi) zpOKnVkXi&uU%@^|S)Kt@#DXxWn7xA>16J5#z)3K46(|NGjS$6bqLN^ukzgjfU@Vtl z3}avdBdmPE77pM9#lT2%;zQ5-R7%mzf{LdCJs24UHI)QC7zI_i1YN+X85}_pc!Lt; zI|c?uCI(jHWz5_xjAD><2TtD>NFhvVC8k8%N(@WDlF)KON!CW-P%D5ZYe;}V!wGk_ zWrVldf~0XqCc!1Q;R%}&marL9LBUP9z$B$sfTU0=r7uQ7#Yy-|OjuS$@)0z=KuF?gnD%q)s80eM{>Tw8#>egaEf5dqG|(7J-;_6W88zX_lJVdWW`*O0>C6cZma zqdd6UwQ`hU5&p%-D9pvqD13>BQTP=Pqwp>vM&VOJup$T4Mii`K6yC(lD3}Cl7>Zg6 zGBFBTF$xMX3TiP5dchP5GAe;A5o9bvFR2AUZB9n^046qYtp_Gx6~9-Y0wc3vrB+}C zBeUSisK7If%)*L{R>2C4sP%my2NRp1tCyfB7Xzc9s1~U9Med0Z)BZtjK0sRyU{f8n z1RcSq8iBevvh0F_T!I3OpdJvG786(_0|Q#i1Y%B3`XjhgTtPBB?nT9)PkhQAaII=l%*6q z9Ay*%>~!iU8yY5iP)+YqngUIUf#$-Uh*FWnF*as!3XFo3iIDp0q!FmTf;Z71{W3@( zMIj1Bvc}j@3`OeXflYU{f>z(8H*FcA-9-ilNMXgm05Q=BY9a~Ee@ImU?}s8KL`cz? zX$4M*d!qsmz=}rd*#`9nG*40`Kv04lRz^}e9t9c89c7pVO|1e=7?}j`8U@~AWD;g& zQVM2aVq_B5W!4JTVP<3!&SX{!&HyobnXQ6*K#adEK|!pHO!h&k#icnV3=D#t=7NmE zER2pE%z~m)f|Bx}rl6;hps&23D;KkWHmIs%21l(bm!K*aBNGFMylYWWei4QQBO?QJ zOr3#2kX2rgk=c=jS&-96kk?<3l?&2RU|?|MVGdMaViSz@5=`U@OkiRYTo@#{lq+xv z6Pw^&Bf-1i767GfUC0Qk6=!^9>m$`~aq z$w;kKMtt{)sB{GD+YqG~r9Xx`UxN}(L4tz*f}C8)4JrcJPz#zC2Uj*EKCBr67@3&; z*bP}jm;|S?3kVCU7z(7CDjOVb;Wi!6X#>Z~#!|ul}z$Cx~9XW7da$pwZG&6LJXA<^hy$|kt z1qn(zf%-<0NrJLjkfHVe;CUnc%sd9h64;a!tcwJZO3Ptj&rd9Y4$vnjGVte>B^EoT zFbiukW(n&uRtXz2stX4)S_ua-1__5UnhUowDhanTo)VtOXfAw^(Mb3p<00XbjN-yK z8H0rHGI|L=WE29r< z$z%k@>cTsjjD&YGX$kLSQWw6-q$GTkDMp&oYbu2hU^ZCqqN;e`aoCdTM-H5rchxZhUc3vLgqR zpa7#F2P1@JU@-1xnaRSyV0?__3JWYgkfsDdO+X2-VkDB0NwBq#kJf*g#X#Am#l^%5&`y82&|AD;%Aq+|fq`EX@iY(i`x_dyF_m;sE;#$Jp8 zj1c?yOHwOJU@{C0#vx1*Odvg=3K1sE$ZWiTaWQ1#ALdo0kxV3IOW3x8ZIlPk+@pm# zBeUR=m5hwW(o70W5Xgy&dv^*x`otb=x$;(-o~<pq7YpBVX8A_u>`5BVQF9i z1rTy+jjotk@Y{bzMq_bi1!nYUDlRDk6$R-?PRwE|hPvK9IkPA^2ieb2%n8h}QUg4k zh;9{=U_uHbqp>2hDl;VD{+ARb<`w58mN4+A##dB=MpP9TLGw!(Bq$FsO=n_YFrL6X zhna!F_!a9nRt5%RNp@9sun%#J+QOX9$ZUL(=@~e+V4LGaQudhfGb1!0poN`$QGRJ& z3QP$DgE0@QAT)CAi%W{~vylU#h`EBr~x(-2g$%-%*`YOiYs*CDAlW)85sqSo&yz5j4F%(uA*3; diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_inline b/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_meta b/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_meta deleted file mode 100644 index 0ed27b291e8e24d044936619d35889ae91e06d98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 491 zcmea()yZUFU|Z41{KOKFh!6t<11E^Vz`y{J%FHVf zW?*1YW?*1og-R48X6BWsFfcF}FfcIiAPedzC+3wU78^1!Ft{)GBYqNW@cbm%FMv9jG2MqFf#+gRb~c;*UStIKbaXA_*fVi3|SZ$>{%EXN>~^e z*0C@!ykTKr_`<@#@RfyuL7tU?L4lQl!GV>5A%K;EA%m5Hp`4Y0VHqm}!&O!Wh99g9 z3}$Q$44!NZ3=wP$3@L034CQPL4E1ab46SSo4Aa;c7-q3CFw9|NV3^Csz;Kg|fq{>m Qfx(BJfx!=oL16{L00y!{fB*mh diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_warnings b/build/dev/javascript/stellar_prune/_gleam_artefacts/hud.cache_warnings deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/math@math.cache b/build/dev/javascript/stellar_prune/_gleam_artefacts/math@math.cache deleted file mode 100644 index cb4cbb83f6e030e29ac7237592c08ee88c6c3721..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2990 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 JK{R&~HvqH4h+Y5y diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_inline b/build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_meta b/build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_meta deleted file mode 100644 index 3cec355ce2b9a79ca7581bbbaa640fd70c2898db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 643 zcmewwsFTUSz`$T4a88_&9mHZ_VBmz(={c#1x%!!TB_O^40|NsWh{3?X0FlVaEG`jb zU|>*UU|?W|%4C$LC^IlH=rS-cutJ3j5;OBk^cWZztQZ&=c#sA4lN0mG5{s=F7#RE* z7#P@~awUmH>8U0D3=9l0NXC>@7Ni!(GB7Z#VqjpX+*Q}`e0{^39HU|7Szz;Ky?fq|cqfgzBQfng#e1H&Xn28Jb!3=Ah285lk>GB7AJF);Wt zF);KnF)(anVqkdA#K0iP%)k)B%)n5`%)qdonStRZGXuk4W(Ec|76yhu76yh!76yjZ zEDQ{HSQr@CSQ!{}Ss56@SQ!`^Ss56%vNAB-XJudzU}IpgVq;)PU}IqDWMg31!p6Yx zl8u2un4N*ag`I&RkDY;GGCKpqUUmkCckB!d5*!Q+vK$Ny@*E5d3LFd!;T#MMnH&rZ z-5d-ITR9jQo^dcR2yikmm~b*M#Bnk(^m8&W?Brx%c)`iQAjHMM;LOFqkjuruFoTPM z;Sd)C!)GoA23c+f1|@C=1{H1w232kbhE#3_hFWe0hIQNw4BtWGJPZs8JPZs|co-OF z^Dr>X;bCCd#lygGj)#GPm6w6RikE@Gk(YtNiI;()hnIn&mzRNIJ}(2qE?x$PSG)`i z?|B&*KJqd!eBxzb5aDBBFyv!k2;yU4=;vc#IL*hvaGsBW;Q}8610O#Fg8&qR;tYfV DMv_)- diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_warnings b/build/dev/javascript/stellar_prune/_gleam_artefacts/rendering.cache_warnings deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/target.cache b/build/dev/javascript/stellar_prune/_gleam_artefacts/target.cache deleted file mode 100644 index fc7937e0aa16d2a9e2997b04a33cfbcd0ba55896..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10406 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 GRz?8NXu4?t diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_inline b/build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_inline deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_meta b/build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_meta deleted file mode 100644 index 63d7ea9e17a7743cd2500e493a5bab5c4c645fd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193 zcmd-x(#d3CU|@Lk!Bv@&8N^~>V1UsXr70j0Q3eJEb`XPsfuSIyvN$ujSd4*z!H$7} zfek8Ll30|UT4K+@z!1g2z`%c1by14U;*BCuSr7%%0g{hqU|@)0U|=X=U|?urU|^Wf zz`(GTfq~&L0|Ubq1_p*V3=9k(7#J8nF)%QEW?*38U}RtrW@KOpU}RwEW@KRKg<_DI GAPfNCav4eh diff --git a/build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_warnings b/build/dev/javascript/stellar_prune/_gleam_artefacts/types.cache_warnings deleted file mode 100644 index 1b1cb4d44c57c2d7a5122870fa6ac3e62ff7e94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 JcmZR80ssIA00961 diff --git a/build/dev/javascript/stellar_prune/browser_ffi.mjs b/build/dev/javascript/stellar_prune/browser_ffi.mjs deleted file mode 100644 index ef62a4c..0000000 --- a/build/dev/javascript/stellar_prune/browser_ffi.mjs +++ /dev/null @@ -1,40 +0,0 @@ -let mouseX = 0; -let mouseY = 0; -let mousePressed = false; - -if (typeof window !== 'undefined') { - const canvas = document.getElementById('canvas'); - - window.addEventListener('mousemove', (e) => { - if (canvas) { - const rect = canvas.getBoundingClientRect(); - const scaleX = canvas.width / rect.width; - const scaleY = canvas.height / rect.height; - mouseX = (e.clientX - rect.left) * scaleX; - mouseY = (e.clientY - rect.top) * scaleY; - } else { - mouseX = e.clientX; - mouseY = e.clientY; - } - }); - - window.addEventListener('mousedown', () => { - mousePressed = true; - }); - - window.addEventListener('mouseup', () => { - mousePressed = false; - }); -} - -export function request_animation_frame(callback) { - requestAnimationFrame(() => callback()); -} - -export function get_mouse_position() { - return { x: mouseX, y: mouseY }; -} - -export function is_mouse_pressed() { - return mousePressed; -} diff --git a/build/dev/javascript/stellar_prune/game.mjs b/build/dev/javascript/stellar_prune/game.mjs deleted file mode 100644 index 7410e69..0000000 --- a/build/dev/javascript/stellar_prune/game.mjs +++ /dev/null @@ -1,325 +0,0 @@ -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $paint from "../paint/paint.mjs"; -import { request_animation_frame, get_mouse_position, is_mouse_pressed } from "./browser_ffi.mjs"; -import { Ok, toList, prepend as listPrepend, CustomType as $CustomType, isEqual } from "./gleam.mjs"; -import * as $hud from "./hud.mjs"; -import { CrossHair, Health, Hud, Score } from "./hud.mjs"; -import * as $physics from "./physics.mjs"; -import { Gravity, Physics, Vec2 } from "./physics.mjs"; -import * as $rendering from "./rendering.mjs"; -import * as $target from "./target.mjs"; -import { Diamond, Lucy, Rocket } from "./target.mjs"; -import * as $types from "./types.mjs"; -import { GameOver, MainMenu, Playing, PlayingState } from "./types.mjs"; - -export { is_mouse_pressed, request_animation_frame }; - -export class TargetClickEffect extends $CustomType { - constructor(score_change, health_change) { - super(); - this.score_change = score_change; - this.health_change = health_change; - } -} -export const TargetClickEffect$TargetClickEffect = (score_change, health_change) => - new TargetClickEffect(score_change, health_change); -export const TargetClickEffect$isTargetClickEffect = (value) => - value instanceof TargetClickEffect; -export const TargetClickEffect$TargetClickEffect$score_change = (value) => - value.score_change; -export const TargetClickEffect$TargetClickEffect$0 = (value) => - value.score_change; -export const TargetClickEffect$TargetClickEffect$health_change = (value) => - value.health_change; -export const TargetClickEffect$TargetClickEffect$1 = (value) => - value.health_change; - -export class TargetFilterResult extends $CustomType { - constructor(remaining_targets, health_loss) { - super(); - this.remaining_targets = remaining_targets; - this.health_loss = health_loss; - } -} -export const TargetFilterResult$TargetFilterResult = (remaining_targets, health_loss) => - new TargetFilterResult(remaining_targets, health_loss); -export const TargetFilterResult$isTargetFilterResult = (value) => - value instanceof TargetFilterResult; -export const TargetFilterResult$TargetFilterResult$remaining_targets = (value) => - value.remaining_targets; -export const TargetFilterResult$TargetFilterResult$0 = (value) => - value.remaining_targets; -export const TargetFilterResult$TargetFilterResult$health_loss = (value) => - value.health_loss; -export const TargetFilterResult$TargetFilterResult$1 = (value) => - value.health_loss; - -export class SpawnResult extends $CustomType { - constructor(targets, spawn_timer) { - super(); - this.targets = targets; - this.spawn_timer = spawn_timer; - } -} -export const SpawnResult$SpawnResult = (targets, spawn_timer) => - new SpawnResult(targets, spawn_timer); -export const SpawnResult$isSpawnResult = (value) => - value instanceof SpawnResult; -export const SpawnResult$SpawnResult$targets = (value) => value.targets; -export const SpawnResult$SpawnResult$0 = (value) => value.targets; -export const SpawnResult$SpawnResult$spawn_timer = (value) => value.spawn_timer; -export const SpawnResult$SpawnResult$1 = (value) => value.spawn_timer; - -function init_playing_state() { - return new PlayingState( - toList([]), - new Physics(new Gravity(new Vec2(0.0, 0.08))), - new Hud( - new Score( - new Vec2(1050.0, 70.0), - new $target.Colorable($paint.colour_hex("#ffffff")), - 0, - ), - new CrossHair( - new Vec2(0.0, 0.0), - new $target.Colorable($paint.colour_hex("#ffffff")), - 5.0, - ), - new Health(new Vec2(30.0, 30.0), 120.0, 3, 3), - ), - new Vec2(0.0, 0.0), - 0.0, - ); -} - -function get_target_click_effects(kind) { - if (kind instanceof Lucy) { - return new TargetClickEffect(1, 0); - } else if (kind instanceof Diamond) { - let points_value = kind.points_value; - return new TargetClickEffect(points_value, 0); - } else { - return new TargetClickEffect(0, -1); - } -} - -function filter_out_of_bounds_targets(targets) { - return $list.fold( - targets, - new TargetFilterResult(toList([]), 0), - (acc, target) => { - let $ = target.position.y > 900.0; - if ($) { - let $1 = target.kind; - if ($1 instanceof Rocket) { - return acc; - } else { - return new TargetFilterResult( - acc.remaining_targets, - acc.health_loss + 1, - ); - } - } else { - return new TargetFilterResult( - listPrepend(target, acc.remaining_targets), - acc.health_loss, - ); - } - }, - ); -} - -function should_spawn_new_target(spawn_timer, active_targets, score) { - let spawn_interval = 60.0; - let max_targets = 1 + (globalThis.Math.trunc(score / 5)); - return (spawn_timer >= spawn_interval) && ($list.length(active_targets) < max_targets); -} - -function handle_target_click(playing_state, clicked_target) { - let new_targets = $list.filter( - playing_state.targets, - (target) => { return !isEqual(target, clicked_target); }, - ); - let effect = get_target_click_effects(clicked_target.kind); - return new PlayingState( - new_targets, - playing_state.physics, - (() => { - let _record = playing_state.hud; - return new Hud( - (() => { - let _record$1 = playing_state.hud.score; - return new Score( - _record$1.position, - _record$1.colorable, - playing_state.hud.score.score + effect.score_change, - ); - })(), - _record.cross_hair, - (() => { - let _record$1 = playing_state.hud.health; - return new Health( - _record$1.position, - _record$1.size, - playing_state.hud.health.amount + effect.health_change, - _record$1.max_health, - ); - })(), - ); - })(), - playing_state.mouse, - playing_state.spawn_timer, - ); -} - -function update_playing_state(playing_state) { - let $ = playing_state.physics; - let gravity; - gravity = $.gravity; - let updated_targets = $list.map( - playing_state.targets, - (target) => { return $target.update_target(target, gravity.acceleration); }, - ); - let filter_result = filter_out_of_bounds_targets(updated_targets); - let new_spawn_timer = playing_state.spawn_timer + 1.0; - let _block; - let $1 = should_spawn_new_target( - new_spawn_timer, - filter_result.remaining_targets, - playing_state.hud.score.score, - ); - if ($1) { - _block = new SpawnResult( - listPrepend($target.create_target(), filter_result.remaining_targets), - 0.0, - ); - } else { - _block = new SpawnResult(filter_result.remaining_targets, new_spawn_timer); - } - let spawn_result = _block; - let new_mouse = get_mouse_position(); - return new PlayingState( - spawn_result.targets, - playing_state.physics, - (() => { - let _record = playing_state.hud; - return new Hud( - _record.score, - (() => { - let _record$1 = playing_state.hud.cross_hair; - return new CrossHair(new_mouse, _record$1.colorable, _record$1.size); - })(), - (() => { - let _record$1 = playing_state.hud.health; - return new Health( - _record$1.position, - _record$1.size, - playing_state.hud.health.amount - filter_result.health_loss, - _record$1.max_health, - ); - })(), - ); - })(), - new_mouse, - spawn_result.spawn_timer, - ); -} - -function update_state(state) { - if (state instanceof MainMenu) { - return state; - } else if (state instanceof Playing) { - let playing_state = state.state; - let prev_mouse = state.previous_mouse_pressed; - return new Playing(update_playing_state(playing_state), prev_mouse); - } else { - return state; - } -} - -function find_clicked_target(mouse, targets) { - return $list.find( - targets, - (target) => { return $target.is_point_in_target(mouse, target); }, - ); -} - -function handle_playing_click(playing_state) { - let $ = find_clicked_target(playing_state.mouse, playing_state.targets); - if ($ instanceof Ok) { - let clicked_target = $[0]; - return handle_target_click(playing_state, clicked_target); - } else { - return playing_state; - } -} - -function handle_main_menu_click(mouse_pressed) { - if (mouse_pressed) { - return new Playing(init_playing_state(), false); - } else { - return new MainMenu(); - } -} - -function handle_playing_state(playing_state, mouse_pressed) { - let _block; - if (mouse_pressed) { - _block = handle_playing_click(playing_state); - } else { - _block = playing_state; - } - let new_state = _block; - let $ = new_state.hud.health.amount <= 0; - if ($) { - return new GameOver(new_state.hud.score.score, mouse_pressed); - } else { - return new Playing(new_state, mouse_pressed); - } -} - -function handle_game_over_click( - final_score, - mouse_pressed, - previous_mouse_pressed -) { - let just_clicked = mouse_pressed && !previous_mouse_pressed; - if (just_clicked) { - return new Playing(init_playing_state(), false); - } else { - return new GameOver(final_score, mouse_pressed); - } -} - -function handle_events(state) { - let current_mouse_pressed = is_mouse_pressed(); - if (state instanceof MainMenu) { - return handle_main_menu_click(current_mouse_pressed); - } else if (state instanceof Playing) { - let playing_state = state.state; - return handle_playing_state(playing_state, current_mouse_pressed); - } else { - let final_score = state.final_score; - let previous_mouse_pressed = state.previous_mouse_pressed; - return handle_game_over_click( - final_score, - current_mouse_pressed, - previous_mouse_pressed, - ); - } -} - -function game_loop(state) { - $rendering.render(state); - return request_animation_frame( - () => { - let _pipe = handle_events(state); - let _pipe$1 = update_state(_pipe); - return game_loop(_pipe$1); - }, - ); -} - -export function main() { - return game_loop(new MainMenu()); -} diff --git a/build/dev/javascript/stellar_prune/gleam.mjs b/build/dev/javascript/stellar_prune/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/build/dev/javascript/stellar_prune/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/build/dev/javascript/stellar_prune/hud.mjs b/build/dev/javascript/stellar_prune/hud.mjs deleted file mode 100644 index fafec79..0000000 --- a/build/dev/javascript/stellar_prune/hud.mjs +++ /dev/null @@ -1,153 +0,0 @@ -import * as $float from "../gleam_stdlib/gleam/float.mjs"; -import * as $int from "../gleam_stdlib/gleam/int.mjs"; -import * as $paint from "../paint/paint.mjs"; -import * as $canvas from "../paint/paint/canvas.mjs"; -import { toList, CustomType as $CustomType } from "./gleam.mjs"; -import * as $physics from "./physics.mjs"; -import { Vec2 } from "./physics.mjs"; -import * as $target from "./target.mjs"; -import { Colorable } from "./target.mjs"; - -export class Score extends $CustomType { - constructor(position, colorable, score) { - super(); - this.position = position; - this.colorable = colorable; - this.score = score; - } -} -export const Score$Score = (position, colorable, score) => - new Score(position, colorable, score); -export const Score$isScore = (value) => value instanceof Score; -export const Score$Score$position = (value) => value.position; -export const Score$Score$0 = (value) => value.position; -export const Score$Score$colorable = (value) => value.colorable; -export const Score$Score$1 = (value) => value.colorable; -export const Score$Score$score = (value) => value.score; -export const Score$Score$2 = (value) => value.score; - -export class CrossHair extends $CustomType { - constructor(position, colorable, size) { - super(); - this.position = position; - this.colorable = colorable; - this.size = size; - } -} -export const CrossHair$CrossHair = (position, colorable, size) => - new CrossHair(position, colorable, size); -export const CrossHair$isCrossHair = (value) => value instanceof CrossHair; -export const CrossHair$CrossHair$position = (value) => value.position; -export const CrossHair$CrossHair$0 = (value) => value.position; -export const CrossHair$CrossHair$colorable = (value) => value.colorable; -export const CrossHair$CrossHair$1 = (value) => value.colorable; -export const CrossHair$CrossHair$size = (value) => value.size; -export const CrossHair$CrossHair$2 = (value) => value.size; - -export class Health extends $CustomType { - constructor(position, size, amount, max_health) { - super(); - this.position = position; - this.size = size; - this.amount = amount; - this.max_health = max_health; - } -} -export const Health$Health = (position, size, amount, max_health) => - new Health(position, size, amount, max_health); -export const Health$isHealth = (value) => value instanceof Health; -export const Health$Health$position = (value) => value.position; -export const Health$Health$0 = (value) => value.position; -export const Health$Health$size = (value) => value.size; -export const Health$Health$1 = (value) => value.size; -export const Health$Health$amount = (value) => value.amount; -export const Health$Health$2 = (value) => value.amount; -export const Health$Health$max_health = (value) => value.max_health; -export const Health$Health$3 = (value) => value.max_health; - -export class Hud extends $CustomType { - constructor(score, cross_hair, health) { - super(); - this.score = score; - this.cross_hair = cross_hair; - this.health = health; - } -} -export const Hud$Hud = (score, cross_hair, health) => - new Hud(score, cross_hair, health); -export const Hud$isHud = (value) => value instanceof Hud; -export const Hud$Hud$score = (value) => value.score; -export const Hud$Hud$0 = (value) => value.score; -export const Hud$Hud$cross_hair = (value) => value.cross_hair; -export const Hud$Hud$1 = (value) => value.cross_hair; -export const Hud$Hud$health = (value) => value.health; -export const Hud$Hud$2 = (value) => value.health; - -export function score_to_picture(score) { - let position; - let color; - let score$1; - position = score.position; - score$1 = score.score; - color = score.colorable.color; - let _pipe = $paint.text("Score: " + $int.to_string(score$1), 32); - let _pipe$1 = $paint.translate_xy(_pipe, position.x, position.y); - return $paint.fill(_pipe$1, color); -} - -export function cross_hair_to_picture(cross_hair) { - let x; - let y; - let color; - let size; - size = cross_hair.size; - x = cross_hair.position.x; - y = cross_hair.position.y; - color = cross_hair.colorable.color; - let _pipe = $paint.circle(size); - let _pipe$1 = $paint.stroke(_pipe, color, 5.0); - return $paint.translate_xy(_pipe$1, x, y); -} - -function health_to_picture_helper(loop$health, loop$acc, loop$count) { - while (true) { - let health = loop$health; - let acc = loop$acc; - let count = loop$count; - let $ = count < health.max_health; - if ($) { - let _block; - let $1 = count < health.amount; - if ($1) { - _block = $canvas.image_from_src("../res/heart.svg"); - } else { - _block = $canvas.image_from_src("../res/no-heart.svg"); - } - let heart_image = _block; - let size = $float.round(health.size); - loop$health = health; - loop$acc = $paint.combine( - toList([ - acc, - (() => { - let _pipe = $paint.image(heart_image, size, size); - let _pipe$1 = $paint.image_scaling_pixelated(_pipe); - return $paint.translate_xy( - _pipe$1, - $int.to_float(count) * (health.size + 10.0), - 0.0, - ); - })(), - ]), - ); - loop$count = count + 1; - } else { - return acc; - } - } -} - -export function health_to_picture(health) { - let _pipe = health_to_picture_helper(health, $paint.blank(), 0); - return $paint.translate_xy(_pipe, health.position.x, health.position.y); -} diff --git a/build/dev/javascript/stellar_prune/math/math.mjs b/build/dev/javascript/stellar_prune/math/math.mjs deleted file mode 100644 index cbe2232..0000000 --- a/build/dev/javascript/stellar_prune/math/math.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { sin, cos, tan, atan2, floor, ceil, round, random, pi } from "./math_ffi.mjs"; - -export { atan2, ceil, cos, floor, pi, random, round, sin, tan }; diff --git a/build/dev/javascript/stellar_prune/math/math_ffi.mjs b/build/dev/javascript/stellar_prune/math/math_ffi.mjs deleted file mode 100644 index 8736bc2..0000000 --- a/build/dev/javascript/stellar_prune/math/math_ffi.mjs +++ /dev/null @@ -1,35 +0,0 @@ -export function sin(x) { - return Math.sin(x); -} - -export function cos(x) { - return Math.cos(x); -} - -export function tan(x) { - return Math.tan(x); -} - -export function atan2(y, x) { - return Math.atan2(y, x); -} - -export function floor(x) { - return Math.floor(x); -} - -export function ceil(x) { - return Math.ceil(x); -} - -export function round(x) { - return Math.round(x); -} - -export function random() { - return Math.random(); -} - -export function pi() { - return Math.PI; -} diff --git a/build/dev/javascript/stellar_prune/physics.mjs b/build/dev/javascript/stellar_prune/physics.mjs deleted file mode 100644 index d0eb5a4..0000000 --- a/build/dev/javascript/stellar_prune/physics.mjs +++ /dev/null @@ -1,63 +0,0 @@ -import { CustomType as $CustomType } from "./gleam.mjs"; - -export class Vec2 extends $CustomType { - constructor(x, y) { - super(); - this.x = x; - this.y = y; - } -} -export const Vec2$Vec2 = (x, y) => new Vec2(x, y); -export const Vec2$isVec2 = (value) => value instanceof Vec2; -export const Vec2$Vec2$x = (value) => value.x; -export const Vec2$Vec2$0 = (value) => value.x; -export const Vec2$Vec2$y = (value) => value.y; -export const Vec2$Vec2$1 = (value) => value.y; - -export class RigidBody extends $CustomType { - constructor(velocity, acceleration, rotation, rotation_velocity) { - super(); - this.velocity = velocity; - this.acceleration = acceleration; - this.rotation = rotation; - this.rotation_velocity = rotation_velocity; - } -} -export const RigidBody$RigidBody = (velocity, acceleration, rotation, rotation_velocity) => - new RigidBody(velocity, acceleration, rotation, rotation_velocity); -export const RigidBody$isRigidBody = (value) => value instanceof RigidBody; -export const RigidBody$RigidBody$velocity = (value) => value.velocity; -export const RigidBody$RigidBody$0 = (value) => value.velocity; -export const RigidBody$RigidBody$acceleration = (value) => value.acceleration; -export const RigidBody$RigidBody$1 = (value) => value.acceleration; -export const RigidBody$RigidBody$rotation = (value) => value.rotation; -export const RigidBody$RigidBody$2 = (value) => value.rotation; -export const RigidBody$RigidBody$rotation_velocity = (value) => - value.rotation_velocity; -export const RigidBody$RigidBody$3 = (value) => value.rotation_velocity; - -export class Gravity extends $CustomType { - constructor(acceleration) { - super(); - this.acceleration = acceleration; - } -} -export const Gravity$Gravity = (acceleration) => new Gravity(acceleration); -export const Gravity$isGravity = (value) => value instanceof Gravity; -export const Gravity$Gravity$acceleration = (value) => value.acceleration; -export const Gravity$Gravity$0 = (value) => value.acceleration; - -export class Physics extends $CustomType { - constructor(gravity) { - super(); - this.gravity = gravity; - } -} -export const Physics$Physics = (gravity) => new Physics(gravity); -export const Physics$isPhysics = (value) => value instanceof Physics; -export const Physics$Physics$gravity = (value) => value.gravity; -export const Physics$Physics$0 = (value) => value.gravity; - -export function add_vec2(v1, v2) { - return new Vec2(v1.x + v2.x, v1.y + v2.y); -} diff --git a/build/dev/javascript/stellar_prune/rendering.mjs b/build/dev/javascript/stellar_prune/rendering.mjs deleted file mode 100644 index 457b2f8..0000000 --- a/build/dev/javascript/stellar_prune/rendering.mjs +++ /dev/null @@ -1,155 +0,0 @@ -import * as $int from "../gleam_stdlib/gleam/int.mjs"; -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $paint from "../paint/paint.mjs"; -import * as $canvas from "../paint/paint/canvas.mjs"; -import { toList, prepend as listPrepend } from "./gleam.mjs"; -import * as $hud from "./hud.mjs"; -import * as $target from "./target.mjs"; -import * as $types from "./types.mjs"; -import { GameOver, MainMenu, Playing } from "./types.mjs"; - -function draw_main_menu() { - let lucy_image = $canvas.image_from_src("../res/lucy.svg"); - let diamond_image = $canvas.image_from_src("../res/diamond.svg"); - let rocket_image = $canvas.image_from_src("../res/rocket.svg"); - return $paint.combine( - toList([ - (() => { - let _pipe = $paint.text("Stellar prune", 72); - let _pipe$1 = $paint.translate_xy(_pipe, 300.0, 100.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffffff")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.text("Click/swipe the targets to score points!", 28); - let _pipe$1 = $paint.translate_xy(_pipe, 320.0, 200.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#aaaaaa")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.text( - "Don't let them escape or you'll lose health!", - 28, - ); - let _pipe$1 = $paint.translate_xy(_pipe, 320.0, 240.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#aaaaaa")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.image(lucy_image, 80, 80); - let _pipe$1 = $paint.image_scaling_pixelated(_pipe); - return $paint.translate_xy(_pipe$1, 320.0, 320.0); - })(), - (() => { - let _pipe = $paint.text("Lucy - Click for 1 point.", 24); - let _pipe$1 = $paint.translate_xy(_pipe, 420.0, 370.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffffff")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.image(diamond_image, 80, 80); - let _pipe$1 = $paint.image_scaling_pixelated(_pipe); - return $paint.translate_xy(_pipe$1, 320.0, 420.0); - })(), - (() => { - let _pipe = $paint.text("Diamond - Click for 3 points!", 24); - let _pipe$1 = $paint.translate_xy(_pipe, 420.0, 460.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffffff")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.image(rocket_image, 80, 80); - let _pipe$1 = $paint.image_scaling_pixelated(_pipe); - return $paint.translate_xy(_pipe$1, 320.0, 520.0); - })(), - (() => { - let _pipe = $paint.text("Rocket - AVOID! Loses 1 health", 24); - let _pipe$1 = $paint.translate_xy(_pipe, 420.0, 560.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ff6666")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.text("Click to play!", 48); - let _pipe$1 = $paint.translate_xy(_pipe, 420.0, 680.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffaff3")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - ]), - ); -} - -function draw_game_over(final_score) { - return $paint.combine( - toList([ - (() => { - let _pipe = $paint.text("Well done!", 128); - let _pipe$1 = $paint.translate_xy(_pipe, 300.0, 175.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffaff3")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.text("Final Score: ", 48); - let _pipe$1 = $paint.translate_xy(_pipe, 440.0, 400.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffffff")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.text($int.to_string(final_score), 48); - let _pipe$1 = $paint.translate_xy(_pipe, 710.0, 400.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffaff3")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - (() => { - let _pipe = $paint.text("Click to play again!", 32); - let _pipe$1 = $paint.translate_xy(_pipe, 455.0, 600.0); - let _pipe$2 = $paint.fill(_pipe$1, $paint.colour_hex("#ffaff3")); - return $paint.image_scaling_pixelated(_pipe$2); - })(), - ]), - ); -} - -function draw_playing(playing_state) { - let target_pictures = $list.map( - playing_state.targets, - (target) => { - let position; - let rigid_body; - let paintable; - position = target.position; - rigid_body = target.rigid_body; - paintable = target.paintable; - let _pipe = $target.paintable_to_picture(paintable); - let _pipe$1 = $paint.rotate(_pipe, $paint.angle_deg(rigid_body.rotation)); - return $paint.translate_xy(_pipe$1, position.x, position.y); - }, - ); - let hud_without_crosshair = $paint.combine( - toList([ - $hud.health_to_picture(playing_state.hud.health), - $hud.score_to_picture(playing_state.hud.score), - ]), - ); - let crosshair = $hud.cross_hair_to_picture(playing_state.hud.cross_hair); - return $paint.combine( - listPrepend( - hud_without_crosshair, - $list.append(target_pictures, toList([crosshair])), - ), - ); -} - -export function render(state) { - let _block; - if (state instanceof MainMenu) { - _block = draw_main_menu(); - } else if (state instanceof Playing) { - let playing_state = state.state; - _block = draw_playing(playing_state); - } else { - let final_score = state.final_score; - _block = draw_game_over(final_score); - } - let picture = _block; - return $canvas.display((_) => { return picture; }, "#canvas"); -} diff --git a/build/dev/javascript/stellar_prune/target.mjs b/build/dev/javascript/stellar_prune/target.mjs deleted file mode 100644 index 04732a2..0000000 --- a/build/dev/javascript/stellar_prune/target.mjs +++ /dev/null @@ -1,194 +0,0 @@ -import * as $int from "../gleam_stdlib/gleam/int.mjs"; -import * as $paint from "../paint/paint.mjs"; -import * as $canvas from "../paint/paint/canvas.mjs"; -import { CustomType as $CustomType } from "./gleam.mjs"; -import * as $math from "./math/math.mjs"; -import * as $physics from "./physics.mjs"; -import { RigidBody, Vec2, add_vec2 } from "./physics.mjs"; - -export class Colorable extends $CustomType { - constructor(color) { - super(); - this.color = color; - } -} -export const Colorable$Colorable = (color) => new Colorable(color); -export const Colorable$isColorable = (value) => value instanceof Colorable; -export const Colorable$Colorable$color = (value) => value.color; -export const Colorable$Colorable$0 = (value) => value.color; - -export class Size extends $CustomType { - constructor(width, height) { - super(); - this.width = width; - this.height = height; - } -} -export const Size$Size = (width, height) => new Size(width, height); -export const Size$isSize = (value) => value instanceof Size; -export const Size$Size$width = (value) => value.width; -export const Size$Size$0 = (value) => value.width; -export const Size$Size$height = (value) => value.height; -export const Size$Size$1 = (value) => value.height; - -export class Square extends $CustomType { - constructor(colorable, size) { - super(); - this.colorable = colorable; - this.size = size; - } -} -export const Paintable$Square = (colorable, size) => - new Square(colorable, size); -export const Paintable$isSquare = (value) => value instanceof Square; -export const Paintable$Square$colorable = (value) => value.colorable; -export const Paintable$Square$0 = (value) => value.colorable; -export const Paintable$Square$size = (value) => value.size; -export const Paintable$Square$1 = (value) => value.size; - -export class Sprite extends $CustomType { - constructor(image, size) { - super(); - this.image = image; - this.size = size; - } -} -export const Paintable$Sprite = (image, size) => new Sprite(image, size); -export const Paintable$isSprite = (value) => value instanceof Sprite; -export const Paintable$Sprite$image = (value) => value.image; -export const Paintable$Sprite$0 = (value) => value.image; -export const Paintable$Sprite$size = (value) => value.size; -export const Paintable$Sprite$1 = (value) => value.size; - -export class Lucy extends $CustomType {} -export const TargetKind$Lucy = () => new Lucy(); -export const TargetKind$isLucy = (value) => value instanceof Lucy; - -export class Diamond extends $CustomType { - constructor(points_value) { - super(); - this.points_value = points_value; - } -} -export const TargetKind$Diamond = (points_value) => new Diamond(points_value); -export const TargetKind$isDiamond = (value) => value instanceof Diamond; -export const TargetKind$Diamond$points_value = (value) => value.points_value; -export const TargetKind$Diamond$0 = (value) => value.points_value; - -export class Rocket extends $CustomType {} -export const TargetKind$Rocket = () => new Rocket(); -export const TargetKind$isRocket = (value) => value instanceof Rocket; - -export class Target extends $CustomType { - constructor(position, rigid_body, paintable, kind) { - super(); - this.position = position; - this.rigid_body = rigid_body; - this.paintable = paintable; - this.kind = kind; - } -} -export const Target$Target = (position, rigid_body, paintable, kind) => - new Target(position, rigid_body, paintable, kind); -export const Target$isTarget = (value) => value instanceof Target; -export const Target$Target$position = (value) => value.position; -export const Target$Target$0 = (value) => value.position; -export const Target$Target$rigid_body = (value) => value.rigid_body; -export const Target$Target$1 = (value) => value.rigid_body; -export const Target$Target$paintable = (value) => value.paintable; -export const Target$Target$2 = (value) => value.paintable; -export const Target$Target$kind = (value) => value.kind; -export const Target$Target$3 = (value) => value.kind; - -export function create_target() { - let vx = ($math.random() * 6.0) - 3.0; - let vy = ($math.random() * -4.0) - 8.0; - let rotation_vel = ($math.random() * 2.0) - 1.0; - let start_x = ($math.random() * 600.0) + 200.0; - let random_type = $math.random(); - let _block; - let r = random_type; - if (r < 0.7) { - _block = ["../res/lucy.svg", new Lucy()]; - } else { - let r$1 = random_type; - if (r$1 < 0.85) { - _block = ["../res/diamond.svg", new Diamond(3)]; - } else { - _block = ["../res/rocket.svg", new Rocket()]; - } - } - let $ = _block; - let sprite_path; - let target_kind; - sprite_path = $[0]; - target_kind = $[1]; - return new Target( - new Vec2(start_x, 900.0), - new RigidBody(new Vec2(vx, vy), new Vec2(0.0, 0.0), 0.0, rotation_vel), - new Sprite($canvas.image_from_src(sprite_path), new Size(120, 120)), - target_kind, - ); -} - -export function update_target(target, gravity) { - let $ = target.rigid_body; - let velocity; - let acceleration; - let rotation; - let rotation_velocity; - velocity = $.velocity; - acceleration = $.acceleration; - rotation = $.rotation; - rotation_velocity = $.rotation_velocity; - let total_acceleration = add_vec2(acceleration, gravity); - let new_velocity = add_vec2(velocity, total_acceleration); - let new_position = add_vec2(target.position, new_velocity); - let new_rigid_body = new RigidBody( - new_velocity, - acceleration, - rotation + rotation_velocity, - rotation_velocity, - ); - return new Target(new_position, new_rigid_body, target.paintable, target.kind); -} - -export function is_point_in_target(point, target) { - let dx = point.x - target.position.x; - let dy = point.y - target.position.y; - let angle_rad = ((target.rigid_body.rotation * $math.pi())) / 180.0; - let cos_angle = $math.cos(angle_rad); - let sin_angle = $math.sin(angle_rad); - let local_x = (dx * cos_angle) + (dy * sin_angle); - let local_y = (dy * cos_angle) - (dx * sin_angle); - let $ = target.paintable; - if ($ instanceof Square) { - let size = $.size; - let half_size = size / 2.0; - return (((local_x >= (0.0 - half_size)) && (local_x <= half_size)) && (local_y >= (0.0 - half_size))) && (local_y <= half_size); - } else { - let size = $.size; - let half_width = $int.to_float(size.width) / 2.0; - let half_height = $int.to_float(size.height) / 2.0; - return (((local_x >= (0.0 - half_width)) && (local_x <= half_width)) && (local_y >= (0.0 - half_height))) && (local_y <= half_height); - } -} - -export function paintable_to_picture(paintable) { - if (paintable instanceof Square) { - let colorable = paintable.colorable; - let size = paintable.size; - let _pipe = $paint.square(size); - return $paint.fill(_pipe, colorable.color); - } else { - let image = paintable.image; - let size = paintable.size; - let _pipe = $paint.image(image, size.width, size.height); - let _pipe$1 = $paint.image_scaling_pixelated(_pipe); - return $paint.translate_xy( - _pipe$1, - 0.0 - ($int.to_float(size.width) / 2.0), - 0.0 - ($int.to_float(size.height) / 2.0), - ); - } -} diff --git a/build/dev/javascript/stellar_prune/types.mjs b/build/dev/javascript/stellar_prune/types.mjs deleted file mode 100644 index 72fff8f..0000000 --- a/build/dev/javascript/stellar_prune/types.mjs +++ /dev/null @@ -1,66 +0,0 @@ -import { CustomType as $CustomType } from "./gleam.mjs"; -import * as $hud from "./hud.mjs"; -import * as $physics from "./physics.mjs"; -import * as $target from "./target.mjs"; - -export class PlayingState extends $CustomType { - constructor(targets, physics, hud, mouse, spawn_timer) { - super(); - this.targets = targets; - this.physics = physics; - this.hud = hud; - this.mouse = mouse; - this.spawn_timer = spawn_timer; - } -} -export const PlayingState$PlayingState = (targets, physics, hud, mouse, spawn_timer) => - new PlayingState(targets, physics, hud, mouse, spawn_timer); -export const PlayingState$isPlayingState = (value) => - value instanceof PlayingState; -export const PlayingState$PlayingState$targets = (value) => value.targets; -export const PlayingState$PlayingState$0 = (value) => value.targets; -export const PlayingState$PlayingState$physics = (value) => value.physics; -export const PlayingState$PlayingState$1 = (value) => value.physics; -export const PlayingState$PlayingState$hud = (value) => value.hud; -export const PlayingState$PlayingState$2 = (value) => value.hud; -export const PlayingState$PlayingState$mouse = (value) => value.mouse; -export const PlayingState$PlayingState$3 = (value) => value.mouse; -export const PlayingState$PlayingState$spawn_timer = (value) => - value.spawn_timer; -export const PlayingState$PlayingState$4 = (value) => value.spawn_timer; - -export class MainMenu extends $CustomType {} -export const GameState$MainMenu = () => new MainMenu(); -export const GameState$isMainMenu = (value) => value instanceof MainMenu; - -export class Playing extends $CustomType { - constructor(state, previous_mouse_pressed) { - super(); - this.state = state; - this.previous_mouse_pressed = previous_mouse_pressed; - } -} -export const GameState$Playing = (state, previous_mouse_pressed) => - new Playing(state, previous_mouse_pressed); -export const GameState$isPlaying = (value) => value instanceof Playing; -export const GameState$Playing$state = (value) => value.state; -export const GameState$Playing$0 = (value) => value.state; -export const GameState$Playing$previous_mouse_pressed = (value) => - value.previous_mouse_pressed; -export const GameState$Playing$1 = (value) => value.previous_mouse_pressed; - -export class GameOver extends $CustomType { - constructor(final_score, previous_mouse_pressed) { - super(); - this.final_score = final_score; - this.previous_mouse_pressed = previous_mouse_pressed; - } -} -export const GameState$GameOver = (final_score, previous_mouse_pressed) => - new GameOver(final_score, previous_mouse_pressed); -export const GameState$isGameOver = (value) => value instanceof GameOver; -export const GameState$GameOver$final_score = (value) => value.final_score; -export const GameState$GameOver$0 = (value) => value.final_score; -export const GameState$GameOver$previous_mouse_pressed = (value) => - value.previous_mouse_pressed; -export const GameState$GameOver$1 = (value) => value.previous_mouse_pressed; diff --git a/build/gleam-dev-erlang.lock b/build/gleam-dev-erlang.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/gleam-dev-javascript.lock b/build/gleam-dev-javascript.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/gleam-lsp-erlang.lock b/build/gleam-lsp-erlang.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/gleam-lsp-javascript.lock b/build/gleam-lsp-javascript.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/gleam-prod-erlang.lock b/build/gleam-prod-erlang.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/gleam-prod-javascript.lock b/build/gleam-prod-javascript.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/packages/gleam.lock b/build/packages/gleam.lock deleted file mode 100644 index e69de29..0000000 diff --git a/build/packages/gleam_community_colour/LICENCE b/build/packages/gleam_community_colour/LICENCE deleted file mode 100644 index a84f0ec..0000000 --- a/build/packages/gleam_community_colour/LICENCE +++ /dev/null @@ -1,190 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2023 Gleam Community Contributors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/build/packages/gleam_community_colour/README.md b/build/packages/gleam_community_colour/README.md deleted file mode 100644 index 0eccdd7..0000000 --- a/build/packages/gleam_community_colour/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# gleam-community/colour - -A package for a standard Colour type, conversions, and other utilities. - -[![Package Version](https://img.shields.io/hexpm/v/gleam_community_colour)](https://hex.pm/packages/gleam_community_colour) -[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/gleam_community_colour/) - -✨ This project is written in pure Gleam so you can use it anywhere Gleam runs: Erlang, Elixir, Node, Deno, and the browser! - ---- - -## Quickstart - -```gleam -import gleam_community/colour -import gleam_community/colour/accessibility - -pub fn main() { - let foreground = colour.from_hsl(h: 0.858, s: 1.0, l: 0.843) - - let background_options = [colour.light_grey, colour.dark_grey] - - let background = accessibility.maximum_contrast(foreground, background_options) -} -``` - -## Installation - -`gleam_community` packages are published to [hex.pm](https://hex.pm/packages/gleam_community_colour) -with the prefix `gleam_community_`. You can add them to your Gleam projects directly: - -```sh -gleam add gleam_community_colour -``` - -The docs can be found over at [hexdocs.pm](https://hexdocs.pm/gleam_community_colour). diff --git a/build/packages/gleam_community_colour/gleam.toml b/build/packages/gleam_community_colour/gleam.toml deleted file mode 100644 index 3b7155c..0000000 --- a/build/packages/gleam_community_colour/gleam.toml +++ /dev/null @@ -1,13 +0,0 @@ -name = "gleam_community_colour" -version = "2.0.2" -licences = ["Apache-2.0"] -description = "Colour types, conversions, and other utilities" -repository = { type = "github", user = "gleam-community", repo = "colour" } -gleam = ">= 1.4.0" - -[dependencies] -gleam_stdlib = ">= 0.50.0 and < 2.0.0" -gleam_json = ">= 2.2.0 and < 4.0.0" - -[dev-dependencies] -gleeunit = ">= 1.3.0 and < 2.0.0" diff --git a/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl b/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl deleted file mode 100644 index 06116df..0000000 --- a/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl +++ /dev/null @@ -1 +0,0 @@ --record(hsla, {h :: float(), s :: float(), l :: float(), a :: float()}). diff --git a/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl b/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl deleted file mode 100644 index fff139e..0000000 --- a/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl +++ /dev/null @@ -1 +0,0 @@ --record(rgba, {r :: float(), g :: float(), b :: float(), a :: float()}). diff --git a/build/packages/gleam_community_colour/src/gleam_community/colour.gleam b/build/packages/gleam_community_colour/src/gleam_community/colour.gleam deleted file mode 100644 index f394cff..0000000 --- a/build/packages/gleam_community_colour/src/gleam_community/colour.gleam +++ /dev/null @@ -1,1214 +0,0 @@ -//// -//// - **Types** -//// - [`Colour`](#Colour) -//// - [`Color`](#Color) -//// - **Constructors** -//// - [`from_rgb255`](#from_rgb255) -//// - [`from_rgb`](#from_rgb) -//// - [`from_rgba`](#from_rgba) -//// - [`from_hsl`](#from_hsl) -//// - [`from_hsla`](#from_hsla) -//// - [`from_rgb_hex`](#from_rgb_hex) -//// - [`from_rgba_hex`](#from_rgba_hex) -//// - [`from_rgb_hex_string`](#from_rgb_hex_string) -//// - [`from_rgba_hex_string`](#from_rgba_hex_string) -//// - **Conversions** -//// - [`to_rgba`](#to_rgba) -//// - [`to_hsla`](#hsla) -//// - [`to_css_rgba_string`](#to_css_rgba_string) -//// - [`to_rgba_hex_string`](#to_rgba_hex_string) -//// - [`to_rgb_hex_string`](#to_rgb_hex_string) -//// - [`to_rgba_hex`](#to_rgba_hex) -//// - [`to_rgb_hex`](#to_rgb_hex) -//// - **JSON** -//// - [`encode`](#encode) -//// - [`decoder`](#decoder) -//// - **Colours** -//// - [`light_red`](#light_red) -//// - [`red`](#red) -//// - [`dark_red`](#dark_red) -//// - [`light_orange`](#light_orange) -//// - [`orange`](#orange) -//// - [`dark_orange`](#dark_orange) -//// - [`light_yellow`](#light_yellow) -//// - [`yellow`](#yellow) -//// - [`dark_yellow`](#dark_yellow) -//// - [`light_green`](#light_green) -//// - [`green`](#green) -//// - [`dark_green`](#dark_green) -//// - [`light_blue`](#light_blue) -//// - [`blue`](#blue) -//// - [`dark_blue`](#dark_blue) -//// - [`light_purple`](#light_purple) -//// - [`purple`](#purple) -//// - [`dark_purple`](#dark_purple) -//// - [`light_brown`](#light_brown) -//// - [`brown`](#brown) -//// - [`dark_brown`](#dark_brown) -//// - [`black`](#black) -//// - [`white`](#white) -//// - [`light_grey`](#light_grey) -//// - [`grey`](#grey) -//// - [`dark_grey`](#dark_grey) -//// - [`light_gray`](#light_gray) -//// - [`gray`](#gray) -//// - [`dark_gray`](#dark_gray) -//// - [`light_charcoal`](#light_charcoal) -//// - [`charcoal`](#charcoal) -//// - [`dark_charcoal`](#dark_charcoal) -//// - [`pink`](#pink) -//// -//// --- -//// -//// This package was heavily inspired by the `elm-color` module. -//// The original source code can be found -//// here. -//// -////