diff --git a/assets/js/app.js b/assets/js/app.js index 1bbca15..727741c 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -31,6 +31,8 @@ if (!csrfToken) { import MapAPRSMap from "./map"; // Import error boundary hook import ErrorBoundary from "./hooks/error_boundary"; +// Import info map hook +import { InfoMap } from "./hooks/info_map"; // Responsive Slideover Hook let ResponsiveSlideoverHook = { @@ -105,6 +107,7 @@ Hooks.APRSMap = MapAPRSMap; Hooks.ResponsiveSlideoverHook = ResponsiveSlideoverHook; Hooks.BodyClassHook = BodyClassHook; Hooks.ErrorBoundary = ErrorBoundary; +Hooks.InfoMap = InfoMap; // Register weather chart hooks from TypeScript import { WeatherChartHooks } from "./features/weather_charts"; diff --git a/assets/js/hooks/info_map.js b/assets/js/hooks/info_map.js new file mode 100644 index 0000000..ed5d907 --- /dev/null +++ b/assets/js/hooks/info_map.js @@ -0,0 +1,89 @@ +// Simple map hook for displaying a single station on the info page +export const InfoMap = { + mounted() { + // Check if Leaflet is available + if (typeof L === "undefined") { + console.error("Leaflet not loaded for InfoMap"); + return; + } + + // Get data from element attributes + const lat = parseFloat(this.el.dataset.lat); + const lon = parseFloat(this.el.dataset.lon); + const zoom = parseInt(this.el.dataset.zoom) || 13; + const callsign = this.el.dataset.callsign; + const symbolHtml = this.el.dataset.symbolHtml; + + // Validate coordinates + if (isNaN(lat) || isNaN(lon)) { + console.error("Invalid coordinates for InfoMap"); + return; + } + + // Initialize the map + try { + this.map = L.map(this.el, { + center: [lat, lon], + zoom: zoom, + scrollWheelZoom: false, // Disable scroll zoom for embedded maps + zoomControl: true, + attributionControl: true + }); + + // Add tile layer + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap', + maxZoom: 19 + }).addTo(this.map); + + // Create marker icon + let markerIcon; + if (symbolHtml) { + // Use the APRS symbol if provided + markerIcon = L.divIcon({ + html: symbolHtml, + className: 'aprs-info-marker', + iconSize: [32, 32], + iconAnchor: [16, 16] + }); + } else { + // Default marker + markerIcon = L.divIcon({ + html: `
`, + className: '', + iconSize: [24, 24], + iconAnchor: [12, 12] + }); + } + + // Add marker for the station + const marker = L.marker([lat, lon], { icon: markerIcon }) + .addTo(this.map) + .bindPopup(`${callsign}
Lat: ${lat.toFixed(6)}
Lon: ${lon.toFixed(6)}`); + + // Invalidate size after a short delay to ensure proper rendering + setTimeout(() => { + if (this.map) { + this.map.invalidateSize(); + } + }, 250); + + } catch (error) { + console.error("Error initializing InfoMap:", error); + } + }, + + destroyed() { + if (this.map) { + this.map.remove(); + this.map = null; + } + } +}; \ No newline at end of file diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@@main.erl b/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@@main.erl deleted file mode 100644 index ae11abb..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@@main.erl +++ /dev/null @@ -1,100 +0,0 @@ --module('aprsme@@main'). --export([run/1]). - --define(red, "\e[31;1m"). --define(grey, "\e[90m"). --define(reset_color, "\e[39m"). --define(reset_all, "\e[0m"). - -run(Module) -> - io:setopts(standard_io, [binary, {encoding, utf8}]), - io:setopts(standard_error, [{encoding, utf8}]), - process_flag(trap_exit, true), - Pid = spawn_link(fun() -> run_module(Module) end), - receive - {'EXIT', Pid, {Reason, StackTrace}} -> - print_error(exit, Reason, StackTrace), - init:stop(1) - end. - -run_module(Module) -> - try - {ok, _} = application:ensure_all_started('aprsme'), - erlang:process_flag(trap_exit, false), - Module:main(), - erlang:halt(0) - catch - Class:Reason:StackTrace -> - print_error(Class, Reason, StackTrace), - init:stop(1) - end. - -print_error(Class, Error, Stacktrace) -> - Printed = [ - ?red, "runtime error", ?reset_color, ": ", error_class(Class, Error), ?reset_all, - "\n\n", - error_message(Error), - "\n\n", - error_details(Class, Error), - "stacktrace:\n", - [error_frame(Line) || Line <- refine_first(Error, Stacktrace)] - ], - io:format(standard_error, "~ts~n", [Printed]). - -refine_first(#{gleam_error := _, line := L}, [{M, F, A, [{file, Fi} | _]} | S]) -> - [{M, F, A, [{file, Fi}, {line, L}]} | S]; -refine_first(_, S) -> - S. - -error_class(_, #{gleam_error := panic}) -> "panic"; -error_class(_, #{gleam_error := todo}) -> "todo"; -error_class(_, #{gleam_error := let_assert}) -> "let assert"; -error_class(_, #{gleam_error := assert}) -> "assert"; -error_class(Class, _) -> ["Erlang ", atom_to_binary(Class)]. - -error_message(#{gleam_error := _, message := M}) -> - M; -error_message(undef) -> - <<"A function was called but it did not exist."/utf8 >>; -error_message({case_clause, _}) -> - <<"No pattern matched in an Erlang case expression."/utf8>>; -error_message({badmatch, _}) -> - <<"An Erlang assignment pattern did not match."/utf8>>; -error_message(function_clause) -> - <<"No Erlang function clause matched the arguments it was called with."/utf8>>; -error_message(_) -> - <<"An error occurred outside of Gleam."/utf8>>. - -error_details(_, #{gleam_error := let_assert, value := V}) -> - ["unmatched value:\n ", print_term(V), $\n, $\n]; -error_details(_, {case_clause, V}) -> - ["unmatched value:\n ", print_term(V), $\n, $\n]; -error_details(_, {badmatch, V}) -> - ["unmatched value:\n ", print_term(V), $\n, $\n]; -error_details(_, #{gleam_error := _}) -> - []; -error_details(error, function_clause) -> - []; -error_details(error, undef) -> - []; -error_details(C, E) -> - ["erlang:", atom_to_binary(C), $(, print_term(E), $), $\n, $\n]. - -print_term(T) -> - try - gleam@string:inspect(T) - catch - _:_ -> io_lib:format("~p", [T]) - end. - -error_frame({?MODULE, _, _, _}) -> []; -error_frame({erl_eval, _, _, _}) -> []; -error_frame({init, _, _, _}) -> []; -error_frame({M, F, _, O}) -> - M1 = string:replace(atom_to_binary(M), "@", "/", all), - [" ", M1, $., atom_to_binary(F), error_frame_end(O), $\n]. - -error_frame_end([{file, Fi}, {line, L} | _]) -> - [?grey, $\s, Fi, $:, integer_to_binary(L), ?reset_all]; -error_frame_end(_) -> - [?grey, " unknown source", ?reset_all]. \ No newline at end of file diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.cache b/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.cache deleted file mode 100644 index acddc36..0000000 Binary files a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.cache and /dev/null differ diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.cache_meta b/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.cache_meta deleted file mode 100644 index a9f9645..0000000 Binary files a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.cache_meta and /dev/null differ diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.erl b/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.erl deleted file mode 100644 index fdcee8b..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/aprsme@encoding.erl +++ /dev/null @@ -1,275 +0,0 @@ --module(aprsme@encoding). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/aprsme/encoding.gleam"). --export([sanitize_string/1, to_float_safe/1, to_hex/1, has_weather_data/4, encoding_info/1]). --export_type([encoding_info/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 encoding_info() :: {encoding_info, - boolean(), - integer(), - gleam@option:option(integer()), - gleam@option:option(integer())}. - --file("src/aprsme/encoding.gleam", 29). --spec do_bit_array_to_list(bitstring(), list(integer())) -> list(integer()). -do_bit_array_to_list(Input, Acc) -> - case erlang:byte_size(Input) of - 0 -> - Acc; - - _ -> - case gleam_stdlib:bit_array_slice(Input, 0, 1) of - {ok, <>} -> - case gleam_stdlib:bit_array_slice( - Input, - 1, - erlang:byte_size(Input) - 1 - ) of - {ok, Rest} -> - do_bit_array_to_list(Rest, [Byte | Acc]); - - {error, _} -> - [Byte | Acc] - end; - - _ -> - Acc - end - end. - --file("src/aprsme/encoding.gleam", 24). -?DOC(" Convert BitArray to list of bytes\n"). --spec bit_array_to_list(bitstring()) -> list(integer()). -bit_array_to_list(Input) -> - _pipe = do_bit_array_to_list(Input, []), - lists:reverse(_pipe). - --file("src/aprsme/encoding.gleam", 48). -?DOC(" Convert latin1 encoded bytes to UTF-8 string\n"). --spec latin1_to_utf8_string(bitstring()) -> binary(). -latin1_to_utf8_string(Input) -> - _pipe = Input, - _pipe@1 = bit_array_to_list(_pipe), - _pipe@2 = gleam@list:filter_map(_pipe@1, fun(Byte) -> case Byte of - B when B =< 127 -> - case gleam@bit_array:to_string(<>) of - {ok, S} -> - {ok, S}; - - {error, _} -> - {error, nil} - end; - - B@1 -> - Byte1 = 192 + (B@1 div 64), - Byte2 = 128 + (B@1 rem 64), - case gleam@bit_array:to_string(<>) of - {ok, S@1} -> - {ok, S@1}; - - {error, _} -> - {error, nil} - end - end end), - gleam@string:join(_pipe@2, <<""/utf8>>). - --file("src/aprsme/encoding.gleam", 77). -?DOC(" Remove control characters from a string\n"). --spec clean_control_characters(binary()) -> binary(). -clean_control_characters(S) -> - _pipe = S, - _pipe@1 = gleam@string:to_graphemes(_pipe), - _pipe@2 = gleam@list:filter( - _pipe@1, - fun(Grapheme) -> case gleam@string:to_utf_codepoints(Grapheme) of - [Codepoint] -> - Cp = gleam_stdlib:identity(Codepoint), - case Cp of - 9 -> - true; - - 10 -> - true; - - 13 -> - true; - - C when (C >= 0) andalso (C =< 31) -> - false; - - 127 -> - false; - - C@1 when (C@1 >= 128) andalso (C@1 =< 159) -> - false; - - _ -> - true - end; - - _ -> - true - end end - ), - _pipe@3 = gleam@string:join(_pipe@2, <<""/utf8>>), - gleam@string:trim(_pipe@3). - --file("src/aprsme/encoding.gleam", 10). -?DOC( - " Sanitizes a binary to ensure it can be safely JSON encoded\n" - " Handles latin1 conversion and removes control characters\n" -). --spec sanitize_string(bitstring()) -> binary(). -sanitize_string(Input) -> - case gleam@bit_array:to_string(Input) of - {ok, S} -> - clean_control_characters(S); - - {error, _} -> - _pipe = Input, - _pipe@1 = latin1_to_utf8_string(_pipe), - clean_control_characters(_pipe@1) - end. - --file("src/aprsme/encoding.gleam", 104). -?DOC(" Type-safe float conversion with validation\n"). --spec to_float_safe(binary()) -> gleam@option:option(float()). -to_float_safe(Value) -> - Sanitized = begin - _pipe = Value, - _pipe@1 = gleam@string:trim(_pipe), - gleam@string:slice(_pipe@1, 0, 30) - end, - case gleam_stdlib:parse_float(Sanitized) of - {ok, F} -> - case F of - X when (X > -9.0e15) andalso (X < 9.0e15) -> - {some, F}; - - _ -> - none - end; - - {error, _} -> - none - end. - --file("src/aprsme/encoding.gleam", 129). --spec do_to_hex(bitstring(), list(binary())) -> list(binary()). -do_to_hex(Input, Acc) -> - case gleam_stdlib:bit_array_slice(Input, 0, 1) of - {ok, <>} -> - Rest = case gleam_stdlib:bit_array_slice( - Input, - 1, - erlang:byte_size(Input) - 1 - ) of - {ok, R} -> - R; - - {error, _} -> - <<>> - end, - Hex = gleam@int:to_base16(Byte), - Padded = case string:length(Hex) of - 1 -> - <<"0"/utf8, Hex/binary>>; - - _ -> - Hex - end, - do_to_hex(Rest, [Padded | Acc]); - - _ -> - Acc - end. - --file("src/aprsme/encoding.gleam", 122). -?DOC(" Convert binary to hex string\n"). --spec to_hex(bitstring()) -> binary(). -to_hex(Input) -> - _pipe = do_to_hex(Input, []), - _pipe@1 = lists:reverse(_pipe), - _pipe@2 = gleam@string:join(_pipe@1, <<""/utf8>>), - string:uppercase(_pipe@2). - --file("src/aprsme/encoding.gleam", 148). -?DOC(" Check if a value looks like it has weather data\n"). --spec has_weather_data( - gleam@option:option(float()), - gleam@option:option(float()), - gleam@option:option(float()), - gleam@option:option(float()) -) -> boolean(). -has_weather_data(Temperature, Humidity, Wind_speed, Pressure) -> - case {Temperature, Humidity, Wind_speed, Pressure} of - {{some, _}, _, _, _} -> - true; - - {_, {some, _}, _, _} -> - true; - - {_, _, {some, _}, _} -> - true; - - {_, _, _, {some, _}} -> - true; - - {_, _, _, _} -> - false - end. - --file("src/aprsme/encoding.gleam", 192). --spec find_invalid_byte_position(bitstring(), integer()) -> gleam@option:option(integer()). -find_invalid_byte_position(Input, Pos) -> - case erlang:byte_size(Input) of - 0 -> - none; - - _ -> - case gleam_stdlib:bit_array_slice(Input, 0, 1) of - {ok, Byte_slice} -> - case gleam@bit_array:to_string(Byte_slice) of - {ok, _} -> - case gleam_stdlib:bit_array_slice( - Input, - 1, - erlang:byte_size(Input) - 1 - ) of - {ok, Rest} -> - find_invalid_byte_position(Rest, Pos + 1); - - {error, _} -> - {some, Pos} - end; - - {error, _} -> - {some, Pos} - end; - - {error, _} -> - {some, Pos} - end - end. - --file("src/aprsme/encoding.gleam", 170). -?DOC(" Get encoding information about a binary\n"). --spec encoding_info(bitstring()) -> encoding_info(). -encoding_info(Input) -> - Byte_count = erlang:byte_size(Input), - case gleam@bit_array:to_string(Input) of - {ok, S} -> - {encoding_info, true, Byte_count, {some, string:length(S)}, none}; - - {error, _} -> - Invalid_pos = find_invalid_byte_position(Input, 0), - {encoding_info, false, Byte_count, none, Invalid_pos} - end. diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/assets/js/map_helpers_test.ts b/build/dev/erlang/aprsme/_gleam_artefacts/assets/js/map_helpers_test.ts deleted file mode 100644 index 3eae93d..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/assets/js/map_helpers_test.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { describe, test, expect, beforeEach, afterEach, vi } from 'vitest'; -import { - parseTimestamp, - getTrailId, - saveMapState, - safePushEvent, - isLiveViewConnected, - getLiveSocket -} from '../../../assets/js/map_helpers'; - -describe('map_helpers', () => { - describe('parseTimestamp', () => { - test('returns current time for null/undefined', () => { - const before = Date.now(); - const result = parseTimestamp(null); - const after = Date.now(); - expect(result).toBeGreaterThanOrEqual(before); - expect(result).toBeLessThanOrEqual(after); - }); - - test('returns number timestamp as-is', () => { - const timestamp = 1234567890; - expect(parseTimestamp(timestamp)).toBe(timestamp); - }); - - test('parses string timestamp', () => { - const dateStr = '2024-01-01T00:00:00Z'; - const expected = new Date(dateStr).getTime(); - expect(parseTimestamp(dateStr)).toBe(expected); - }); - - test('returns current time for invalid input', () => { - const before = Date.now(); - const result = parseTimestamp({}); - const after = Date.now(); - expect(result).toBeGreaterThanOrEqual(before); - expect(result).toBeLessThanOrEqual(after); - }); - }); - - describe('getTrailId', () => { - test('prioritizes callsign_group', () => { - const data = { - callsign_group: 'GROUP-1', - callsign: 'CALL-1', - id: 'ID-1' - }; - expect(getTrailId(data)).toBe('GROUP-1'); - }); - - test('falls back to callsign when no callsign_group', () => { - const data = { - callsign: 'CALL-1', - id: 'ID-1' - }; - expect(getTrailId(data)).toBe('CALL-1'); - }); - - test('falls back to id when no callsign_group or callsign', () => { - const data = { - id: 'ID-1' - }; - expect(getTrailId(data)).toBe('ID-1'); - }); - }); - - describe('saveMapState', () => { - let mockMap: any; - let mockPushEvent: any; - - beforeEach(() => { - // Mock localStorage - const localStorageMock = { - setItem: vi.fn() - }; - Object.defineProperty(window, 'localStorage', { - value: localStorageMock, - writable: true - }); - - // Mock map object - mockMap = { - getCenter: vi.fn().mockReturnValue({ lat: 40.7128, lng: -74.0060 }), - getZoom: vi.fn().mockReturnValue(10), - getBounds: vi.fn().mockReturnValue({ - getNorth: vi.fn().mockReturnValue(41.0), - getSouth: vi.fn().mockReturnValue(40.0), - getEast: vi.fn().mockReturnValue(-73.0), - getWest: vi.fn().mockReturnValue(-75.0) - }) - }; - - mockPushEvent = vi.fn(); - }); - - test('saves truncated coordinates to localStorage', () => { - saveMapState(mockMap, mockPushEvent); - - expect(localStorage.setItem).toHaveBeenCalledWith( - 'aprs_map_state', - JSON.stringify({ lat: 40.7128, lng: -74.006, zoom: 10 }) - ); - }); - - test('pushes event with map state and bounds', () => { - saveMapState(mockMap, mockPushEvent); - - expect(mockPushEvent).toHaveBeenCalledWith('update_map_state', { - center: { lat: 40.7128, lng: -74.006 }, - zoom: 10, - bounds: { - north: 41.0, - south: 40.0, - east: -73.0, - west: -75.0 - } - }); - }); - - test('truncates coordinates to 5 decimal places', () => { - mockMap.getCenter.mockReturnValue({ lat: 40.71281234567, lng: -74.00601234567 }); - - saveMapState(mockMap, mockPushEvent); - - const call = mockPushEvent.mock.calls[0][1]; - expect(call.center.lat).toBe(40.71281); - expect(call.center.lng).toBe(-74.00601); - }); - }); - - describe('safePushEvent', () => { - test('calls pushEvent and returns true on success', () => { - const mockPushEvent = vi.fn(); - const result = safePushEvent(mockPushEvent, 'test_event', { data: 'test' }); - - expect(mockPushEvent).toHaveBeenCalledWith('test_event', { data: 'test' }); - expect(result).toBe(true); - }); - - test('returns false when pushEvent is undefined', () => { - const result = safePushEvent(undefined, 'test_event', { data: 'test' }); - expect(result).toBe(false); - }); - - test('catches error and returns false', () => { - const mockPushEvent = vi.fn().mockImplementation(() => { - throw new Error('LiveView not connected'); - }); - - const consoleSpy = vi.spyOn(console, 'debug').mockImplementation(() => {}); - const result = safePushEvent(mockPushEvent, 'test_event', { data: 'test' }); - - expect(result).toBe(false); - expect(consoleSpy).toHaveBeenCalledWith('Unable to send test_event event - LiveView disconnected'); - - consoleSpy.mockRestore(); - }); - }); - - describe('LiveView socket helpers', () => { - afterEach(() => { - // Clean up window.liveSocket - delete (window as any).liveSocket; - }); - - test('isLiveViewConnected returns true when socket exists', () => { - (window as any).liveSocket = { connected: true }; - expect(isLiveViewConnected()).toBe(true); - }); - - test('isLiveViewConnected returns false when socket missing', () => { - expect(isLiveViewConnected()).toBe(false); - }); - - test('getLiveSocket returns the socket', () => { - const mockSocket = { connected: true, pushHistoryPatch: vi.fn() }; - (window as any).liveSocket = mockSocket; - - expect(getLiveSocket()).toBe(mockSocket); - }); - - test('getLiveSocket returns undefined when missing', () => { - expect(getLiveSocket()).toBeUndefined(); - }); - }); -}); \ No newline at end of file diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/aprs_is_mock.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/aprs_is_mock.ex deleted file mode 100644 index b43faa8..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/aprs_is_mock.ex +++ /dev/null @@ -1,167 +0,0 @@ -defmodule AprsIsMock do - @moduledoc """ - Mock implementation of Aprs.Is for testing purposes. - This ensures no external APRS connections are made during tests. - """ - - use GenServer - - require Logger - - def start_link(opts \\ []) do - GenServer.start_link(__MODULE__, opts, name: __MODULE__) - end - - @impl true - def init(_opts) do - # Mock connection state - initial_state = %{ - connected: false, - server: "mock.aprs.test", - port: 14_580, - connected_at: nil, - login_id: "TEST", - filter: "r/33/-96/100", - packet_stats: %{ - total_packets: 0, - last_packet_at: nil, - packets_per_second: 0, - last_second_count: 0, - last_second_timestamp: System.system_time(:second) - }, - stored_packet_count: 0 - } - - {:ok, initial_state} - end - - # Client API - Mock implementations - - def stop do - GenServer.stop(__MODULE__, :normal) - end - - def get_status do - case Process.whereis(__MODULE__) do - nil -> - # Mock disconnected state - %{ - connected: false, - server: "mock.aprs.test", - port: 14_580, - connected_at: nil, - uptime_seconds: 0, - login_id: "TEST", - filter: "r/33/-96/100", - packet_stats: %{ - total_packets: 0, - last_packet_at: nil, - packets_per_second: 0, - last_second_count: 0, - last_second_timestamp: System.system_time(:second) - }, - stored_packet_count: 0 - } - - _pid -> - try do - GenServer.call(__MODULE__, :get_status, 5000) - catch - :exit, _ -> - # Fallback mock state - %{ - connected: false, - server: "mock.aprs.test", - port: 14_580, - connected_at: nil, - uptime_seconds: 0, - login_id: "TEST", - filter: "r/33/-96/100", - packet_stats: %{ - total_packets: 0, - last_packet_at: nil, - packets_per_second: 0, - last_second_count: 0, - last_second_timestamp: System.system_time(:second) - }, - stored_packet_count: 0 - } - end - end - end - - def set_filter(_filter_string) do - :ok - end - - def list_active_filters do - :ok - end - - def send_message(_from, _to, _message) do - :ok - end - - def send_message(message) do - GenServer.call(__MODULE__, {:send_message, message}) - end - - # Server callbacks - - @impl true - def handle_call({:send_message, _message}, _from, state) do - {:reply, :ok, state} - end - - def handle_call(:get_status, _from, state) do - uptime_seconds = - if state.connected_at do - DateTime.diff(DateTime.utc_now(), state.connected_at, :second) - else - 0 - end - - mock_status = - Map.put(state, :uptime_seconds, uptime_seconds) - - {:reply, mock_status, state} - end - - def handle_call({:set_connection_state, connected}, _from, state) do - new_state = %{ - state - | connected: connected, - connected_at: if(connected, do: DateTime.utc_now()) - } - - {:reply, :ok, new_state} - end - - @impl true - def handle_info(_msg, state) do - {:noreply, state} - end - - @impl true - def terminate(_reason, _state) do - :ok - end - - # Helper functions for testing - - def simulate_packet(packet_data) do - # Simulate receiving an APRS packet for testing purposes. - # This can be used in tests to trigger packet processing without - # connecting to external servers. - - # Broadcast to live clients like the real implementation would - AprsmeWeb.Endpoint.broadcast("aprs_messages", "packet", packet_data) - - :ok - end - - def simulate_connection_state(connected \\ true) do - # Simulate connection state changes for testing. - GenServer.call(__MODULE__, {:set_connection_state, connected}) - end -end diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/conn_case.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/conn_case.ex deleted file mode 100644 index b8a28d4..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/conn_case.ex +++ /dev/null @@ -1,74 +0,0 @@ -defmodule AprsmeWeb.ConnCase do - @moduledoc """ - This module defines the test case to be used by - tests that require setting up a connection. - - Such tests rely on `Phoenix.ConnTest` and also - import other functionality to make it easier - to build common data structures and query the data layer. - - Finally, if the test case interacts with the database, - we enable the SQL sandbox, so changes done to the database - are reverted at the end of every test. If you use PostgreSQL, you - can even run database tests asynchronously by setting - `use AprsmeWeb.ConnCase, async: true`, although - this option is not recommended for other databases. - """ - - use ExUnit.CaseTemplate - - using do - quote do - # The default import for connections - use AprsmeWeb, :verified_routes - - import Aprsme.MockHelpers - import AprsmeWeb.ConnCase - import Phoenix.ConnTest - import Plug.Conn - - alias Aprsme.Repo - - # The default endpoint for testing - @endpoint AprsmeWeb.Endpoint - - # Import conveniences for testing with connections - - # The default import for Repo - end - end - - setup tags do - Aprsme.DataCase.setup_sandbox(tags) - {:ok, conn: Phoenix.ConnTest.build_conn()} - end - - @doc """ - A helper that sets up the test case. - - use AprsmeWeb.ConnCase, async: true - - """ - def setup_sandbox(_tags) do - Aprsme.MockHelpers.stub_packets_mock() - :ok - end - - @doc """ - A helper that logs in a user. - - setup %{conn: conn} do - conn = log_in_user(conn, user) - {:ok, conn: conn} - end - - """ - def log_in_user(conn, user) do - token = Aprsme.Accounts.generate_user_session_token(user) - - conn - |> Phoenix.ConnTest.init_test_session(%{}) - |> Plug.Conn.put_session(:user_token, token) - |> Plug.Conn.put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}") - end -end diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/data_case.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/data_case.ex deleted file mode 100644 index 806d7f2..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/data_case.ex +++ /dev/null @@ -1,78 +0,0 @@ -defmodule Aprsme.DataCase do - @moduledoc """ - This module defines the test case to be used by - data tests. - - You may define functions here to be used as helpers in - your data tests. See `errors_on/2`'s definition as an example. - - Finally, if the test case interacts with the database, - we enable the SQL sandbox, so changes done to the database - are reverted at the end of every test. If you use PostgreSQL, you - can even run database tests asynchronously by setting - `use Aprsme.DataCase, async: true`, although - this option is not recommended for other databases. - """ - - use ExUnit.CaseTemplate - - alias Ecto.Adapters.SQL.Sandbox - - using do - quote do - import Aprsme.DataCase - # Import conveniences for testing with connections - import Ecto - import Ecto.Changeset - import Ecto.Query - - # and other functionality to make calls such as: - # import Aprsme.DataCase - # Aprsme.DataCase.errors_on(MySchema.changeset(%MySchema{}, %{})) - - # The default import for Repo - alias Aprsme.Repo - end - end - - setup tags do - Aprsme.DataCase.setup_sandbox(tags) - Aprsme.DevicesSeeder.seed_from_json() - :ok - end - - @doc """ - A helper that transforms changeset errors into a map of messages. - - iex> errors_on(MySchema.changeset(%MySchema{}, %{field: bad_value})) - %{field: ["has invalid value"]} - - """ - def errors_on(changeset) do - Ecto.Changeset.traverse_errors(changeset, &translate_error/1) - end - - @doc """ - Sets up the sandbox and allows the test case - to be run asynchronously. - """ - def setup_sandbox(tags) do - pid = Sandbox.start_owner!(Aprsme.Repo, shared: not tags[:async]) - on_exit(fn -> Sandbox.stop_owner(pid) end) - end - - defp translate_error({msg, opts}) do - # You can make use of gettext to translate error messages by - # uncommenting and adjusting the following code: - - # if count = opts[:count] do - # Gettext.dngettext(AprsmeWeb.Gettext, "errors", msg, msg, count, opts) - # else - # Gettext.dgettext(AprsmeWeb.Gettext, "errors", msg, opts) - # end - - Enum.reduce(opts, msg, fn {key, value}, acc -> - String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end) - end) - end -end diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/fixtures/accounts_fixtures.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/fixtures/accounts_fixtures.ex deleted file mode 100644 index 4c6921b..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/fixtures/accounts_fixtures.ex +++ /dev/null @@ -1,37 +0,0 @@ -defmodule Aprsme.AccountsFixtures do - @moduledoc """ - This module defines test helpers for creating - entities via the `Aprsme.Accounts` context. - """ - - def unique_user_email, do: "user#{System.unique_integer()}@example.com" - def valid_user_password, do: "hello world!" - - def unique_user_callsign do - num = rem(System.unique_integer([:positive]), 99) + 1 - "K#{num}ABC" - end - - def valid_user_attributes(attrs \\ %{}) do - Enum.into(attrs, %{ - email: unique_user_email(), - password: valid_user_password(), - callsign: unique_user_callsign() - }) - end - - def user_fixture(attrs \\ %{}) do - {:ok, user} = - attrs - |> valid_user_attributes() - |> Aprsme.Accounts.register_user() - - user - end - - def extract_user_token(fun) do - {:ok, captured_email} = fun.(&"[TOKEN]#{&1}[TOKEN]") - [_, token | _] = String.split(captured_email.text_body, "[TOKEN]") - token - end -end diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/fixtures/packets_fixtures.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/fixtures/packets_fixtures.ex deleted file mode 100644 index 1f88dbc..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/fixtures/packets_fixtures.ex +++ /dev/null @@ -1,54 +0,0 @@ -defmodule Aprsme.PacketsFixtures do - @moduledoc """ - This module defines test helpers for creating - entities via the `Aprsme.Packets` context. - """ - - alias Aprsme.Callsign - alias Aprsme.Packet - alias Aprsme.Repo - - @doc """ - Generate a packet. - """ - def packet_fixture(attrs \\ %{}) do - base_attrs = %{ - sender: "TEST-1", - base_callsign: "TEST", - ssid: "1", - destination: "APRS", - received_at: DateTime.utc_now(), - lat: Decimal.new("40.7128"), - lon: Decimal.new("-74.0060"), - has_position: true, - raw_packet: "TEST-1>APRS:=4042.77N/07400.36W>Test packet", - data_type: "position", - path: "APRS", - data_extended: %{ - symbol_table_id: "/", - symbol_code: ">", - comment: "Test packet" - } - } - - # Extract base_callsign and ssid from sender if provided - final_attrs = - case Map.get(attrs, :sender) do - nil -> - base_attrs - - sender -> - {base, ssid} = Callsign.extract_parts(sender) - - Map.merge(base_attrs, %{base_callsign: base, ssid: ssid}) - end - - {:ok, packet} = - attrs - |> Enum.into(final_attrs) - |> then(&Packet.changeset(%Packet{}, &1)) - |> Repo.insert() - - packet - end -end diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/mock_helpers.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/mock_helpers.ex deleted file mode 100644 index a70ac6c..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/mock_helpers.ex +++ /dev/null @@ -1,32 +0,0 @@ -defmodule Aprsme.MockHelpers do - @moduledoc """ - Helper functions for setting up mocks in tests. - """ - - def stub_packets_mock do - # Stub the packets module to prevent external calls - Mox.stub(Aprsme.PacketsMock, :get_packets_for_callsign, fn _callsign -> - {:ok, []} - end) - - Mox.stub(Aprsme.PacketsMock, :get_packets_for_callsign_with_limit, fn _callsign, _limit -> - {:ok, []} - end) - - Mox.stub(Aprsme.PacketsMock, :get_packets_for_callsign_with_date_range, fn _callsign, _start_date, _end_date -> - {:ok, []} - end) - - Mox.stub(Aprsme.PacketsMock, :get_recent_packets_optimized, fn _opts -> - [] - end) - - Mox.stub(Aprsme.PacketsMock, :get_nearby_stations, fn _lat, _lon, _exclude, _opts -> - [] - end) - end - - def stub_badpackets_mock do - Mox.stub_with(BadPacketsMock, BadPacketsStub) - end -end diff --git a/build/dev/erlang/aprsme/_gleam_artefacts/support/test_helpers.ex b/build/dev/erlang/aprsme/_gleam_artefacts/support/test_helpers.ex deleted file mode 100644 index 9448076..0000000 --- a/build/dev/erlang/aprsme/_gleam_artefacts/support/test_helpers.ex +++ /dev/null @@ -1,81 +0,0 @@ -defmodule AprsmeWeb.TestHelpers do - @moduledoc """ - Common test helper functions to reduce duplication across test files. - """ - - alias Aprsme.Packet - alias Aprsme.Repo - - @doc """ - Creates a test packet with default values that can be overridden. - """ - def create_test_packet(attrs \\ %{}) do - default_attrs = %{ - sender: "TEST-1", - base_callsign: "TEST", - ssid: "1", - lat: Decimal.new("33.0000"), - lon: Decimal.new("-96.0000"), - has_position: true, - received_at: DateTime.truncate(DateTime.utc_now(), :second), - data_type: "position" - } - - attrs = Map.merge(default_attrs, attrs) - - Repo.insert(%Packet{ - sender: attrs.sender, - base_callsign: attrs.base_callsign, - ssid: attrs.ssid, - lat: attrs.lat, - lon: attrs.lon, - has_position: attrs.has_position, - received_at: attrs.received_at, - data_type: attrs.data_type, - symbol_table_id: Map.get(attrs, :symbol_table_id), - symbol_code: Map.get(attrs, :symbol_code), - temperature: Map.get(attrs, :temperature), - humidity: Map.get(attrs, :humidity), - wind_speed: Map.get(attrs, :wind_speed) - }) - end - - @doc """ - Creates common test bounds for Texas area. - """ - def texas_bounds do - %{ - "north" => "33.0", - "south" => "32.0", - "east" => "-96.0", - "west" => "-97.0" - } - end - - @doc """ - Creates common test bounds for a restrictive area. - """ - def restrictive_bounds do - %{ - "north" => "31.0", - "south" => "30.0", - "east" => "-95.0", - "west" => "-96.0" - } - end - - @doc """ - Common time calculations used across tests. - """ - def hours_ago(hours) when is_number(hours) do - DateTime.add(DateTime.utc_now(), -hours * 3600, :second) - end - - def minutes_ago(minutes) when is_number(minutes) do - DateTime.add(DateTime.utc_now(), -minutes * 60, :second) - end - - def days_ago(days) when is_number(days) do - DateTime.add(DateTime.utc_now(), -days * 86_400, :second) - end -end diff --git a/build/dev/erlang/aprsme/ebin/aprsme.app b/build/dev/erlang/aprsme/ebin/aprsme.app deleted file mode 100644 index 524ab0d..0000000 --- a/build/dev/erlang/aprsme/ebin/aprsme.app +++ /dev/null @@ -1,8 +0,0 @@ -{application, aprsme, [ - {vsn, "0.2.0"}, - {applications, [gleam_stdlib, - gleeunit]}, - {description, "APRS packet display with type-safe Gleam modules"}, - {modules, []}, - {registered, []} -]}. diff --git a/build/dev/erlang/aprsme/ebin/aprsme@@main.beam b/build/dev/erlang/aprsme/ebin/aprsme@@main.beam deleted file mode 100644 index d1d4d9f..0000000 Binary files a/build/dev/erlang/aprsme/ebin/aprsme@@main.beam and /dev/null differ diff --git a/build/dev/erlang/aprsme/ebin/aprsme@encoding.beam b/build/dev/erlang/aprsme/ebin/aprsme@encoding.beam deleted file mode 100644 index 1fb10cf..0000000 Binary files a/build/dev/erlang/aprsme/ebin/aprsme@encoding.beam and /dev/null differ diff --git a/build/dev/erlang/aprsme/include/aprsme@encoding_EncodingInfo.hrl b/build/dev/erlang/aprsme/include/aprsme@encoding_EncodingInfo.hrl deleted file mode 100644 index af2aee3..0000000 --- a/build/dev/erlang/aprsme/include/aprsme@encoding_EncodingInfo.hrl +++ /dev/null @@ -1,6 +0,0 @@ --record(encoding_info, { - valid_utf8 :: boolean(), - byte_count :: integer(), - char_count :: gleam@option:option(integer()), - invalid_at :: gleam@option:option(integer()) -}). diff --git a/build/dev/erlang/aprsme/priv b/build/dev/erlang/aprsme/priv deleted file mode 120000 index 4e7b000..0000000 --- a/build/dev/erlang/aprsme/priv +++ /dev/null @@ -1 +0,0 @@ -/Users/graham/dev/aprs.me/priv \ No newline at end of file diff --git a/build/dev/erlang/eex b/build/dev/erlang/eex deleted file mode 120000 index 22b6ea6..0000000 --- a/build/dev/erlang/eex +++ /dev/null @@ -1 +0,0 @@ -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/eex \ No newline at end of file diff --git a/build/dev/erlang/elixir b/build/dev/erlang/elixir deleted file mode 120000 index c0f1160..0000000 --- a/build/dev/erlang/elixir +++ /dev/null @@ -1 +0,0 @@ -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/elixir \ No newline at end of file diff --git a/build/dev/erlang/gleam_elixir_paths b/build/dev/erlang/gleam_elixir_paths deleted file mode 100644 index 8eb6634..0000000 --- a/build/dev/erlang/gleam_elixir_paths +++ /dev/null @@ -1,4 +0,0 @@ -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/eex -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/elixir -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/logger -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/mix \ No newline at end of file diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/dict.mjs b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/dict.mjs deleted file mode 100644 index f39cd54..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/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/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl deleted file mode 100644 index 406deee..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env escript --mode(compile). - -% TODO: Don't concurrently print warnings and errors -% TODO: Some tests - -main(_) -> - ok = io:setopts([binary, {encoding, utf8}]), - ok = configure_logging(), - compile_package_loop(). - -compile_package_loop() -> - case io:get_line("") of - eof -> ok; - Line -> - Chars = unicode:characters_to_list(Line), - {ok, Tokens, _} = erl_scan:string(Chars), - {ok, {Lib, Out, Modules}} = erl_parse:parse_term(Tokens), - case compile_package(Lib, Out, Modules) of - {ok, ModuleNames} -> - PrintModuleName = fun(ModuleName) -> - io:put_chars("gleam-compile-module:" ++ atom_to_list(ModuleName) ++ "\n") - end, - lists:map(PrintModuleName, ModuleNames), - io:put_chars("gleam-compile-result-ok\n"); - err -> - io:put_chars("gleam-compile-result-error\n") - end, - compile_package_loop() - end. - -compile_package(Lib, Out, Modules) -> - IsElixirModule = fun(Module) -> - filename:extension(Module) =:= ".ex" - end, - {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), - ok = filelib:ensure_dir([Out, $/]), - ok = add_lib_to_erlang_path(Lib), - {ErlangOk, ErlangBeams} = compile_erlang(ErlangModules, Out), - {ElixirOk, ElixirBeams} = case ErlangOk of - true -> compile_elixir(ElixirModules, Out); - false -> {false, []} - end, - ok = del_lib_from_erlang_path(Lib), - case ErlangOk andalso ElixirOk of - true -> - ModuleNames = proplists:get_keys(ErlangBeams ++ ElixirBeams), - {ok, ModuleNames}; - false -> - err - end. - -compile_erlang(Modules, Out) -> - Workers = start_compiler_workers(Out), - ok = producer_loop(Modules, Workers), - collect_results({true, []}). - -collect_results(Acc = {Result, Beams}) -> - receive - {compiled, ModuleName, Beam} -> collect_results({Result, [{ModuleName, Beam} | Beams]}); - failed -> collect_results({false, Beams}) - after 0 -> Acc - end. - -producer_loop([], 0) -> - ok; -producer_loop([], Workers) -> - receive - {work_please, _} -> producer_loop([], Workers - 1) - end; -producer_loop([Module | Modules], Workers) -> - receive - {work_please, Worker} -> - erlang:send(Worker, {module, Module}), - producer_loop(Modules, Workers) - end. - -start_compiler_workers(Out) -> - Parent = self(), - NumSchedulers = erlang:system_info(schedulers), - SpawnWorker = fun(_) -> - erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) - end, - lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), - NumSchedulers. - -worker_loop(Parent, Out) -> - Options = [report_errors, report_warnings, debug_info, {outdir, Out}], - erlang:send(Parent, {work_please, self()}), - receive - {module, Module} -> - log({compiling, Module}), - case compile:file(Module, Options) of - {ok, ModuleName} -> - Beam = filename:join(Out, ModuleName) ++ ".beam", - Message = {compiled, ModuleName, Beam}, - log(Message), - erlang:send(Parent, Message); - error -> - log({failed, Module}), - erlang:send(Parent, failed) - end, - worker_loop(Parent, Out) - end. - -compile_elixir(Modules, Out) -> - Error = [ - "The program elixir was not found. Is it installed?", - $\n, - "Documentation for installing Elixir can be viewed here:", - $\n, - "https://elixir-lang.org/install.html" - ], - case Modules of - [] -> {true, []}; - _ -> - log({starting, "compiler.app"}), - ok = application:start(compiler), - log({starting, "elixir.app"}), - case application:start(elixir) of - ok -> do_compile_elixir(Modules, Out); - _ -> - io:put_chars(standard_error, [Error, $\n]), - {false, []} - end - end. - -do_compile_elixir(Modules, Out) -> - ModuleBins = lists:map(fun(Module) -> - log({compiling, Module}), - list_to_binary(Module) - end, Modules), - OutBin = list_to_binary(Out), - Options = [{dest, OutBin}], - % Silence "redefining module" warnings. - % Compiled modules in the build directory are added to the code path. - % These warnings result from recompiling loaded modules. - % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. - 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), - case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of - {ok, ModuleAtoms, _} -> - ToBeam = fun(ModuleAtom) -> - Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", - log({compiled, Beam}), - {ModuleAtom, Beam} - end, - {true, lists:map(ToBeam, ModuleAtoms)}; - {error, Errors, _} -> - % Log all filenames associated with modules that failed to compile. - % Note: The compiler prints compilation errors upon encountering them. - ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), - Log = fun(File) -> - log({failed, binary_to_list(File)}) - end, - lists:foreach(Log, ErrorFiles), - {false, []}; - _ -> {false, []} - end. - -add_lib_to_erlang_path(Lib) -> - code:add_paths(expand_lib_paths(Lib)). - --if(?OTP_RELEASE >= 26). -del_lib_from_erlang_path(Lib) -> - code:del_paths(expand_lib_paths(Lib)). --else. -del_lib_from_erlang_path(Lib) -> - lists:foreach(fun code:del_path/1, expand_lib_paths(Lib)). --endif. - -expand_lib_paths(Lib) -> - filelib:wildcard([Lib, "/*/ebin"]). - -configure_logging() -> - Enabled = os:getenv("GLEAM_LOG") /= false, - persistent_term:put(gleam_logging_enabled, Enabled). - -log(Term) -> - case persistent_term:get(gleam_logging_enabled) of - true -> io:fwrite("~p~n", [Term]), ok; - false -> ok - end. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache deleted file mode 100644 index f851435..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta deleted file mode 100644 index 94c7522..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl deleted file mode 100644 index 80a11e4..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl +++ /dev/null @@ -1,346 +0,0 @@ --module(gleam@bit_array). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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:bit_array_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:base_decode64(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 = gleam_stdlib:bit_array_base64_encode(Input, Padding), - _pipe@1 = gleam@string:replace(_pipe, <<"+"/utf8>>, <<"-"/utf8>>), - gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"_"/utf8>>). - --file("src/gleam/bit_array.gleam", 149). -?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", 163). -?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", 169). -?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", 190). --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", 186). -?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", 231). -?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", 272). -?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/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache deleted file mode 100644 index c374b2d..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta deleted file mode 100644 index c6b30c1..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl deleted file mode 100644 index a09a3eb..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl +++ /dev/null @@ -1,352 +0,0 @@ --module(gleam@bool). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(), BVF, fun(() -> BVF)) -> BVF. -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(() -> BVG), fun(() -> BVG)) -> BVG. -lazy_guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence(); - - false -> - Alternative() - end. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache deleted file mode 100644 index e9a2e2b..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta deleted file mode 100644 index b464c32..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.erl deleted file mode 100644 index 5e78e9c..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/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]). --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(B) -> from_bit_array(B) end), - 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/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache deleted file mode 100644 index aed9b45..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta deleted file mode 100644 index db29c27..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl deleted file mode 100644 index ad3b17b..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl +++ /dev/null @@ -1,561 +0,0 @@ --module(gleam@dict). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(LA, LB) :: any() | {gleam_phantom, LA, LB}. - --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(LK, LL)) -> list({LK, LL}). -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(MN, MO), MN) -> {ok, MO} | {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(MB, any()), MB) -> 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(MT, MU), MT, MU) -> dict(MT, MU). -insert(Dict, Key, Value) -> - maps:put(Key, Value, Dict). - --file("src/gleam/dict.gleam", 92). --spec from_list_loop(list({LU, LV}), dict(LU, LV)) -> dict(LU, LV). -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({LP, LQ})) -> dict(LP, LQ). -from_list(List) -> - maps:from_list(List). - --file("src/gleam/dict.gleam", 223). --spec reverse_and_concat(list(OD), list(OD)) -> list(OD). -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({NY, any()}), list(NY)) -> list(NY). -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(NT, any())) -> list(NT). -keys(Dict) -> - maps:keys(Dict). - --file("src/gleam/dict.gleam", 249). --spec do_values_loop(list({any(), ON}), list(ON)) -> list(ON). -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(), OI)) -> list(OI). -values(Dict) -> - maps:values(Dict). - --file("src/gleam/dict.gleam", 318). --spec do_take_loop(dict(PR, PS), list(PR), dict(PR, PS)) -> dict(PR, PS). -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(PD, PE), list(PD)) -> dict(PD, PE). -take(Dict, Desired_keys) -> - maps:with(Desired_keys, Dict). - --file("src/gleam/dict.gleam", 363). --spec insert_pair(dict(QP, QQ), {QP, QQ}) -> dict(QP, QQ). -insert_pair(Dict, Pair) -> - insert(Dict, erlang:element(1, Pair), erlang:element(2, Pair)). - --file("src/gleam/dict.gleam", 356). --spec fold_inserts(list({QI, QJ}), dict(QI, QJ)) -> dict(QI, QJ). -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(QA, QB), dict(QA, QB)) -> dict(QA, QB). -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(QV, QW), QV) -> dict(QV, QW). -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(RH, RI), list(RH)) -> dict(RH, RI). -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(RO, RP), RO, fun((gleam@option:option(RP)) -> RP)) -> dict(RO, RP). -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({SA, SB}), SD, fun((SD, SA, SB) -> SD)) -> SD. -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(RV, RW), RZ, fun((RZ, RV, RW) -> RZ)) -> RZ. -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(NF, NG), fun((NF, NG) -> NJ)) -> dict(NF, NJ). -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(OR, OS), fun((OR, OS) -> boolean())) -> dict(OR, OS). -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(SE, SF), fun((SE, SF) -> 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(SJ, SK), dict(SJ, SK), fun((SK, SK) -> SK)) -> dict(SJ, SK). -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/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache deleted file mode 100644 index 66b9dcd..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta deleted file mode 100644 index 19152c5..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl deleted file mode 100644 index 027b403..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl +++ /dev/null @@ -1,106 +0,0 @@ --module(gleam@dynamic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(from(\"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/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache deleted file mode 100644 index 833037b..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta deleted file mode 100644 index 525a900..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.erl deleted file mode 100644 index fc66d91..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.erl +++ /dev/null @@ -1,1083 +0,0 @@ --module(gleam@dynamic@decode). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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.from(\"water\"), decoder)\n" - " assert result == Ok(Water)\n" - "\n" - " let result = decode.run(dynamic.from(\"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(BXN) :: {decoder, - fun((gleam@dynamic:dynamic_()) -> {BXN, 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(BXV)) -> {ok, BXV} | - {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", 478). -?DOC( - " Finalise a decoder having successfully extracted a value.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.from(dict.from_list([\n" - " #(\"email\", \"lucy@example.com\"),\n" - " #(\"name\", \"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(BYW) -> decoder(BYW). -success(Data) -> - {decoder, fun(_) -> {Data, []} end}. - --file("src/gleam/dynamic/decode.gleam", 717). --spec decode_dynamic(gleam@dynamic:dynamic_()) -> {gleam@dynamic:dynamic_(), - list(decode_error())}. -decode_dynamic(Data) -> - {Data, []}. - --file("src/gleam/dynamic/decode.gleam", 871). -?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.from(1000), decoder)\n" - " assert result == Ok(\"1000\")\n" - " ```\n" -). --spec map(decoder(CBT), fun((CBT) -> CBV)) -> decoder(CBV). -map(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Transformer(Data), Errors} - end}. - --file("src/gleam/dynamic/decode.gleam", 880). -?DOC(" Apply a transformation function to any errors returned by the decoder.\n"). --spec map_errors( - decoder(CBX), - fun((list(decode_error())) -> list(decode_error())) -) -> decoder(CBX). -map_errors(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Data, Transformer(Errors)} - end}. - --file("src/gleam/dynamic/decode.gleam", 918). -?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(CCF), fun((CCF) -> decoder(CCH))) -> decoder(CCH). -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", 961). --spec run_decoders( - gleam@dynamic:dynamic_(), - {CCP, list(decode_error())}, - list(decoder(CCP)) -) -> {CCP, 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", 948). -?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.from(1000), decoder)\n" - " // -> Ok(\"1000\")\n" - " ```\n" -). --spec one_of(decoder(CCK), list(decoder(CCK))) -> decoder(CCK). -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", 1044). -?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(CDA))) -> decoder(CDA). -recursive(Inner) -> - {decoder, - fun(Data) -> - Decoder = Inner(), - (erlang:element(2, Decoder))(Data) - end}. - --file("src/gleam/dynamic/decode.gleam", 849). -?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.from(100), decode.optional(decode.int))\n" - " assert result == Ok(option.Some(100))\n" - " ```\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.from(Nil), decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" -). --spec optional(decoder(CBP)) -> decoder(gleam@option:option(CBP)). -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", 484). -?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", 608). --spec run_dynamic_function( - gleam@dynamic:dynamic_(), - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, BZQ} | {error, BZQ}) -) -> {BZQ, 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", 657). --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", 679). --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", 698). --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", 732). --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", 904). -?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.from(1000), decoder)\n" - " assert result == Error([DecodeError(\"MyThing\", \"Int\", [])])\n" - " ```\n" -). --spec collapse_errors(decoder(CCC), binary()) -> decoder(CCC). -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", 982). -?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(CCU, binary()) -> decoder(CCU). -failure(Zero, Expected) -> - {decoder, fun(D) -> {Zero, decode_error(Expected, D)} end}. - --file("src/gleam/dynamic/decode.gleam", 1011). -?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, CCW} | {error, CCW}) -) -> decoder(CCW). -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", 635). --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", 630). --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", 803). --spec fold_dict( - {gleam@dict:dict(CBB, CBC), list(decode_error())}, - gleam@dynamic:dynamic_(), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_()) -> {CBB, list(decode_error())}), - fun((gleam@dynamic:dynamic_()) -> {CBC, list(decode_error())}) -) -> {gleam@dict:dict(CBB, CBC), 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", 783). -?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 = dict.from_list([\n" - " #(\"one\", 1),\n" - " #(\"two\", 2),\n" - " ])\n" - "\n" - " let result =\n" - " decode.run(dynamic.from(values), decode.dict(decode.string, decode.int))\n" - " assert result == Ok(values)\n" - " ```\n" -). --spec dict(decoder(CAU), decoder(CAW)) -> decoder(gleam@dict:dict(CAU, CAW)). -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", 751). -?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" - " decode.run(dynamic.from([1, 2, 3]), decode.list(of: decode.int))\n" - " assert result == Ok([1, 2, 3])\n" - " ```\n" -). --spec list(decoder(CAI)) -> decoder(list(CAI)). -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", 438). --spec push_path({BYR, list(decode_error())}, list(any())) -> {BYR, - 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) -> _record = Error, - {decode_error, - erlang:element(2, _record), - erlang:element(3, _record), - lists:append(Path@1, erlang:element(4, Error))} end - ), - {erlang:element(1, Layer), Errors}. - --file("src/gleam/dynamic/decode.gleam", 403). --spec index( - list(BYF), - list(BYF), - fun((gleam@dynamic:dynamic_()) -> {BYI, list(decode_error())}), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_(), list(BYF)) -> {BYI, list(decode_error())}) -) -> {BYI, list(decode_error())}. -index(Path, Position, Inner, Data, Handle_miss) -> - case Path of - [] -> - _pipe = Inner(Data), - push_path(_pipe, 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@1 = {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]}, - push_path(_pipe@1, 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.from(dict.from_list([\n" - " #(\"data\", dict.from_list([\n" - " #(\"email\", \"lucy@example.com\"),\n" - " #(\"name\", \"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(BXQ), fun((BXQ) -> decoder(BXS))) -> decoder(BXS). -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.from(dict.from_list([\n" - " #(\"one\", dict.from_list([\n" - " #(\"two\", 1000),\n" - " ])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(1000)\n" - " ```\n" - "\n" - " ```gleam\n" - " dynamic.from(Nil)\n" - " |> decode.run(decode.optional(decode.int))\n" - " // -> Ok(option.None)\n" - " ```\n" -). --spec at(list(any()), decoder(BYC)) -> decoder(BYC). -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", 523). -?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.from(dict.from_list([\n" - " #(\"email\", \"lucy@example.com\"),\n" - " #(\"name\", \"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(BZA), fun((BZA) -> decoder(BZC))) -> decoder(BZC). -field(Field_name, Field_decoder, Next) -> - subfield([Field_name], Field_decoder, Next). - --file("src/gleam/dynamic/decode.gleam", 556). -?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.from(dict.from_list([\n" - " #(\"name\", \"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(), BZG, decoder(BZG), fun((BZG) -> decoder(BZI))) -> decoder(BZI). -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", 598). -?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.from(dict.from_list([\n" - " #(\"one\", dict.from_list([])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(100)\n" - " ```\n" -). --spec optionally_at(list(any()), BZN, decoder(BZN)) -> decoder(BZN). -optionally_at(Path, Default, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(_, _) -> {Default, []} end - ) - end}. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache deleted file mode 100644 index 47a58f4..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta deleted file mode 100644 index 604414b..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl deleted file mode 100644 index e893b8e..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl +++ /dev/null @@ -1,744 +0,0 @@ --module(gleam@float). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache deleted file mode 100644 index fca1325..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta deleted file mode 100644 index 1f87f09..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl deleted file mode 100644 index c1e8b5a..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl +++ /dev/null @@ -1,30 +0,0 @@ --module(gleam@function). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(CNY) -> CNY. -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(CNZ, fun((CNZ) -> any())) -> CNZ. -tap(Arg, Effect) -> - Effect(Arg), - Arg. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache deleted file mode 100644 index 19bbdae..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta deleted file mode 100644 index 09b5980..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl deleted file mode 100644 index b9f71b2..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl +++ /dev/null @@ -1,984 +0,0 @@ --module(gleam@int). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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", 107). -?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", 139). -?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", 161). -?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", 194). -?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", 214). -?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", 227). -?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", 240). -?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", 253). -?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", 278). -?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 = erlang:float(Base), - gleam@float:power(_pipe, Exponent). - --file("src/gleam/int.gleam", 86). -?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 = erlang:float(X), - gleam@float:square_root(_pipe). - --file("src/gleam/int.gleam", 314). -?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", 334). -?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", 350). -?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", 289). -?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", 371). -?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", 389). -?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", 402). -?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", 419). --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", 415). -?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", 439). --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", 435). -?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", 454). --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", 447). --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", 469). --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", 462). --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", 498). -?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", 531). -?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", 583). -?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", 625). -?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", 669). -?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", 703). -?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", 731). -?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", 764). -?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", 776). -?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", 786). -?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", 796). -?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", 806). -?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", 816). -?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", 826). -?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/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache deleted file mode 100644 index 13e0525..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta deleted file mode 100644 index a67a4cf..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl deleted file mode 100644 index a21232e..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl +++ /dev/null @@ -1,80 +0,0 @@ --module(gleam@io). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache deleted file mode 100644 index d7db915..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta deleted file mode 100644 index cbac75e..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl deleted file mode 100644 index f266a06..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl +++ /dev/null @@ -1,2860 +0,0 @@ --module(gleam@list). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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, permutations/1, 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]). --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(YG) :: {continue, YG} | {stop, YG}. - --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(YN), fun((YN) -> 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(YL), fun((YL) -> boolean())) -> integer(). -count(List, Predicate) -> - count_loop(List, Predicate, 0). - --file("src/gleam/list.gleam", 139). -?DOC( - " Reverses a list and prepends it to another list.\n" - " This function runs in linear time, proportional to the length of the list\n" - " to prepend.\n" -). --spec reverse_and_prepend(list(YS), list(YS)) -> list(YS). -reverse_and_prepend(Prefix, Suffix) -> - case Prefix of - [] -> - Suffix; - - [First | Rest] -> - reverse_and_prepend(Rest, [First | Suffix]) - end. - --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(YP)) -> list(YP). -reverse(List) -> - lists:reverse(List). - --file("src/gleam/list.gleam", 167). -?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", 203). -?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(YY), YY) -> boolean(). -contains(List, Elem) -> - case List of - [] -> - false; - - [First | _] when First =:= Elem -> - true; - - [_ | Rest] -> - contains(Rest, Elem) - end. - --file("src/gleam/list.gleam", 230). -?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(AAA)) -> {ok, AAA} | {error, nil}. -first(List) -> - case List of - [] -> - {error, nil}; - - [First | _] -> - {ok, First} - end. - --file("src/gleam/list.gleam", 259). -?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(AAE)) -> {ok, list(AAE)} | {error, nil}. -rest(List) -> - case List of - [] -> - {error, nil}; - - [_ | Rest] -> - {ok, Rest} - end. - --file("src/gleam/list.gleam", 301). --spec group_loop(list(AAP), fun((AAP) -> AAR), gleam@dict:dict(AAR, list(AAP))) -> gleam@dict:dict(AAR, list(AAP)). -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", 297). -?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(AAJ), fun((AAJ) -> AAL)) -> gleam@dict:dict(AAL, list(AAJ)). -group(List, Key) -> - group_loop(List, Key, maps:new()). - --file("src/gleam/list.gleam", 338). --spec filter_loop(list(ABB), fun((ABB) -> boolean()), list(ABB)) -> list(ABB). -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", 334). -?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(AAY), fun((AAY) -> boolean())) -> list(AAY). -filter(List, Predicate) -> - filter_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 370). --spec filter_map_loop( - list(ABM), - fun((ABM) -> {ok, ABO} | {error, any()}), - list(ABO) -) -> list(ABO). -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", 366). -?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(ABF), fun((ABF) -> {ok, ABH} | {error, any()})) -> list(ABH). -filter_map(List, Fun) -> - filter_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 401). --spec map_loop(list(ABY), fun((ABY) -> ACA), list(ACA)) -> list(ACA). -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", 397). -?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(ABU), fun((ABU) -> ABW)) -> list(ABW). -map(List, Fun) -> - map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 428). --spec map2_loop(list(ACJ), list(ACL), fun((ACJ, ACL) -> ACN), list(ACN)) -> list(ACN). -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", 424). -?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(ACD), list(ACF), fun((ACD, ACF) -> ACH)) -> list(ACH). -map2(List1, List2, Fun) -> - map2_loop(List1, List2, Fun, []). - --file("src/gleam/list.gleam", 461). --spec map_fold_loop(list(ACV), fun((ACX, ACV) -> {ACX, ACY}), ACX, list(ACY)) -> {ACX, - list(ACY)}. -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", 453). -?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(ACQ), ACS, fun((ACS, ACQ) -> {ACS, ACT})) -> {ACS, - list(ACT)}. -map_fold(List, Initial, Fun) -> - map_fold_loop(List, Fun, Initial, []). - --file("src/gleam/list.gleam", 493). --spec index_map_loop( - list(ADF), - fun((ADF, integer()) -> ADH), - integer(), - list(ADH) -) -> list(ADH). -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", 489). -?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(ADB), fun((ADB, integer()) -> ADD)) -> list(ADD). -index_map(List, Fun) -> - index_map_loop(List, Fun, 0, []). - --file("src/gleam/list.gleam", 547). --spec try_map_loop(list(ADT), fun((ADT) -> {ok, ADV} | {error, ADW}), list(ADV)) -> {ok, - list(ADV)} | - {error, ADW}. -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", 540). -?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(ADK), fun((ADK) -> {ok, ADM} | {error, ADN})) -> {ok, - list(ADM)} | - {error, ADN}. -try_map(List, Fun) -> - try_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 582). -?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(AED), integer()) -> list(AED). -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", 617). --spec take_loop(list(AEJ), integer(), list(AEJ)) -> list(AEJ). -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", 613). -?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(AEG), integer()) -> list(AEG). -take(List, N) -> - take_loop(List, N, []). - --file("src/gleam/list.gleam", 637). -?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", 657). -?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(AEP) -> list(AEP). -wrap(Item) -> - [Item]. - --file("src/gleam/list.gleam", 678). --spec append_loop(list(AEV), list(AEV)) -> list(AEV). -append_loop(First, Second) -> - case First of - [] -> - Second; - - [First@1 | Rest] -> - append_loop(Rest, [First@1 | Second]) - end. - --file("src/gleam/list.gleam", 674). -?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(AER), list(AER)) -> list(AER). -append(First, Second) -> - lists:append(First, Second). - --file("src/gleam/list.gleam", 698). -?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(AEZ), AEZ) -> list(AEZ). -prepend(List, Item) -> - [Item | List]. - --file("src/gleam/list.gleam", 719). --spec flatten_loop(list(list(AFG)), list(AFG)) -> list(AFG). -flatten_loop(Lists, Acc) -> - case Lists of - [] -> - lists:reverse(Acc); - - [List | Further_lists] -> - flatten_loop(Further_lists, reverse_and_prepend(List, Acc)) - end. - --file("src/gleam/list.gleam", 715). -?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(AFC))) -> list(AFC). -flatten(Lists) -> - lists:append(Lists). - --file("src/gleam/list.gleam", 736). -?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(AFL), fun((AFL) -> list(AFN))) -> list(AFN). -flat_map(List, Fun) -> - lists:append(map(List, Fun)). - --file("src/gleam/list.gleam", 748). -?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(AFQ), AFS, fun((AFS, AFQ) -> AFS)) -> AFS. -fold(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - fold(Rest, Fun(Initial, First), Fun) - end. - --file("src/gleam/list.gleam", 770). -?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(AFT), AFV, fun((AFV, AFT) -> AFV)) -> AFV. -fold_right(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - Fun(fold_right(Rest, Initial, Fun), First) - end. - --file("src/gleam/list.gleam", 798). --spec index_fold_loop( - list(AFZ), - AGB, - fun((AGB, AFZ, integer()) -> AGB), - integer() -) -> AGB. -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", 790). -?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" - " ```\n" -). --spec index_fold(list(AFW), AFY, fun((AFY, AFW, integer()) -> AFY)) -> AFY. -index_fold(List, Initial, Fun) -> - index_fold_loop(List, Initial, Fun, 0). - --file("src/gleam/list.gleam", 830). -?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(AGC), AGE, fun((AGE, AGC) -> {ok, AGE} | {error, AGF})) -> {ok, - AGE} | - {error, AGF}. -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", 869). -?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(AGK), AGM, fun((AGM, AGK) -> continue_or_stop(AGM))) -> AGM. -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", 906). -?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(AGO), fun((AGO) -> boolean())) -> {ok, AGO} | {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", 942). -?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(AGS), fun((AGS) -> {ok, AGU} | {error, any()})) -> {ok, AGU} | - {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", 977). -?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(AHA), fun((AHA) -> 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", 1014). -?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(AHC), fun((AHC) -> 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", 1056). --spec zip_loop(list(AHJ), list(AHL), list({AHJ, AHL})) -> list({AHJ, AHL}). -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", 1052). -?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(AHE), list(AHG)) -> list({AHE, AHG}). -zip(List, Other) -> - zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1097). --spec strict_zip_loop(list(AHW), list(AHY), list({AHW, AHY})) -> {ok, - list({AHW, AHY})} | - {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", 1090). -?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(AHP), list(AHR)) -> {ok, list({AHP, AHR})} | {error, nil}. -strict_zip(List, Other) -> - strict_zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1128). --spec unzip_loop(list({AIJ, AIK}), list(AIJ), list(AIK)) -> {list(AIJ), - list(AIK)}. -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", 1124). -?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({AIE, AIF})) -> {list(AIE), list(AIF)}. -unzip(Input) -> - unzip_loop(Input, [], []). - --file("src/gleam/list.gleam", 1163). --spec intersperse_loop(list(AIT), AIT, list(AIT)) -> list(AIT). -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", 1156). -?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(AIQ), AIQ) -> list(AIQ). -intersperse(List, Elem) -> - case List of - [] -> - List; - - [_] -> - List; - - [First | Rest] -> - intersperse_loop(Rest, Elem, [First]) - end. - --file("src/gleam/list.gleam", 1186). --spec unique_loop(list(AJA), gleam@dict:dict(AJA, nil), list(AJA)) -> list(AJA). -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", 1182). -?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(AIX)) -> list(AIX). -unique(List) -> - unique_loop(List, maps:new(), []). - --file("src/gleam/list.gleam", 1272). -?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(AJJ), - fun((AJJ, AJJ) -> gleam@order:order()), - list(AJJ), - sorting(), - AJJ, - list(list(AJJ)) -) -> list(list(AJJ)). -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", 1420). -?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(AKG), - list(AKG), - fun((AKG, AKG) -> gleam@order:order()), - list(AKG) -) -> list(AKG). -merge_ascendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - reverse_and_prepend(List, Acc); - - {List, []} -> - reverse_and_prepend(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", 1373). -?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(AJU)), - fun((AJU, AJU) -> gleam@order:order()), - list(list(AJU)) -) -> list(list(AJU)). -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", 1447). -?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(AKL), - list(AKL), - fun((AKL, AKL) -> gleam@order:order()), - list(AKL) -) -> list(AKL). -merge_descendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - reverse_and_prepend(List, Acc); - - {List, []} -> - reverse_and_prepend(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", 1395). -?DOC(" This is the same as merge_ascending_pairs but flipped for descending lists.\n"). --spec merge_descending_pairs( - list(list(AKA)), - fun((AKA, AKA) -> gleam@order:order()), - list(list(AKA)) -) -> list(list(AKA)). -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", 1339). -?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(AJQ)), - sorting(), - fun((AJQ, AJQ) -> gleam@order:order()) -) -> list(AJQ). -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", 1210). -?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(AJG), fun((AJG, AJG) -> gleam@order:order())) -> list(AJG). -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", 1487). --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", 1483). -?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", 1513). --spec repeat_loop(AKV, integer(), list(AKV)) -> list(AKV). -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", 1509). -?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(AKT, integer()) -> list(AKT). -repeat(A, Times) -> - repeat_loop(A, Times, []). - --file("src/gleam/list.gleam", 1546). --spec split_loop(list(ALC), integer(), list(ALC)) -> {list(ALC), list(ALC)}. -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", 1542). -?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(AKY), integer()) -> {list(AKY), list(AKY)}. -split(List, Index) -> - split_loop(List, Index, []). - --file("src/gleam/list.gleam", 1582). --spec split_while_loop(list(ALL), fun((ALL) -> boolean()), list(ALL)) -> {list(ALL), - list(ALL)}. -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", 1575). -?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(ALH), fun((ALH) -> boolean())) -> {list(ALH), list(ALH)}. -split_while(List, Predicate) -> - split_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1622). -?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({ALQ, ALR}), ALQ) -> {ok, ALR} | {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", 1653). -?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({ALV, ALW}), ALV) -> list(ALW). -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", 1693). --spec key_pop_loop(list({AMF, AMG}), AMF, list({AMF, AMG})) -> {ok, - {AMG, list({AMF, AMG})}} | - {error, nil}. -key_pop_loop(List, Key, Checked) -> - case List of - [] -> - {error, nil}; - - [{K, V} | Rest] when K =:= Key -> - {ok, {V, reverse_and_prepend(Checked, Rest)}}; - - [First | Rest@1] -> - key_pop_loop(Rest@1, Key, [First | Checked]) - end. - --file("src/gleam/list.gleam", 1689). -?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({ALZ, AMA}), ALZ) -> {ok, {AMA, list({ALZ, AMA})}} | - {error, nil}. -key_pop(List, Key) -> - key_pop_loop(List, Key, []). - --file("src/gleam/list.gleam", 1727). --spec key_set_loop(list({AMQ, AMR}), AMQ, AMR, list({AMQ, AMR})) -> list({AMQ, - AMR}). -key_set_loop(List, Key, Value, Inspected) -> - case List of - [{K, _} | Rest] when K =:= Key -> - reverse_and_prepend(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", 1723). -?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({AMM, AMN}), AMM, AMN) -> list({AMM, AMN}). -key_set(List, Key, Value) -> - key_set_loop(List, Key, Value, []). - --file("src/gleam/list.gleam", 1755). -?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(AMV), fun((AMV) -> any())) -> nil. -each(List, F) -> - case List of - [] -> - nil; - - [First | Rest] -> - F(First), - each(Rest, F) - end. - --file("src/gleam/list.gleam", 1781). -?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(AMY), fun((AMY) -> {ok, any()} | {error, ANB})) -> {ok, nil} | - {error, ANB}. -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", 1814). --spec partition_loop(list(BGB), fun((BGB) -> boolean()), list(BGB), list(BGB)) -> {list(BGB), - list(BGB)}. -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", 1807). -?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(ANG), fun((ANG) -> boolean())) -> {list(ANG), list(ANG)}. -partition(List, Categorise) -> - partition_loop(List, Categorise, [], []). - --file("src/gleam/list.gleam", 1834). -?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(ANP)) -> list(list(ANP)). -permutations(List) -> - case List of - [] -> - [[]]; - - [_ | _] -> - _pipe@3 = index_map( - List, - fun(I, I_idx) -> - _pipe = index_fold( - List, - [], - fun(Acc, J, J_idx) -> case I_idx =:= J_idx of - true -> - Acc; - - false -> - [J | Acc] - end end - ), - _pipe@1 = lists:reverse(_pipe), - _pipe@2 = permutations(_pipe@1), - map(_pipe@2, fun(Permutation) -> [I | Permutation] end) - end - ), - lists:append(_pipe@3) - end. - --file("src/gleam/list.gleam", 1874). --spec window_loop(list(list(ANX)), list(ANX), integer()) -> list(list(ANX)). -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", 1867). -?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(ANT), integer()) -> list(list(ANT)). -window(List, N) -> - case N =< 0 of - true -> - []; - - false -> - window_loop([], List, N) - end. - --file("src/gleam/list.gleam", 1897). -?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(AOD)) -> list({AOD, AOD}). -window_by_2(List) -> - zip(List, drop(List, 1)). - --file("src/gleam/list.gleam", 1910). -?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(AOG), fun((AOG) -> boolean())) -> list(AOG). -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", 1940). --spec take_while_loop(list(AOM), fun((AOM) -> boolean()), list(AOM)) -> list(AOM). -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", 1933). -?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(AOJ), fun((AOJ) -> boolean())) -> list(AOJ). -take_while(List, Predicate) -> - take_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1972). --spec chunk_loop(list(AOV), fun((AOV) -> AOX), AOX, list(AOV), list(list(AOV))) -> list(list(AOV)). -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", 1965). -?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(AOQ), fun((AOQ) -> any())) -> list(list(AOQ)). -chunk(List, F) -> - case List of - [] -> - []; - - [First | Rest] -> - chunk_loop(Rest, F, F(First), [First], []) - end. - --file("src/gleam/list.gleam", 2017). --spec sized_chunk_loop( - list(APH), - integer(), - integer(), - list(APH), - list(list(APH)) -) -> list(list(APH)). -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", 2013). -?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(APD), integer()) -> list(list(APD)). -sized_chunk(List, Count) -> - sized_chunk_loop(List, Count, Count, [], []). - --file("src/gleam/list.gleam", 2061). -?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(APO), fun((APO, APO) -> APO)) -> {ok, APO} | {error, nil}. -reduce(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, fold(Rest, First, Fun)} - end. - --file("src/gleam/list.gleam", 2085). --spec scan_loop(list(APW), APY, list(APY), fun((APY, APW) -> APY)) -> list(APY). -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", 2077). -?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(APS), APU, fun((APU, APS) -> APU)) -> list(APU). -scan(List, Initial, Fun) -> - scan_loop(List, Initial, [], Fun). - --file("src/gleam/list.gleam", 2118). -?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(AQB)) -> {ok, AQB} | {error, nil}. -last(List) -> - case List of - [] -> - {error, nil}; - - [Last] -> - {ok, Last}; - - [_ | Rest] -> - last(Rest) - end. - --file("src/gleam/list.gleam", 2140). -?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(AQF), integer()) -> list(list(AQF)). -combinations(Items, N) -> - case {N, Items} of - {0, _} -> - [[]]; - - {_, []} -> - []; - - {_, [First | Rest]} -> - _pipe = combinations(Rest, N - 1), - _pipe@1 = map(_pipe, fun(Combination) -> [First | Combination] end), - _pipe@2 = lists:reverse(_pipe@1), - fold(_pipe@2, combinations(Rest, N), fun(Acc, C) -> [C | Acc] end) - end. - --file("src/gleam/list.gleam", 2165). --spec combination_pairs_loop(list(AQM), list({AQM, AQM})) -> list({AQM, AQM}). -combination_pairs_loop(Items, Acc) -> - case Items of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - First_combinations = map(Rest, fun(Other) -> {First, Other} end), - Acc@1 = reverse_and_prepend(First_combinations, Acc), - combination_pairs_loop(Rest, Acc@1) - end. - --file("src/gleam/list.gleam", 2161). -?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(AQJ)) -> list({AQJ, AQJ}). -combination_pairs(Items) -> - combination_pairs_loop(Items, []). - --file("src/gleam/list.gleam", 2220). --spec take_firsts(list(list(ARG)), list(ARG), list(list(ARG))) -> {list(ARG), - list(list(ARG))}. -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", 2207). --spec transpose_loop(list(list(AQZ)), list(list(AQZ))) -> list(list(AQZ)). -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", 2203). -?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(AQU))) -> list(list(AQU)). -transpose(List_of_lists) -> - transpose_loop(List_of_lists, []). - --file("src/gleam/list.gleam", 2185). -?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(AQQ))) -> list(AQQ). -interleave(List) -> - _pipe = transpose(List), - lists:append(_pipe). - --file("src/gleam/list.gleam", 2253). --spec shuffle_pair_unwrap_loop(list({float(), ARS}), list(ARS)) -> list(ARS). -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", 2261). --spec do_shuffle_by_pair_indexes(list({float(), ARW})) -> list({float(), ARW}). -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", 2246). -?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(ARP)) -> list(ARP). -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", 2293). --spec max_loop(list(ASG), fun((ASG, ASG) -> gleam@order:order()), ASG) -> ASG. -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", 2283). -?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(ARZ), fun((ARZ, ARZ) -> gleam@order:order())) -> {ok, ARZ} | - {error, nil}. -max(List, Compare) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, max_loop(Rest, Compare, First)} - end. - --file("src/gleam/list.gleam", 2374). --spec build_reservoir_loop( - list(ASV), - integer(), - gleam@dict:dict(integer(), ASV) -) -> {gleam@dict:dict(integer(), ASV), list(ASV)}. -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", 2370). -?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(ASQ), integer()) -> {gleam@dict:dict(integer(), ASQ), - list(ASQ)}. -build_reservoir(List, N) -> - build_reservoir_loop(List, N, maps:new()). - --file("src/gleam/list.gleam", 2358). --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 => 2359, - value => _assert_fail, - start => 55490, - 'end' => 55561, - pattern_start => 55501, - pattern_end => 55511}) - end, - Random@1. - --file("src/gleam/list.gleam", 2335). --spec sample_loop( - list(ASK), - gleam@dict:dict(integer(), ASK), - integer(), - float() -) -> gleam@dict:dict(integer(), ASK). -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 => 2342, - value => _assert_fail, - start => 55051, - 'end' => 55097, - pattern_start => 55062, - pattern_end => 55069}) - 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", 2317). -?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(ASH), integer()) -> list(ASH). -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. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache deleted file mode 100644 index 0bb7bd5..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta deleted file mode 100644 index 8656c26..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl deleted file mode 100644 index cbacd70..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl +++ /dev/null @@ -1,413 +0,0 @@ --module(gleam@option). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(GA) :: {some, GA} | none. - --file("src/gleam/option.gleam", 59). --spec reverse_and_prepend(list(GP), list(GP)) -> list(GP). -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(GG)), list(GG)) -> option(list(GG)). -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(GB))) -> option(list(GB)). -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(GX), HA) -> {ok, GX} | {error, HA}. -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, HD} | {error, any()}) -> option(HD). -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(HI), HI) -> HI. -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(HK), fun(() -> HK)) -> HK. -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(HM), fun((HM) -> HO)) -> option(HO). -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(HQ))) -> option(HQ). -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(HU), fun((HU) -> option(HW))) -> option(HW). -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(HZ), option(HZ)) -> option(HZ). -'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(ID), fun(() -> option(ID))) -> option(ID). -lazy_or(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second() - end. - --file("src/gleam/option.gleam", 352). --spec values_loop(list(option(IL)), list(IL)) -> list(IL). -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(IH))) -> list(IH). -values(Options) -> - values_loop(Options, []). diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache deleted file mode 100644 index 76ec374..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta deleted file mode 100644 index 4404517..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl deleted file mode 100644 index 5ad2cb2..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl +++ /dev/null @@ -1,200 +0,0 @@ --module(gleam@order). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache deleted file mode 100644 index 4d26985..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta deleted file mode 100644 index daa77fc..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl deleted file mode 100644 index 228140e..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl +++ /dev/null @@ -1,110 +0,0 @@ --module(gleam@pair). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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({COH, any()}) -> COH. -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(), COK}) -> COK. -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({COL, COM}) -> {COM, COL}. -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({CON, COO}, fun((CON) -> COP)) -> {COP, COO}. -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({COQ, COR}, fun((COR) -> COS)) -> {COQ, COS}. -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(COT, COU) -> {COT, COU}. -new(First, Second) -> - {First, Second}. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache deleted file mode 100644 index dc5c1b9..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta deleted file mode 100644 index 8283209..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl deleted file mode 100644 index 3a0deb5..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl +++ /dev/null @@ -1,566 +0,0 @@ --module(gleam@result). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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, CPE} | {error, CPF}, fun((CPE) -> CPI)) -> {ok, CPI} | - {error, CPF}. -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, CPL} | {error, CPM}, fun((CPM) -> CPP)) -> {ok, CPL} | - {error, CPP}. -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, CPS} | {error, CPT}} | {error, CPT}) -> {ok, CPS} | - {error, CPT}. -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, CQA} | {error, CQB}, fun((CQA) -> {ok, CQE} | {error, CQB})) -> {ok, - CQE} | - {error, CQB}. -'try'(Result, Fun) -> - case Result of - {ok, X} -> - Fun(X); - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 169). --spec then({ok, CQJ} | {error, CQK}, fun((CQJ) -> {ok, CQN} | {error, CQK})) -> {ok, - CQN} | - {error, CQK}. -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, CQS} | {error, any()}, CQS) -> CQS. -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, CQW} | {error, any()}, fun(() -> CQW)) -> CQW. -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, CRB}, CRB) -> CRB. -unwrap_error(Result, Default) -> - case Result of - {ok, _} -> - Default; - - {error, E} -> - E - end. - --file("src/gleam/result.gleam", 257). -?DOC( - " Extracts the inner value from a result. Both the value and error must be of\n" - " the same type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap_both(Error(1))\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap_both(Ok(2))\n" - " // -> 2\n" - " ```\n" -). --spec unwrap_both({ok, CRE} | {error, CRE}) -> CRE. -unwrap_both(Result) -> - case Result of - {ok, A} -> - A; - - {error, A@1} -> - A@1 - end. - --file("src/gleam/result.gleam", 288). -?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, CRH} | {error, CRI}, {ok, CRH} | {error, CRI}) -> {ok, CRH} | - {error, CRI}. -'or'(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second - end. - --file("src/gleam/result.gleam", 321). -?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, CRP} | {error, CRQ}, fun(() -> {ok, CRP} | {error, CRQ})) -> {ok, - CRP} | - {error, CRQ}. -lazy_or(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second() - end. - --file("src/gleam/result.gleam", 347). -?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, CRX} | {error, CRY})) -> {ok, list(CRX)} | {error, CRY}. -all(Results) -> - gleam@list:try_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 367). --spec partition_loop(list({ok, CSM} | {error, CSN}), list(CSM), list(CSN)) -> {list(CSM), - list(CSN)}. -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", 363). -?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, CSF} | {error, CSG})) -> {list(CSF), list(CSG)}. -partition(Results) -> - partition_loop(Results, [], []). - --file("src/gleam/result.gleam", 389). -?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, CSV}, CSY) -> {ok, CSY} | {error, CSV}. -replace(Result, Value) -> - case Result of - {ok, _} -> - {ok, Value}; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 410). -?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, CTB} | {error, any()}, CTF) -> {ok, CTB} | {error, CTF}. -replace_error(Result, Error) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, _} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 426). -?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, CTI} | {error, any()})) -> list(CTI). -values(Results) -> - gleam@list:filter_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 459). -?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, CTO} | {error, CTP}, - fun((CTP) -> {ok, CTO} | {error, CTS}) -) -> {ok, CTO} | {error, CTS}. -try_recover(Result, Fun) -> - case Result of - {ok, Value} -> - {ok, Value}; - - {error, Error} -> - Fun(Error) - end. diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache deleted file mode 100644 index 1832ba4..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta deleted file mode 100644 index e5bd75e..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl deleted file mode 100644 index 6a15c29..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl +++ /dev/null @@ -1,429 +0,0 @@ --module(gleam@set). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(CYN) :: {set, gleam@dict:dict(CYN, 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(CYY), CYY) -> 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(CZA), CZA) -> set(CZA). -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(CZD)) -> list(CZD). -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(CZJ), CZL, fun((CZL, CZJ) -> CZL)) -> CZL. -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(CZM), fun((CZM) -> boolean())) -> set(CZM). -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(CZT), list(CZT)) -> set(CZT). -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(CZX), list(CZX)) -> set(CZX). -take(Set, Desired) -> - {set, gleam@dict:take(erlang:element(2, Set), Desired)}. - --file("src/gleam/set.gleam", 287). --spec order(set(DAF), set(DAF)) -> {set(DAF), set(DAF)}. -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(DAK), set(DAK)) -> set(DAK). -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(DAO), set(DAO)) -> set(DAO). -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(DAS), set(DAS)) -> 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(DAV), set(DAV)) -> 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(DBC), fun((DBC) -> 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(CYV), CYV) -> set(CYV). -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(CZG)) -> set(CZG). -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(CZP), fun((CZP) -> CZR)) -> set(CZR). -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(DAB), set(DAB)) -> set(DAB). -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(DAY), set(DAY)) -> set(DAY). -symmetric_difference(First, Second) -> - difference(union(First, Second), intersection(First, Second)). diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache deleted file mode 100644 index e493e51..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta deleted file mode 100644 index bfebc83..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl deleted file mode 100644 index a441003..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl +++ /dev/null @@ -1,957 +0,0 @@ --module(gleam@string). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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, drop_start/2, 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]). --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.\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.\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", 190). -?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" - " ## 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", 223). -?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 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", 254). -?DOC( - " Drops *n* graphemes from the end of a `String`.\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", 282). -?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", 295). -?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", 308). -?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", 347). -?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", 378). -?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", 400). --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", 396). -?DOC( - " Creates a new `String` by joining many `String`s together.\n" - "\n" - " This function copies both `String`s and runs in linear time. If you find\n" - " yourself joining `String`s frequently consider using the [`string_tree`](../gleam/string_tree.html)\n" - " module as it can append `String`s much faster!\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", 422). --spec repeat_loop(binary(), integer(), binary()) -> binary(). -repeat_loop(String, Times, Acc) -> - case Times =< 0 of - true -> - Acc; - - false -> - repeat_loop(String, Times - 1, <>) - end. - --file("src/gleam/string.gleam", 418). -?DOC( - " Creates a new `String` by repeating a `String` a given number of times.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " repeat(\"ha\", times: 3)\n" - " // -> \"hahaha\"\n" - " ```\n" -). --spec repeat(binary(), integer()) -> binary(). -repeat(String, Times) -> - repeat_loop(String, Times, <<""/utf8>>). - --file("src/gleam/string.gleam", 447). --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", 440). -?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", 525). --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", 478). -?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", 511). -?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", 569). -?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", 583). -?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", 547). -?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", 610). -?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", 234). -?DOC( - " Drops *n* graphemes from the start of a `String`.\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 - false -> - String; - - true -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {_, String@1}} -> - drop_start(String@1, Num_graphemes - 1); - - {error, nil} -> - String - end - end. - --file("src/gleam/string.gleam", 626). --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", 621). -?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 = to_graphemes_loop(String, []), - lists:reverse(_pipe). - --file("src/gleam/string.gleam", 319). -?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", 673). --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", 668). --spec do_to_utf_codepoints(binary()) -> list(integer()). -do_to_utf_codepoints(String) -> - to_utf_codepoints_loop(<>, []). - --file("src/gleam/string.gleam", 663). -?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", 713). -?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", 719). -?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", 740). -?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", 757). -?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", 780). -?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", 803). -?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" - " ## 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", 821). -?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", 830). -?DOC(" Returns a `String` representation of a term in Gleam syntax.\n"). --spec inspect(any()) -> binary(). -inspect(Term) -> - _pipe = gleam_stdlib:inspect(Term), - unicode:characters_to_binary(_pipe). - --file("src/gleam/string.gleam", 853). -?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). diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache deleted file mode 100644 index ed930dd..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta deleted file mode 100644 index abfcf6a..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_tree.erl deleted file mode 100644 index c36c1b2..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/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]). --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/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache deleted file mode 100644 index 638f372..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta deleted file mode 100644 index d4e5f34..0000000 Binary files a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl deleted file mode 100644 index f64a9db..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl +++ /dev/null @@ -1,1117 +0,0 @@ --module(gleam@uri). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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", 503). --spec parse_fragment(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_fragment(Rest, Pieces) -> - {ok, - begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - erlang:element(4, _record), - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - {some, Rest}} - end}. - --file("src/gleam/uri.gleam", 475). --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 = begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - erlang:element(4, _record), - erlang:element(5, _record), - erlang:element(6, _record), - {some, Query}, - erlang:element(8, _record)} - end, - parse_fragment(Rest@1, Pieces@1); - - <<""/utf8>> -> - {ok, - begin - _record@1 = Pieces, - {uri, - erlang:element(2, _record@1), - erlang:element(3, _record@1), - erlang:element(4, _record@1), - erlang:element(5, _record@1), - erlang:element(6, _record@1), - {some, Original}, - erlang:element(8, _record@1)} - end}; - - _ -> - {_, 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", 468). --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", 434). --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 = begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - erlang:element(4, _record), - erlang:element(5, _record), - Path, - erlang:element(7, _record), - erlang:element(8, _record)} - end, - parse_query_with_question_mark(Rest, Pieces@1); - - <<"#"/utf8, Rest@1/binary>> -> - Path@1 = binary:part(Original, 0, Size), - Pieces@2 = begin - _record@1 = Pieces, - {uri, - erlang:element(2, _record@1), - erlang:element(3, _record@1), - erlang:element(4, _record@1), - erlang:element(5, _record@1), - Path@1, - erlang:element(7, _record@1), - erlang:element(8, _record@1)} - end, - parse_fragment(Rest@1, Pieces@2); - - <<""/utf8>> -> - {ok, - begin - _record@2 = Pieces, - {uri, - erlang:element(2, _record@2), - erlang:element(3, _record@2), - erlang:element(4, _record@2), - erlang:element(5, _record@2), - Original, - erlang:element(7, _record@2), - erlang:element(8, _record@2)} - end}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_path_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 430). --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", 385). --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 = begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - erlang:element(4, _record), - {some, Port}, - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end, - parse_query_with_question_mark(Rest@10, Pieces@1); - - <<"#"/utf8, Rest@11/binary>> -> - Pieces@2 = begin - _record@1 = Pieces, - {uri, - erlang:element(2, _record@1), - erlang:element(3, _record@1), - erlang:element(4, _record@1), - {some, Port}, - erlang:element(6, _record@1), - erlang:element(7, _record@1), - erlang:element(8, _record@1)} - end, - parse_fragment(Rest@11, Pieces@2); - - <<"/"/utf8, _/binary>> -> - Pieces@3 = begin - _record@2 = Pieces, - {uri, - erlang:element(2, _record@2), - erlang:element(3, _record@2), - erlang:element(4, _record@2), - {some, Port}, - erlang:element(6, _record@2), - erlang:element(7, _record@2), - erlang:element(8, _record@2)} - end, - parse_path(Uri_string, Pieces@3); - - <<""/utf8>> -> - {ok, - begin - _record@3 = Pieces, - {uri, - erlang:element(2, _record@3), - erlang:element(3, _record@3), - erlang:element(4, _record@3), - {some, Port}, - erlang:element(6, _record@3), - erlang:element(7, _record@3), - erlang:element(8, _record@3)} - end}; - - _ -> - {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, _/binary>> -> - {error, nil}; - - <<"?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<"#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_path(Uri_string, Pieces); - - <<""/utf8>> -> - {ok, Pieces}; - - _ -> - {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, - begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - {some, Original}, - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end}; - - <<":"/utf8, _/binary>> -> - Host = binary:part(Original, 0, Size), - Pieces@1 = begin - _record@1 = Pieces, - {uri, - erlang:element(2, _record@1), - erlang:element(3, _record@1), - {some, Host}, - erlang:element(5, _record@1), - erlang:element(6, _record@1), - erlang:element(7, _record@1), - erlang:element(8, _record@1)} - end, - parse_port(Uri_string, Pieces@1); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = begin - _record@2 = Pieces, - {uri, - erlang:element(2, _record@2), - erlang:element(3, _record@2), - {some, Host@1}, - erlang:element(5, _record@2), - erlang:element(6, _record@2), - erlang:element(7, _record@2), - erlang:element(8, _record@2)} - end, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = begin - _record@3 = Pieces, - {uri, - erlang:element(2, _record@3), - erlang:element(3, _record@3), - {some, Host@2}, - erlang:element(5, _record@3), - erlang:element(6, _record@3), - erlang:element(7, _record@3), - erlang:element(8, _record@3)} - end, - parse_query_with_question_mark(Rest, Pieces@3); - - <<"#"/utf8, Rest@1/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = begin - _record@4 = Pieces, - {uri, - erlang:element(2, _record@4), - erlang:element(3, _record@4), - {some, Host@3}, - erlang:element(5, _record@4), - erlang:element(6, _record@4), - erlang:element(7, _record@4), - erlang:element(8, _record@4)} - end, - 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, - begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - {some, Uri_string}, - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end}; - - <<"]"/utf8, Rest/binary>> when Size =:= 0 -> - parse_port(Rest, Pieces); - - <<"]"/utf8, Rest@1/binary>> -> - Host = binary:part(Original, 0, Size + 1), - Pieces@1 = begin - _record@1 = Pieces, - {uri, - erlang:element(2, _record@1), - erlang:element(3, _record@1), - {some, Host}, - erlang:element(5, _record@1), - erlang:element(6, _record@1), - erlang:element(7, _record@1), - erlang:element(8, _record@1)} - end, - 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 = begin - _record@2 = Pieces, - {uri, - erlang:element(2, _record@2), - erlang:element(3, _record@2), - {some, Host@1}, - erlang:element(5, _record@2), - erlang:element(6, _record@2), - erlang:element(7, _record@2), - erlang:element(8, _record@2)} - end, - 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 = begin - _record@3 = Pieces, - {uri, - erlang:element(2, _record@3), - erlang:element(3, _record@3), - {some, Host@2}, - erlang:element(5, _record@3), - erlang:element(6, _record@3), - erlang:element(7, _record@3), - erlang:element(8, _record@3)} - end, - 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 = begin - _record@4 = Pieces, - {uri, - erlang:element(2, _record@4), - erlang:element(3, _record@4), - {some, Host@3}, - erlang:element(5, _record@4), - erlang:element(6, _record@4), - erlang:element(7, _record@4), - erlang:element(8, _record@4)} - end, - 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 = begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - {some, <<""/utf8>>}, - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end, - parse_port(Uri_string, Pieces@1); - - <<""/utf8>> -> - {ok, - begin - _record@1 = Pieces, - {uri, - erlang:element(2, _record@1), - erlang:element(3, _record@1), - {some, <<""/utf8>>}, - erlang:element(5, _record@1), - erlang:element(6, _record@1), - erlang:element(7, _record@1), - erlang:element(8, _record@1)} - end}; - - _ -> - 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 = begin - _record = Pieces, - {uri, - erlang:element(2, _record), - {some, Userinfo}, - erlang:element(4, _record), - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end, - 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, - begin - _record = Pieces, - {uri, - erlang:element(2, _record), - erlang:element(3, _record), - {some, <<""/utf8>>}, - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end}; - - <<"//"/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 = begin - _record = Pieces, - {uri, - {some, string:lowercase(Scheme)}, - erlang:element(3, _record), - erlang:element(4, _record), - erlang:element(5, _record), - erlang:element(6, _record), - erlang:element(7, _record), - erlang:element(8, _record)} - end, - 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 = begin - _record@1 = Pieces, - {uri, - {some, string:lowercase(Scheme@1)}, - erlang:element(3, _record@1), - erlang:element(4, _record@1), - erlang:element(5, _record@1), - erlang:element(6, _record@1), - erlang:element(7, _record@1), - erlang:element(8, _record@1)} - end, - 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 = begin - _record@2 = Pieces, - {uri, - {some, string:lowercase(Scheme@2)}, - erlang:element(3, _record@2), - erlang:element(4, _record@2), - erlang:element(5, _record@2), - erlang:element(6, _record@2), - erlang:element(7, _record@2), - erlang:element(8, _record@2)} - end, - 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 = begin - _record@3 = Pieces, - {uri, - {some, string:lowercase(Scheme@3)}, - erlang:element(3, _record@3), - erlang:element(4, _record@3), - erlang:element(5, _record@3), - erlang:element(6, _record@3), - erlang:element(7, _record@3), - erlang:element(8, _record@3)} - end, - parse_authority_with_slashes(Rest@4, Pieces@4); - - <<""/utf8>> -> - {ok, - begin - _record@4 = Pieces, - {uri, - erlang:element(2, _record@4), - erlang:element(3, _record@4), - erlang:element(4, _record@4), - erlang:element(5, _record@4), - Original, - erlang:element(7, _record@4), - erlang:element(8, _record@4)} - end}; - - _ -> - {_, Rest@5} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_scheme_loop(Original, Rest@5, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 534). -?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", 570). -?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", 555). --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", 547). -?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", 583). -?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", 605). --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", 601). --spec remove_dot_segments(list(binary())) -> list(binary()). -remove_dot_segments(Input) -> - remove_dot_segments_loop(Input, []). - --file("src/gleam/uri.gleam", 597). -?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", 636). -?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", 680). -?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", 759). --spec drop_last(list(DGQ)) -> list(DGQ). -drop_last(Elements) -> - gleam@list:take(Elements, erlang:length(Elements) - 1). - --file("src/gleam/uri.gleam", 763). --spec join_segments(list(binary())) -> binary(). -join_segments(Segments) -> - gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). - --file("src/gleam/uri.gleam", 703). -?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 = gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ), - _pipe@1 = remove_dot_segments(_pipe), - join_segments(_pipe@1) - 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@2 = gleam@string:split( - erlang:element(6, Base), - <<"/"/utf8>> - ), - _pipe@3 = drop_last(_pipe@2), - lists:append( - _pipe@3, - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ) - ) - end, - Path@1 = begin - _pipe@4 = Path_segments, - _pipe@5 = remove_dot_segments(_pipe@4), - join_segments(_pipe@5) - 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/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl deleted file mode 100644 index 0bfcd2f..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl +++ /dev/null @@ -1,529 +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, - base_decode64/1, parse_query/1, bit_array_concat/1, - bit_array_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). -bit_array_base64_encode(Bin, Padding) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - base64:encode(PaddedBin, #{padding => Padding}). --else. -bit_array_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. - -base_decode64(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 -> - {ok, {uri, - maps_get_optional(Uri, scheme), - maps_get_optional(Uri, userinfo), - maps_get_optional(Uri, host), - maps_get_optional(Uri, 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_from_string(\"", 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/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs b/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs deleted file mode 100644 index 2edf3ad..0000000 --- a/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs +++ /dev/null @@ -1,1044 +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_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 encode64(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 decode64(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/erlang/gleam_stdlib/ebin/gleam@bit_array.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beam deleted file mode 100644 index 26eace9..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam deleted file mode 100644 index 2c04300..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_tree.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_tree.beam deleted file mode 100644 index 8292b2c..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_tree.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam deleted file mode 100644 index 8d85788..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam deleted file mode 100644 index b0e12b8..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic@decode.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic@decode.beam deleted file mode 100644 index 1c55702..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic@decode.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam deleted file mode 100644 index a1d441d..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam deleted file mode 100644 index e08475f..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam deleted file mode 100644 index a0eca8b..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam deleted file mode 100644 index 8ed3292..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam deleted file mode 100644 index 41002b7..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam deleted file mode 100644 index 70e8c8e..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam deleted file mode 100644 index 3c47227..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam deleted file mode 100644 index d5fb3e8..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam deleted file mode 100644 index 68bf12b..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam deleted file mode 100644 index 21fb676..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam deleted file mode 100644 index a3b2166..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@string_tree.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@string_tree.beam deleted file mode 100644 index 780409d..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@string_tree.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam deleted file mode 100644 index d1d64b4..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app b/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app deleted file mode 100644 index e3d9b17..0000000 --- a/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app +++ /dev/null @@ -1,7 +0,0 @@ -{application, gleam_stdlib, [ - {vsn, "0.62.0"}, - {applications, []}, - {description, "A standard library for the Gleam programming language"}, - {modules, []}, - {registered, []} -]}. diff --git a/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam b/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam deleted file mode 100644 index 37a4d91..0000000 Binary files a/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam and /dev/null differ diff --git a/build/dev/erlang/gleam_stdlib/include/gleam@dynamic@decode_DecodeError.hrl b/build/dev/erlang/gleam_stdlib/include/gleam@dynamic@decode_DecodeError.hrl deleted file mode 100644 index b1135f2..0000000 --- a/build/dev/erlang/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/dev/erlang/gleam_stdlib/include/gleam@dynamic@decode_Decoder.hrl b/build/dev/erlang/gleam_stdlib/include/gleam@dynamic@decode_Decoder.hrl deleted file mode 100644 index a2fcfc6..0000000 --- a/build/dev/erlang/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/dev/erlang/gleam_stdlib/include/gleam@set_Set.hrl b/build/dev/erlang/gleam_stdlib/include/gleam@set_Set.hrl deleted file mode 100644 index 51fb778..0000000 --- a/build/dev/erlang/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/dev/erlang/gleam_stdlib/include/gleam@uri_Uri.hrl b/build/dev/erlang/gleam_stdlib/include/gleam@uri_Uri.hrl deleted file mode 100644 index 50150f4..0000000 --- a/build/dev/erlang/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/dev/erlang/gleam_version b/build/dev/erlang/gleam_version deleted file mode 100644 index b0f61c5..0000000 --- a/build/dev/erlang/gleam_version +++ /dev/null @@ -1 +0,0 @@ -1.11.1 \ No newline at end of file diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.cache b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.cache deleted file mode 100644 index a5a9a0a..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.cache and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta deleted file mode 100644 index ebeff6e..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.erl deleted file mode 100644 index ba208f2..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit.erl +++ /dev/null @@ -1,87 +0,0 @@ --module(gleeunit). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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())}}. - --file("src/gleeunit.gleam", 37). --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}]}}], - 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/erlang/gleeunit/_gleam_artefacts/gleeunit/internal/gleeunit_gleam_panic_ffi.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit/internal/gleeunit_gleam_panic_ffi.erl deleted file mode 100644 index d78f5e5..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/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/erlang/gleeunit/_gleam_artefacts/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs deleted file mode 100644 index cef7646..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import { Ok, Error, Empty, NonEmpty } from "../../gleam.mjs"; -import { - GleamPanic, - Todo, - Panic, - LetAssert, - Assert, - BinaryOperator, - FunctionCall, - OtherExpression, - AssertedExpression, - Literal, - Expression, - Unevaluated, -} from "./gleam_panic.mjs"; - -export function from_dynamic(error) { - if (!(error instanceof globalThis.Error) || !error.gleam_error) { - return new Error(undefined); - } - - if (error.gleam_error === "todo") { - return wrap(error, new Todo()); - } - - if (error.gleam_error === "panic") { - return wrap(error, new Panic()); - } - - if (error.gleam_error === "let_assert") { - let kind = new LetAssert( - error.start, - error.end, - error.pattern_start, - error.pattern_end, - error.value, - ); - return wrap(error, kind); - } - - if (error.gleam_error === "assert") { - let kind = new Assert( - error.start, - error.end, - error.expression_start, - assert_kind(error), - ); - return wrap(error, kind); - } - - return new Error(undefined); -} - -function assert_kind(error) { - if (error.kind == "binary_operator") { - return new BinaryOperator( - error.operator, - expression(error.left), - expression(error.right), - ); - } - - if (error.kind == "function_call") { - let list = new Empty(); - let i = error.arguments.length; - while (i--) { - list = new NonEmpty(expression(error.arguments[i]), list); - } - return new FunctionCall(list); - } - - return new OtherExpression(expression(error.expression)); -} - -function expression(data) { - const expression = new AssertedExpression(data.start, data.end, undefined); - if (data.kind == "literal") { - expression.kind = new Literal(data.value); - } else if (data.kind == "expression") { - expression.kind = new Expression(data.value); - } else { - expression.kind = new Unevaluated(); - } - return expression; -} - -function wrap(e, kind) { - return new Ok( - new GleamPanic(e.message, e.file, e.module, e.function, e.line, kind), - ); -} diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache deleted file mode 100644 index 091a0c4..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta deleted file mode 100644 index 8e2ed2a..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.erl deleted file mode 100644 index f6dcb97..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/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]). --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/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache deleted file mode 100644 index 106c0fc..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta deleted file mode 100644 index d67e2c6..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.erl deleted file mode 100644 index 8b90c8c..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.erl +++ /dev/null @@ -1,331 +0,0 @@ --module(gleeunit@internal@reporting). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/gleeunit/internal/reporting.gleam"). --export([new_state/0, test_skipped/3, test_passed/1, finished/1, 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", 194). -?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", 198). -?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", 178). -?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", 202). -?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", 189). -?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>> - ), - _record = State, - {state, - erlang:element(2, _record), - erlang:element(3, _record), - erlang:element(4, State) + 1}. - --file("src/gleeunit/internal/reporting.gleam", 206). -?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", 64). -?DOC(false). --spec test_passed(state()) -> state(). -test_passed(State) -> - gleam_stdlib:print(green(<<"."/utf8>>)), - _record = State, - {state, - erlang:element(2, State) + 1, - erlang:element(3, _record), - erlang:element(4, _record)}. - --file("src/gleeunit/internal/reporting.gleam", 210). -?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, - " tests, 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, - " tests, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures"/utf8>>, - gleam_stdlib:println(red(Message@1)), - 0; - - {state, _, 0, _} -> - Message@2 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " tests, 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, - " tests, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures, "/utf8>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(red(Message@3)), - 1 - end. - --file("src/gleeunit/internal/reporting.gleam", 214). -?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", 87). -?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", 170). -?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", 166). -?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", 147). -?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", 100). -?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", 69). -?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>>), - _record = State, - {state, - erlang:element(2, _record), - erlang:element(3, State) + 1, - erlang:element(4, _record)}. diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache deleted file mode 100644 index 02ff42a..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta deleted file mode 100644 index dc1e870..0000000 Binary files a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta and /dev/null differ diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.erl deleted file mode 100644 index a9b26c0..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit@should.erl +++ /dev/null @@ -1,153 +0,0 @@ --module(gleeunit@should). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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(DRQ, DRQ) -> 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(DRR, DRR) -> 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, DRS} | {error, any()}) -> DRS. -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, DRX}) -> DRX. -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(DSA)) -> DSA. -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/erlang/gleeunit/_gleam_artefacts/gleeunit_ffi.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_ffi.erl deleted file mode 100644 index 29b9553..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_ffi.erl +++ /dev/null @@ -1,14 +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 eunit:test({timeout, 60, Tests}, Options) of - ok -> {ok, nil}; - error -> {error, nil}; - {error, Term} -> {error, Term} - end. diff --git a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_ffi.mjs b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_ffi.mjs deleted file mode 100644 index ea7e301..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_ffi.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import { readFileSync } from "node:fs"; -import { Ok, Error as GleamError } from "./gleam.mjs"; -import * as reporting from "./gleeunit/internal/reporting.mjs"; - -export function read_file(path) { - try { - return new Ok(readFileSync(path)); - } catch { - return new GleamError(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/erlang/gleeunit/_gleam_artefacts/gleeunit_progress.erl b/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_progress.erl deleted file mode 100644 index 2883008..0000000 --- a/build/dev/erlang/gleeunit/_gleam_artefacts/gleeunit_progress.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters - --module(gleeunit_progress). --behaviour(eunit_listener). --define(NOTEST, true). --include_lib("eunit/include/eunit.hrl"). - -%% 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/erlang/gleeunit/ebin/gleeunit.app b/build/dev/erlang/gleeunit/ebin/gleeunit.app deleted file mode 100644 index acc1a8c..0000000 --- a/build/dev/erlang/gleeunit/ebin/gleeunit.app +++ /dev/null @@ -1,7 +0,0 @@ -{application, gleeunit, [ - {vsn, "1.6.0"}, - {applications, [gleam_stdlib]}, - {description, "A simple test runner for Gleam, using EUnit on Erlang"}, - {modules, []}, - {registered, []} -]}. diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit.beam b/build/dev/erlang/gleeunit/ebin/gleeunit.beam deleted file mode 100644 index 40f2152..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit@internal@gleam_panic.beam b/build/dev/erlang/gleeunit/ebin/gleeunit@internal@gleam_panic.beam deleted file mode 100644 index 67d3741..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit@internal@gleam_panic.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit@internal@reporting.beam b/build/dev/erlang/gleeunit/ebin/gleeunit@internal@reporting.beam deleted file mode 100644 index 12b2e12..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit@internal@reporting.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit@should.beam b/build/dev/erlang/gleeunit/ebin/gleeunit@should.beam deleted file mode 100644 index 57db512..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit@should.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit_ffi.beam b/build/dev/erlang/gleeunit/ebin/gleeunit_ffi.beam deleted file mode 100644 index 0ccc792..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit_ffi.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit_gleam_panic_ffi.beam b/build/dev/erlang/gleeunit/ebin/gleeunit_gleam_panic_ffi.beam deleted file mode 100644 index 67a7eaf..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit_gleam_panic_ffi.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/ebin/gleeunit_progress.beam b/build/dev/erlang/gleeunit/ebin/gleeunit_progress.beam deleted file mode 100644 index 349d580..0000000 Binary files a/build/dev/erlang/gleeunit/ebin/gleeunit_progress.beam and /dev/null differ diff --git a/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Assert.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Assert.hrl deleted file mode 100644 index 9360941..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_AssertedExpression.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_AssertedExpression.hrl deleted file mode 100644 index 812663c..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_BinaryOperator.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_BinaryOperator.hrl deleted file mode 100644 index eee44c9..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl deleted file mode 100644 index e7ffaa0..0000000 --- a/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Expression.hrl +++ /dev/null @@ -1 +0,0 @@ --record(expression, {value :: gleam@dynamic:dynamic_()}). diff --git a/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_FunctionCall.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_FunctionCall.hrl deleted file mode 100644 index 9d55488..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_GleamPanic.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_GleamPanic.hrl deleted file mode 100644 index cf36764..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_LetAssert.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_LetAssert.hrl deleted file mode 100644 index 11f865e..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl deleted file mode 100644 index 2396489..0000000 --- a/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_Literal.hrl +++ /dev/null @@ -1 +0,0 @@ --record(literal, {value :: gleam@dynamic:dynamic_()}). diff --git a/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_OtherExpression.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@gleam_panic_OtherExpression.hrl deleted file mode 100644 index 0424990..0000000 --- a/build/dev/erlang/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/dev/erlang/gleeunit/include/gleeunit@internal@reporting_State.hrl b/build/dev/erlang/gleeunit/include/gleeunit@internal@reporting_State.hrl deleted file mode 100644 index 575ccce..0000000 --- a/build/dev/erlang/gleeunit/include/gleeunit@internal@reporting_State.hrl +++ /dev/null @@ -1 +0,0 @@ --record(state, {passed :: integer(), failed :: integer(), skipped :: integer()}). diff --git a/build/dev/erlang/logger b/build/dev/erlang/logger deleted file mode 120000 index 590f9ed..0000000 --- a/build/dev/erlang/logger +++ /dev/null @@ -1 +0,0 @@ -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/logger \ No newline at end of file diff --git a/build/dev/erlang/mix b/build/dev/erlang/mix deleted file mode 120000 index b57e932..0000000 --- a/build/dev/erlang/mix +++ /dev/null @@ -1 +0,0 @@ -/Users/graham/.asdf/installs/elixir/1.19.0-rc.0-otp-27/lib/mix \ No newline at end of file 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_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 b72a41b..0000000 --- a/build/packages/gleam_stdlib/gleam.toml +++ /dev/null @@ -1,14 +0,0 @@ -name = "gleam_stdlib" -version = "0.62.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 1aae367..0000000 --- a/build/packages/gleam_stdlib/src/gleam/bit_array.gleam +++ /dev/null @@ -1,279 +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", "bit_array_base64_encode") -@external(javascript, "../gleam_stdlib.mjs", "encode64") -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", "base_decode64") -@external(javascript, "../gleam_stdlib.mjs", "decode64") -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 { - base64_encode(input, 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 0418644..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(fn(b) { from_bit_array(b) }) - |> 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 9939d56..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(from("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 7618331..0000000 --- a/build/packages/gleam_stdlib/src/gleam/dynamic/decode.gleam +++ /dev/null @@ -1,1057 +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.from("water"), decoder) -//// assert result == Ok(Water) -//// -//// let result = decode.run(dynamic.from("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.from(dict.from_list([ -/// #("data", dict.from_list([ -/// #("email", "lucy@example.com"), -/// #("name", "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.from(dict.from_list([ -/// #("one", dict.from_list([ -/// #("two", 1000), -/// ])), -/// ])) -/// -/// -/// decode.run(data, decoder) -/// // -> Ok(1000) -/// ``` -/// -/// ```gleam -/// dynamic.from(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 { - [] -> { - inner(data) - |> 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.from(dict.from_list([ -/// #("email", "lucy@example.com"), -/// #("name", "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.from(dict.from_list([ -/// #("email", "lucy@example.com"), -/// #("name", "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.from(dict.from_list([ -/// #("name", "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.from(dict.from_list([ -/// #("one", dict.from_list([])), -/// ])) -/// -/// -/// 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.from("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.from(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.from(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.from(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.from(3.14), decode.dynamic) -/// assert result == Ok(dynamic.from(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.from(<<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 = -/// decode.run(dynamic.from([1, 2, 3]), 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 = dict.from_list([ -/// #("one", 1), -/// #("two", 2), -/// ]) -/// -/// let result = -/// decode.run(dynamic.from(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.from(100), decode.optional(decode.int)) -/// assert result == Ok(option.Some(100)) -/// ``` -/// -/// ```gleam -/// let result = decode.run(dynamic.from(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.from(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.from(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.from(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 060ea89..0000000 --- a/build/packages/gleam_stdlib/src/gleam/int.gleam +++ /dev/null @@ -1,826 +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) { - to_float(base) - |> 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) { - to_float(x) - |> 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 551480b..0000000 --- a/build/packages/gleam_stdlib/src/gleam/list.gleam +++ /dev/null @@ -1,2394 +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. -/// -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) { ... }) -/// ``` -/// -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 { - [] -> [[]] - [_, ..] -> - index_map(list, fn(i, i_idx) { - index_fold(list, [], fn(acc, j, j_idx) { - case i_idx == j_idx { - True -> acc - False -> [j, ..acc] - } - }) - |> reverse - |> permutations - |> map(fn(permutation) { [i, ..permutation] }) - }) - |> flatten - } -} - -/// 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] -> - combinations(rest, 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) { - transpose(list) - |> 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 c44b800..0000000 --- a/build/packages/gleam_stdlib/src/gleam/result.gleam +++ /dev/null @@ -1,467 +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 - } -} - -/// Extracts the inner value from a result. Both the value and error must be of -/// the same type. -/// -/// ## Examples -/// -/// ```gleam -/// unwrap_both(Error(1)) -/// // -> 1 -/// ``` -/// -/// ```gleam -/// unwrap_both(Ok(2)) -/// // -> 2 -/// ``` -/// -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 c1e31c4..0000000 --- a/build/packages/gleam_stdlib/src/gleam/string.gleam +++ /dev/null @@ -1,853 +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. -/// -/// ## 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. -/// -/// ## 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. -/// -/// ## 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 -> do_slice(string, translated_idx, len) - } - } - False -> do_slice(string, idx, len) - } - } -} - -@external(erlang, "gleam_stdlib", "slice") -@external(javascript, "../gleam_stdlib.mjs", "string_slice") -fn do_slice(string: String, idx: Int, len: 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`. -/// -/// ## 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 { - False -> string - True -> - case pop_grapheme(string) { - Ok(#(_, string)) -> drop_start(string, num_graphemes - 1) - Error(Nil) -> string - } - } -} - -/// Drops *n* graphemes from the end of a `String`. -/// -/// ## 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 both `String`s and runs in linear time. If you find -/// yourself joining `String`s frequently consider using the [`string_tree`](../gleam/string_tree.html) -/// module as it can append `String`s much faster! -/// -/// ## 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 linear time. -/// -/// ## Examples -/// -/// ```gleam -/// repeat("ha", times: 3) -/// // -> "hahaha" -/// ``` -/// -pub fn repeat(string: String, times times: Int) -> String { - repeat_loop(string, times, "") -} - -fn repeat_loop(string: String, times: Int, acc: String) -> String { - case times <= 0 { - True -> acc - False -> repeat_loop(string, times - 1, acc <> 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" -/// ``` -/// -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) { - to_graphemes_loop(string, []) - |> 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)`. -/// -/// ## 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. -/// -pub fn inspect(term: anything) -> String { - do_inspect(term) - |> 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 de08428..0000000 --- a/build/packages/gleam_stdlib/src/gleam/uri.gleam +++ /dev/null @@ -1,765 +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) - - // It means the port segment is not composed of numbers, the port is invalid - // and so is the uri! - ":" <> _ -> Error(Nil) - - // `?` marks the beginning of the query with question mark. - "?" <> rest -> parse_query_with_question_mark(rest, pieces) - - // `#` marks the beginning of the fragment part. - "#" <> rest -> parse_fragment(rest, pieces) - - // `/` marks the beginning of a path. - "/" <> _ -> parse_path(uri_string, pieces) - - "" -> Ok(pieces) - - _ -> 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 = - string.split(relative.path, "/") - |> 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 -> - string.split(base.path, "/") - |> 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 80a11e4..0000000 --- a/build/packages/gleam_stdlib/src/gleam@bit_array.erl +++ /dev/null @@ -1,346 +0,0 @@ --module(gleam@bit_array). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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:bit_array_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:base_decode64(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 = gleam_stdlib:bit_array_base64_encode(Input, Padding), - _pipe@1 = gleam@string:replace(_pipe, <<"+"/utf8>>, <<"-"/utf8>>), - gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"_"/utf8>>). - --file("src/gleam/bit_array.gleam", 149). -?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", 163). -?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", 169). -?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", 190). --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", 186). -?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", 231). -?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", 272). -?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 a09a3eb..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]). --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(), BVF, fun(() -> BVF)) -> BVF. -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(() -> BVG), fun(() -> BVG)) -> BVG. -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 5e78e9c..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]). --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(B) -> from_bit_array(B) end), - 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 ad3b17b..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]). --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(LA, LB) :: any() | {gleam_phantom, LA, LB}. - --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(LK, LL)) -> list({LK, LL}). -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(MN, MO), MN) -> {ok, MO} | {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(MB, any()), MB) -> 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(MT, MU), MT, MU) -> dict(MT, MU). -insert(Dict, Key, Value) -> - maps:put(Key, Value, Dict). - --file("src/gleam/dict.gleam", 92). --spec from_list_loop(list({LU, LV}), dict(LU, LV)) -> dict(LU, LV). -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({LP, LQ})) -> dict(LP, LQ). -from_list(List) -> - maps:from_list(List). - --file("src/gleam/dict.gleam", 223). --spec reverse_and_concat(list(OD), list(OD)) -> list(OD). -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({NY, any()}), list(NY)) -> list(NY). -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(NT, any())) -> list(NT). -keys(Dict) -> - maps:keys(Dict). - --file("src/gleam/dict.gleam", 249). --spec do_values_loop(list({any(), ON}), list(ON)) -> list(ON). -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(), OI)) -> list(OI). -values(Dict) -> - maps:values(Dict). - --file("src/gleam/dict.gleam", 318). --spec do_take_loop(dict(PR, PS), list(PR), dict(PR, PS)) -> dict(PR, PS). -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(PD, PE), list(PD)) -> dict(PD, PE). -take(Dict, Desired_keys) -> - maps:with(Desired_keys, Dict). - --file("src/gleam/dict.gleam", 363). --spec insert_pair(dict(QP, QQ), {QP, QQ}) -> dict(QP, QQ). -insert_pair(Dict, Pair) -> - insert(Dict, erlang:element(1, Pair), erlang:element(2, Pair)). - --file("src/gleam/dict.gleam", 356). --spec fold_inserts(list({QI, QJ}), dict(QI, QJ)) -> dict(QI, QJ). -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(QA, QB), dict(QA, QB)) -> dict(QA, QB). -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(QV, QW), QV) -> dict(QV, QW). -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(RH, RI), list(RH)) -> dict(RH, RI). -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(RO, RP), RO, fun((gleam@option:option(RP)) -> RP)) -> dict(RO, RP). -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({SA, SB}), SD, fun((SD, SA, SB) -> SD)) -> SD. -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(RV, RW), RZ, fun((RZ, RV, RW) -> RZ)) -> RZ. -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(NF, NG), fun((NF, NG) -> NJ)) -> dict(NF, NJ). -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(OR, OS), fun((OR, OS) -> boolean())) -> dict(OR, OS). -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(SE, SF), fun((SE, SF) -> 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(SJ, SK), dict(SJ, SK), fun((SK, SK) -> SK)) -> dict(SJ, SK). -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 027b403..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]). --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(from(\"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 0996e6c..0000000 --- a/build/packages/gleam_stdlib/src/gleam@dynamic@decode.erl +++ /dev/null @@ -1,1084 +0,0 @@ --module(gleam@dynamic@decode). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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.from(\"water\"), decoder)\n" - " assert result == Ok(Water)\n" - "\n" - " let result = decode.run(dynamic.from(\"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(BXN) :: {decoder, - fun((gleam@dynamic:dynamic_()) -> {BXN, 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(BXV)) -> {ok, BXV} | - {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", 478). -?DOC( - " Finalise a decoder having successfully extracted a value.\n" - "\n" - " # Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.from(dict.from_list([\n" - " #(\"email\", \"lucy@example.com\"),\n" - " #(\"name\", \"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(BYW) -> decoder(BYW). -success(Data) -> - {decoder, fun(_) -> {Data, []} end}. - --file("src/gleam/dynamic/decode.gleam", 717). --spec decode_dynamic(gleam@dynamic:dynamic_()) -> {gleam@dynamic:dynamic_(), - list(decode_error())}. -decode_dynamic(Data) -> - {Data, []}. - --file("src/gleam/dynamic/decode.gleam", 871). -?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.from(1000), decoder)\n" - " assert result == Ok(\"1000\")\n" - " ```\n" -). --spec map(decoder(CBT), fun((CBT) -> CBV)) -> decoder(CBV). -map(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Transformer(Data), Errors} - end}. - --file("src/gleam/dynamic/decode.gleam", 880). -?DOC(" Apply a transformation function to any errors returned by the decoder.\n"). --spec map_errors( - decoder(CBX), - fun((list(decode_error())) -> list(decode_error())) -) -> decoder(CBX). -map_errors(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Data, Transformer(Errors)} - end}. - --file("src/gleam/dynamic/decode.gleam", 918). -?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(CCF), fun((CCF) -> decoder(CCH))) -> decoder(CCH). -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", 961). --spec run_decoders( - gleam@dynamic:dynamic_(), - {CCP, list(decode_error())}, - list(decoder(CCP)) -) -> {CCP, 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", 948). -?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.from(1000), decoder)\n" - " // -> Ok(\"1000\")\n" - " ```\n" -). --spec one_of(decoder(CCK), list(decoder(CCK))) -> decoder(CCK). -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", 1044). -?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(CDA))) -> decoder(CDA). -recursive(Inner) -> - {decoder, - fun(Data) -> - Decoder = Inner(), - (erlang:element(2, Decoder))(Data) - end}. - --file("src/gleam/dynamic/decode.gleam", 849). -?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.from(100), decode.optional(decode.int))\n" - " assert result == Ok(option.Some(100))\n" - " ```\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.from(Nil), decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" -). --spec optional(decoder(CBP)) -> decoder(gleam@option:option(CBP)). -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", 484). -?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", 608). --spec run_dynamic_function( - gleam@dynamic:dynamic_(), - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, BZQ} | {error, BZQ}) -) -> {BZQ, 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", 657). --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", 679). --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", 698). --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", 732). --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", 904). -?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.from(1000), decoder)\n" - " assert result == Error([DecodeError(\"MyThing\", \"Int\", [])])\n" - " ```\n" -). --spec collapse_errors(decoder(CCC), binary()) -> decoder(CCC). -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", 982). -?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(CCU, binary()) -> decoder(CCU). -failure(Zero, Expected) -> - {decoder, fun(D) -> {Zero, decode_error(Expected, D)} end}. - --file("src/gleam/dynamic/decode.gleam", 1011). -?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, CCW} | {error, CCW}) -) -> decoder(CCW). -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", 635). --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", 630). --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", 803). --spec fold_dict( - {gleam@dict:dict(CBB, CBC), list(decode_error())}, - gleam@dynamic:dynamic_(), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_()) -> {CBB, list(decode_error())}), - fun((gleam@dynamic:dynamic_()) -> {CBC, list(decode_error())}) -) -> {gleam@dict:dict(CBB, CBC), 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", 783). -?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 = dict.from_list([\n" - " #(\"one\", 1),\n" - " #(\"two\", 2),\n" - " ])\n" - "\n" - " let result =\n" - " decode.run(dynamic.from(values), decode.dict(decode.string, decode.int))\n" - " assert result == Ok(values)\n" - " ```\n" -). --spec dict(decoder(CAU), decoder(CAW)) -> decoder(gleam@dict:dict(CAU, CAW)). -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", 751). -?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" - " decode.run(dynamic.from([1, 2, 3]), decode.list(of: decode.int))\n" - " assert result == Ok([1, 2, 3])\n" - " ```\n" -). --spec list(decoder(CAI)) -> decoder(list(CAI)). -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", 438). --spec push_path({BYR, list(decode_error())}, list(any())) -> {BYR, - 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(BYF), - list(BYF), - fun((gleam@dynamic:dynamic_()) -> {BYI, list(decode_error())}), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_(), list(BYF)) -> {BYI, list(decode_error())}) -) -> {BYI, list(decode_error())}. -index(Path, Position, Inner, Data, Handle_miss) -> - case Path of - [] -> - _pipe = Inner(Data), - push_path(_pipe, 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@1 = {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]}, - push_path(_pipe@1, 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.from(dict.from_list([\n" - " #(\"data\", dict.from_list([\n" - " #(\"email\", \"lucy@example.com\"),\n" - " #(\"name\", \"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(BXQ), fun((BXQ) -> decoder(BXS))) -> decoder(BXS). -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.from(dict.from_list([\n" - " #(\"one\", dict.from_list([\n" - " #(\"two\", 1000),\n" - " ])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(1000)\n" - " ```\n" - "\n" - " ```gleam\n" - " dynamic.from(Nil)\n" - " |> decode.run(decode.optional(decode.int))\n" - " // -> Ok(option.None)\n" - " ```\n" -). --spec at(list(any()), decoder(BYC)) -> decoder(BYC). -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", 523). -?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.from(dict.from_list([\n" - " #(\"email\", \"lucy@example.com\"),\n" - " #(\"name\", \"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(BZA), fun((BZA) -> decoder(BZC))) -> decoder(BZC). -field(Field_name, Field_decoder, Next) -> - subfield([Field_name], Field_decoder, Next). - --file("src/gleam/dynamic/decode.gleam", 556). -?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.from(dict.from_list([\n" - " #(\"name\", \"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(), BZG, decoder(BZG), fun((BZG) -> decoder(BZI))) -> decoder(BZI). -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", 598). -?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.from(dict.from_list([\n" - " #(\"one\", dict.from_list([])),\n" - " ]))\n" - "\n" - "\n" - " decode.run(data, decoder)\n" - " // -> Ok(100)\n" - " ```\n" -). --spec optionally_at(list(any()), BZN, decoder(BZN)) -> decoder(BZN). -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 e893b8e..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]). --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 c1e8b5a..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]). --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(CNY) -> CNY. -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(CNZ, fun((CNZ) -> any())) -> CNZ. -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 b9f71b2..0000000 --- a/build/packages/gleam_stdlib/src/gleam@int.erl +++ /dev/null @@ -1,984 +0,0 @@ --module(gleam@int). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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", 107). -?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", 139). -?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", 161). -?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", 194). -?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", 214). -?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", 227). -?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", 240). -?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", 253). -?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", 278). -?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 = erlang:float(Base), - gleam@float:power(_pipe, Exponent). - --file("src/gleam/int.gleam", 86). -?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 = erlang:float(X), - gleam@float:square_root(_pipe). - --file("src/gleam/int.gleam", 314). -?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", 334). -?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", 350). -?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", 289). -?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", 371). -?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", 389). -?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", 402). -?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", 419). --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", 415). -?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", 439). --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", 435). -?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", 454). --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", 447). --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", 469). --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", 462). --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", 498). -?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", 531). -?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", 583). -?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", 625). -?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", 669). -?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", 703). -?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", 731). -?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", 764). -?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", 776). -?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", 786). -?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", 796). -?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", 806). -?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", 816). -?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", 826). -?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 a21232e..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]). --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 f266a06..0000000 --- a/build/packages/gleam_stdlib/src/gleam@list.erl +++ /dev/null @@ -1,2860 +0,0 @@ --module(gleam@list). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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, permutations/1, 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]). --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(YG) :: {continue, YG} | {stop, YG}. - --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(YN), fun((YN) -> 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(YL), fun((YL) -> boolean())) -> integer(). -count(List, Predicate) -> - count_loop(List, Predicate, 0). - --file("src/gleam/list.gleam", 139). -?DOC( - " Reverses a list and prepends it to another list.\n" - " This function runs in linear time, proportional to the length of the list\n" - " to prepend.\n" -). --spec reverse_and_prepend(list(YS), list(YS)) -> list(YS). -reverse_and_prepend(Prefix, Suffix) -> - case Prefix of - [] -> - Suffix; - - [First | Rest] -> - reverse_and_prepend(Rest, [First | Suffix]) - end. - --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(YP)) -> list(YP). -reverse(List) -> - lists:reverse(List). - --file("src/gleam/list.gleam", 167). -?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", 203). -?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(YY), YY) -> boolean(). -contains(List, Elem) -> - case List of - [] -> - false; - - [First | _] when First =:= Elem -> - true; - - [_ | Rest] -> - contains(Rest, Elem) - end. - --file("src/gleam/list.gleam", 230). -?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(AAA)) -> {ok, AAA} | {error, nil}. -first(List) -> - case List of - [] -> - {error, nil}; - - [First | _] -> - {ok, First} - end. - --file("src/gleam/list.gleam", 259). -?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(AAE)) -> {ok, list(AAE)} | {error, nil}. -rest(List) -> - case List of - [] -> - {error, nil}; - - [_ | Rest] -> - {ok, Rest} - end. - --file("src/gleam/list.gleam", 301). --spec group_loop(list(AAP), fun((AAP) -> AAR), gleam@dict:dict(AAR, list(AAP))) -> gleam@dict:dict(AAR, list(AAP)). -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", 297). -?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(AAJ), fun((AAJ) -> AAL)) -> gleam@dict:dict(AAL, list(AAJ)). -group(List, Key) -> - group_loop(List, Key, maps:new()). - --file("src/gleam/list.gleam", 338). --spec filter_loop(list(ABB), fun((ABB) -> boolean()), list(ABB)) -> list(ABB). -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", 334). -?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(AAY), fun((AAY) -> boolean())) -> list(AAY). -filter(List, Predicate) -> - filter_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 370). --spec filter_map_loop( - list(ABM), - fun((ABM) -> {ok, ABO} | {error, any()}), - list(ABO) -) -> list(ABO). -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", 366). -?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(ABF), fun((ABF) -> {ok, ABH} | {error, any()})) -> list(ABH). -filter_map(List, Fun) -> - filter_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 401). --spec map_loop(list(ABY), fun((ABY) -> ACA), list(ACA)) -> list(ACA). -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", 397). -?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(ABU), fun((ABU) -> ABW)) -> list(ABW). -map(List, Fun) -> - map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 428). --spec map2_loop(list(ACJ), list(ACL), fun((ACJ, ACL) -> ACN), list(ACN)) -> list(ACN). -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", 424). -?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(ACD), list(ACF), fun((ACD, ACF) -> ACH)) -> list(ACH). -map2(List1, List2, Fun) -> - map2_loop(List1, List2, Fun, []). - --file("src/gleam/list.gleam", 461). --spec map_fold_loop(list(ACV), fun((ACX, ACV) -> {ACX, ACY}), ACX, list(ACY)) -> {ACX, - list(ACY)}. -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", 453). -?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(ACQ), ACS, fun((ACS, ACQ) -> {ACS, ACT})) -> {ACS, - list(ACT)}. -map_fold(List, Initial, Fun) -> - map_fold_loop(List, Fun, Initial, []). - --file("src/gleam/list.gleam", 493). --spec index_map_loop( - list(ADF), - fun((ADF, integer()) -> ADH), - integer(), - list(ADH) -) -> list(ADH). -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", 489). -?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(ADB), fun((ADB, integer()) -> ADD)) -> list(ADD). -index_map(List, Fun) -> - index_map_loop(List, Fun, 0, []). - --file("src/gleam/list.gleam", 547). --spec try_map_loop(list(ADT), fun((ADT) -> {ok, ADV} | {error, ADW}), list(ADV)) -> {ok, - list(ADV)} | - {error, ADW}. -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", 540). -?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(ADK), fun((ADK) -> {ok, ADM} | {error, ADN})) -> {ok, - list(ADM)} | - {error, ADN}. -try_map(List, Fun) -> - try_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 582). -?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(AED), integer()) -> list(AED). -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", 617). --spec take_loop(list(AEJ), integer(), list(AEJ)) -> list(AEJ). -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", 613). -?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(AEG), integer()) -> list(AEG). -take(List, N) -> - take_loop(List, N, []). - --file("src/gleam/list.gleam", 637). -?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", 657). -?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(AEP) -> list(AEP). -wrap(Item) -> - [Item]. - --file("src/gleam/list.gleam", 678). --spec append_loop(list(AEV), list(AEV)) -> list(AEV). -append_loop(First, Second) -> - case First of - [] -> - Second; - - [First@1 | Rest] -> - append_loop(Rest, [First@1 | Second]) - end. - --file("src/gleam/list.gleam", 674). -?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(AER), list(AER)) -> list(AER). -append(First, Second) -> - lists:append(First, Second). - --file("src/gleam/list.gleam", 698). -?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(AEZ), AEZ) -> list(AEZ). -prepend(List, Item) -> - [Item | List]. - --file("src/gleam/list.gleam", 719). --spec flatten_loop(list(list(AFG)), list(AFG)) -> list(AFG). -flatten_loop(Lists, Acc) -> - case Lists of - [] -> - lists:reverse(Acc); - - [List | Further_lists] -> - flatten_loop(Further_lists, reverse_and_prepend(List, Acc)) - end. - --file("src/gleam/list.gleam", 715). -?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(AFC))) -> list(AFC). -flatten(Lists) -> - lists:append(Lists). - --file("src/gleam/list.gleam", 736). -?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(AFL), fun((AFL) -> list(AFN))) -> list(AFN). -flat_map(List, Fun) -> - lists:append(map(List, Fun)). - --file("src/gleam/list.gleam", 748). -?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(AFQ), AFS, fun((AFS, AFQ) -> AFS)) -> AFS. -fold(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - fold(Rest, Fun(Initial, First), Fun) - end. - --file("src/gleam/list.gleam", 770). -?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(AFT), AFV, fun((AFV, AFT) -> AFV)) -> AFV. -fold_right(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - Fun(fold_right(Rest, Initial, Fun), First) - end. - --file("src/gleam/list.gleam", 798). --spec index_fold_loop( - list(AFZ), - AGB, - fun((AGB, AFZ, integer()) -> AGB), - integer() -) -> AGB. -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", 790). -?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" - " ```\n" -). --spec index_fold(list(AFW), AFY, fun((AFY, AFW, integer()) -> AFY)) -> AFY. -index_fold(List, Initial, Fun) -> - index_fold_loop(List, Initial, Fun, 0). - --file("src/gleam/list.gleam", 830). -?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(AGC), AGE, fun((AGE, AGC) -> {ok, AGE} | {error, AGF})) -> {ok, - AGE} | - {error, AGF}. -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", 869). -?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(AGK), AGM, fun((AGM, AGK) -> continue_or_stop(AGM))) -> AGM. -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", 906). -?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(AGO), fun((AGO) -> boolean())) -> {ok, AGO} | {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", 942). -?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(AGS), fun((AGS) -> {ok, AGU} | {error, any()})) -> {ok, AGU} | - {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", 977). -?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(AHA), fun((AHA) -> 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", 1014). -?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(AHC), fun((AHC) -> 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", 1056). --spec zip_loop(list(AHJ), list(AHL), list({AHJ, AHL})) -> list({AHJ, AHL}). -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", 1052). -?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(AHE), list(AHG)) -> list({AHE, AHG}). -zip(List, Other) -> - zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1097). --spec strict_zip_loop(list(AHW), list(AHY), list({AHW, AHY})) -> {ok, - list({AHW, AHY})} | - {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", 1090). -?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(AHP), list(AHR)) -> {ok, list({AHP, AHR})} | {error, nil}. -strict_zip(List, Other) -> - strict_zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1128). --spec unzip_loop(list({AIJ, AIK}), list(AIJ), list(AIK)) -> {list(AIJ), - list(AIK)}. -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", 1124). -?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({AIE, AIF})) -> {list(AIE), list(AIF)}. -unzip(Input) -> - unzip_loop(Input, [], []). - --file("src/gleam/list.gleam", 1163). --spec intersperse_loop(list(AIT), AIT, list(AIT)) -> list(AIT). -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", 1156). -?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(AIQ), AIQ) -> list(AIQ). -intersperse(List, Elem) -> - case List of - [] -> - List; - - [_] -> - List; - - [First | Rest] -> - intersperse_loop(Rest, Elem, [First]) - end. - --file("src/gleam/list.gleam", 1186). --spec unique_loop(list(AJA), gleam@dict:dict(AJA, nil), list(AJA)) -> list(AJA). -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", 1182). -?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(AIX)) -> list(AIX). -unique(List) -> - unique_loop(List, maps:new(), []). - --file("src/gleam/list.gleam", 1272). -?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(AJJ), - fun((AJJ, AJJ) -> gleam@order:order()), - list(AJJ), - sorting(), - AJJ, - list(list(AJJ)) -) -> list(list(AJJ)). -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", 1420). -?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(AKG), - list(AKG), - fun((AKG, AKG) -> gleam@order:order()), - list(AKG) -) -> list(AKG). -merge_ascendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - reverse_and_prepend(List, Acc); - - {List, []} -> - reverse_and_prepend(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", 1373). -?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(AJU)), - fun((AJU, AJU) -> gleam@order:order()), - list(list(AJU)) -) -> list(list(AJU)). -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", 1447). -?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(AKL), - list(AKL), - fun((AKL, AKL) -> gleam@order:order()), - list(AKL) -) -> list(AKL). -merge_descendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - reverse_and_prepend(List, Acc); - - {List, []} -> - reverse_and_prepend(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", 1395). -?DOC(" This is the same as merge_ascending_pairs but flipped for descending lists.\n"). --spec merge_descending_pairs( - list(list(AKA)), - fun((AKA, AKA) -> gleam@order:order()), - list(list(AKA)) -) -> list(list(AKA)). -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", 1339). -?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(AJQ)), - sorting(), - fun((AJQ, AJQ) -> gleam@order:order()) -) -> list(AJQ). -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", 1210). -?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(AJG), fun((AJG, AJG) -> gleam@order:order())) -> list(AJG). -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", 1487). --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", 1483). -?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", 1513). --spec repeat_loop(AKV, integer(), list(AKV)) -> list(AKV). -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", 1509). -?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(AKT, integer()) -> list(AKT). -repeat(A, Times) -> - repeat_loop(A, Times, []). - --file("src/gleam/list.gleam", 1546). --spec split_loop(list(ALC), integer(), list(ALC)) -> {list(ALC), list(ALC)}. -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", 1542). -?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(AKY), integer()) -> {list(AKY), list(AKY)}. -split(List, Index) -> - split_loop(List, Index, []). - --file("src/gleam/list.gleam", 1582). --spec split_while_loop(list(ALL), fun((ALL) -> boolean()), list(ALL)) -> {list(ALL), - list(ALL)}. -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", 1575). -?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(ALH), fun((ALH) -> boolean())) -> {list(ALH), list(ALH)}. -split_while(List, Predicate) -> - split_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1622). -?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({ALQ, ALR}), ALQ) -> {ok, ALR} | {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", 1653). -?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({ALV, ALW}), ALV) -> list(ALW). -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", 1693). --spec key_pop_loop(list({AMF, AMG}), AMF, list({AMF, AMG})) -> {ok, - {AMG, list({AMF, AMG})}} | - {error, nil}. -key_pop_loop(List, Key, Checked) -> - case List of - [] -> - {error, nil}; - - [{K, V} | Rest] when K =:= Key -> - {ok, {V, reverse_and_prepend(Checked, Rest)}}; - - [First | Rest@1] -> - key_pop_loop(Rest@1, Key, [First | Checked]) - end. - --file("src/gleam/list.gleam", 1689). -?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({ALZ, AMA}), ALZ) -> {ok, {AMA, list({ALZ, AMA})}} | - {error, nil}. -key_pop(List, Key) -> - key_pop_loop(List, Key, []). - --file("src/gleam/list.gleam", 1727). --spec key_set_loop(list({AMQ, AMR}), AMQ, AMR, list({AMQ, AMR})) -> list({AMQ, - AMR}). -key_set_loop(List, Key, Value, Inspected) -> - case List of - [{K, _} | Rest] when K =:= Key -> - reverse_and_prepend(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", 1723). -?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({AMM, AMN}), AMM, AMN) -> list({AMM, AMN}). -key_set(List, Key, Value) -> - key_set_loop(List, Key, Value, []). - --file("src/gleam/list.gleam", 1755). -?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(AMV), fun((AMV) -> any())) -> nil. -each(List, F) -> - case List of - [] -> - nil; - - [First | Rest] -> - F(First), - each(Rest, F) - end. - --file("src/gleam/list.gleam", 1781). -?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(AMY), fun((AMY) -> {ok, any()} | {error, ANB})) -> {ok, nil} | - {error, ANB}. -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", 1814). --spec partition_loop(list(BGB), fun((BGB) -> boolean()), list(BGB), list(BGB)) -> {list(BGB), - list(BGB)}. -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", 1807). -?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(ANG), fun((ANG) -> boolean())) -> {list(ANG), list(ANG)}. -partition(List, Categorise) -> - partition_loop(List, Categorise, [], []). - --file("src/gleam/list.gleam", 1834). -?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(ANP)) -> list(list(ANP)). -permutations(List) -> - case List of - [] -> - [[]]; - - [_ | _] -> - _pipe@3 = index_map( - List, - fun(I, I_idx) -> - _pipe = index_fold( - List, - [], - fun(Acc, J, J_idx) -> case I_idx =:= J_idx of - true -> - Acc; - - false -> - [J | Acc] - end end - ), - _pipe@1 = lists:reverse(_pipe), - _pipe@2 = permutations(_pipe@1), - map(_pipe@2, fun(Permutation) -> [I | Permutation] end) - end - ), - lists:append(_pipe@3) - end. - --file("src/gleam/list.gleam", 1874). --spec window_loop(list(list(ANX)), list(ANX), integer()) -> list(list(ANX)). -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", 1867). -?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(ANT), integer()) -> list(list(ANT)). -window(List, N) -> - case N =< 0 of - true -> - []; - - false -> - window_loop([], List, N) - end. - --file("src/gleam/list.gleam", 1897). -?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(AOD)) -> list({AOD, AOD}). -window_by_2(List) -> - zip(List, drop(List, 1)). - --file("src/gleam/list.gleam", 1910). -?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(AOG), fun((AOG) -> boolean())) -> list(AOG). -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", 1940). --spec take_while_loop(list(AOM), fun((AOM) -> boolean()), list(AOM)) -> list(AOM). -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", 1933). -?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(AOJ), fun((AOJ) -> boolean())) -> list(AOJ). -take_while(List, Predicate) -> - take_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1972). --spec chunk_loop(list(AOV), fun((AOV) -> AOX), AOX, list(AOV), list(list(AOV))) -> list(list(AOV)). -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", 1965). -?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(AOQ), fun((AOQ) -> any())) -> list(list(AOQ)). -chunk(List, F) -> - case List of - [] -> - []; - - [First | Rest] -> - chunk_loop(Rest, F, F(First), [First], []) - end. - --file("src/gleam/list.gleam", 2017). --spec sized_chunk_loop( - list(APH), - integer(), - integer(), - list(APH), - list(list(APH)) -) -> list(list(APH)). -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", 2013). -?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(APD), integer()) -> list(list(APD)). -sized_chunk(List, Count) -> - sized_chunk_loop(List, Count, Count, [], []). - --file("src/gleam/list.gleam", 2061). -?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(APO), fun((APO, APO) -> APO)) -> {ok, APO} | {error, nil}. -reduce(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, fold(Rest, First, Fun)} - end. - --file("src/gleam/list.gleam", 2085). --spec scan_loop(list(APW), APY, list(APY), fun((APY, APW) -> APY)) -> list(APY). -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", 2077). -?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(APS), APU, fun((APU, APS) -> APU)) -> list(APU). -scan(List, Initial, Fun) -> - scan_loop(List, Initial, [], Fun). - --file("src/gleam/list.gleam", 2118). -?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(AQB)) -> {ok, AQB} | {error, nil}. -last(List) -> - case List of - [] -> - {error, nil}; - - [Last] -> - {ok, Last}; - - [_ | Rest] -> - last(Rest) - end. - --file("src/gleam/list.gleam", 2140). -?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(AQF), integer()) -> list(list(AQF)). -combinations(Items, N) -> - case {N, Items} of - {0, _} -> - [[]]; - - {_, []} -> - []; - - {_, [First | Rest]} -> - _pipe = combinations(Rest, N - 1), - _pipe@1 = map(_pipe, fun(Combination) -> [First | Combination] end), - _pipe@2 = lists:reverse(_pipe@1), - fold(_pipe@2, combinations(Rest, N), fun(Acc, C) -> [C | Acc] end) - end. - --file("src/gleam/list.gleam", 2165). --spec combination_pairs_loop(list(AQM), list({AQM, AQM})) -> list({AQM, AQM}). -combination_pairs_loop(Items, Acc) -> - case Items of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - First_combinations = map(Rest, fun(Other) -> {First, Other} end), - Acc@1 = reverse_and_prepend(First_combinations, Acc), - combination_pairs_loop(Rest, Acc@1) - end. - --file("src/gleam/list.gleam", 2161). -?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(AQJ)) -> list({AQJ, AQJ}). -combination_pairs(Items) -> - combination_pairs_loop(Items, []). - --file("src/gleam/list.gleam", 2220). --spec take_firsts(list(list(ARG)), list(ARG), list(list(ARG))) -> {list(ARG), - list(list(ARG))}. -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", 2207). --spec transpose_loop(list(list(AQZ)), list(list(AQZ))) -> list(list(AQZ)). -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", 2203). -?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(AQU))) -> list(list(AQU)). -transpose(List_of_lists) -> - transpose_loop(List_of_lists, []). - --file("src/gleam/list.gleam", 2185). -?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(AQQ))) -> list(AQQ). -interleave(List) -> - _pipe = transpose(List), - lists:append(_pipe). - --file("src/gleam/list.gleam", 2253). --spec shuffle_pair_unwrap_loop(list({float(), ARS}), list(ARS)) -> list(ARS). -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", 2261). --spec do_shuffle_by_pair_indexes(list({float(), ARW})) -> list({float(), ARW}). -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", 2246). -?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(ARP)) -> list(ARP). -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", 2293). --spec max_loop(list(ASG), fun((ASG, ASG) -> gleam@order:order()), ASG) -> ASG. -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", 2283). -?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(ARZ), fun((ARZ, ARZ) -> gleam@order:order())) -> {ok, ARZ} | - {error, nil}. -max(List, Compare) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, max_loop(Rest, Compare, First)} - end. - --file("src/gleam/list.gleam", 2374). --spec build_reservoir_loop( - list(ASV), - integer(), - gleam@dict:dict(integer(), ASV) -) -> {gleam@dict:dict(integer(), ASV), list(ASV)}. -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", 2370). -?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(ASQ), integer()) -> {gleam@dict:dict(integer(), ASQ), - list(ASQ)}. -build_reservoir(List, N) -> - build_reservoir_loop(List, N, maps:new()). - --file("src/gleam/list.gleam", 2358). --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 => 2359, - value => _assert_fail, - start => 55490, - 'end' => 55561, - pattern_start => 55501, - pattern_end => 55511}) - end, - Random@1. - --file("src/gleam/list.gleam", 2335). --spec sample_loop( - list(ASK), - gleam@dict:dict(integer(), ASK), - integer(), - float() -) -> gleam@dict:dict(integer(), ASK). -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 => 2342, - value => _assert_fail, - start => 55051, - 'end' => 55097, - pattern_start => 55062, - pattern_end => 55069}) - 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", 2317). -?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(ASH), integer()) -> list(ASH). -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. 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 cbacd70..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]). --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(GA) :: {some, GA} | none. - --file("src/gleam/option.gleam", 59). --spec reverse_and_prepend(list(GP), list(GP)) -> list(GP). -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(GG)), list(GG)) -> option(list(GG)). -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(GB))) -> option(list(GB)). -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(GX), HA) -> {ok, GX} | {error, HA}. -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, HD} | {error, any()}) -> option(HD). -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(HI), HI) -> HI. -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(HK), fun(() -> HK)) -> HK. -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(HM), fun((HM) -> HO)) -> option(HO). -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(HQ))) -> option(HQ). -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(HU), fun((HU) -> option(HW))) -> option(HW). -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(HZ), option(HZ)) -> option(HZ). -'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(ID), fun(() -> option(ID))) -> option(ID). -lazy_or(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second() - end. - --file("src/gleam/option.gleam", 352). --spec values_loop(list(option(IL)), list(IL)) -> list(IL). -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(IH))) -> list(IH). -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 5ad2cb2..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]). --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 228140e..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]). --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({COH, any()}) -> COH. -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(), COK}) -> COK. -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({COL, COM}) -> {COM, COL}. -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({CON, COO}, fun((CON) -> COP)) -> {COP, COO}. -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({COQ, COR}, fun((COR) -> COS)) -> {COQ, COS}. -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(COT, COU) -> {COT, COU}. -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 3a0deb5..0000000 --- a/build/packages/gleam_stdlib/src/gleam@result.erl +++ /dev/null @@ -1,566 +0,0 @@ --module(gleam@result). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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, CPE} | {error, CPF}, fun((CPE) -> CPI)) -> {ok, CPI} | - {error, CPF}. -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, CPL} | {error, CPM}, fun((CPM) -> CPP)) -> {ok, CPL} | - {error, CPP}. -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, CPS} | {error, CPT}} | {error, CPT}) -> {ok, CPS} | - {error, CPT}. -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, CQA} | {error, CQB}, fun((CQA) -> {ok, CQE} | {error, CQB})) -> {ok, - CQE} | - {error, CQB}. -'try'(Result, Fun) -> - case Result of - {ok, X} -> - Fun(X); - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 169). --spec then({ok, CQJ} | {error, CQK}, fun((CQJ) -> {ok, CQN} | {error, CQK})) -> {ok, - CQN} | - {error, CQK}. -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, CQS} | {error, any()}, CQS) -> CQS. -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, CQW} | {error, any()}, fun(() -> CQW)) -> CQW. -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, CRB}, CRB) -> CRB. -unwrap_error(Result, Default) -> - case Result of - {ok, _} -> - Default; - - {error, E} -> - E - end. - --file("src/gleam/result.gleam", 257). -?DOC( - " Extracts the inner value from a result. Both the value and error must be of\n" - " the same type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " unwrap_both(Error(1))\n" - " // -> 1\n" - " ```\n" - "\n" - " ```gleam\n" - " unwrap_both(Ok(2))\n" - " // -> 2\n" - " ```\n" -). --spec unwrap_both({ok, CRE} | {error, CRE}) -> CRE. -unwrap_both(Result) -> - case Result of - {ok, A} -> - A; - - {error, A@1} -> - A@1 - end. - --file("src/gleam/result.gleam", 288). -?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, CRH} | {error, CRI}, {ok, CRH} | {error, CRI}) -> {ok, CRH} | - {error, CRI}. -'or'(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second - end. - --file("src/gleam/result.gleam", 321). -?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, CRP} | {error, CRQ}, fun(() -> {ok, CRP} | {error, CRQ})) -> {ok, - CRP} | - {error, CRQ}. -lazy_or(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second() - end. - --file("src/gleam/result.gleam", 347). -?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, CRX} | {error, CRY})) -> {ok, list(CRX)} | {error, CRY}. -all(Results) -> - gleam@list:try_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 367). --spec partition_loop(list({ok, CSM} | {error, CSN}), list(CSM), list(CSN)) -> {list(CSM), - list(CSN)}. -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", 363). -?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, CSF} | {error, CSG})) -> {list(CSF), list(CSG)}. -partition(Results) -> - partition_loop(Results, [], []). - --file("src/gleam/result.gleam", 389). -?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, CSV}, CSY) -> {ok, CSY} | {error, CSV}. -replace(Result, Value) -> - case Result of - {ok, _} -> - {ok, Value}; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 410). -?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, CTB} | {error, any()}, CTF) -> {ok, CTB} | {error, CTF}. -replace_error(Result, Error) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, _} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 426). -?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, CTI} | {error, any()})) -> list(CTI). -values(Results) -> - gleam@list:filter_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 459). -?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, CTO} | {error, CTP}, - fun((CTP) -> {ok, CTO} | {error, CTS}) -) -> {ok, CTO} | {error, CTS}. -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 6a15c29..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]). --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(CYN) :: {set, gleam@dict:dict(CYN, 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(CYY), CYY) -> 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(CZA), CZA) -> set(CZA). -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(CZD)) -> list(CZD). -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(CZJ), CZL, fun((CZL, CZJ) -> CZL)) -> CZL. -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(CZM), fun((CZM) -> boolean())) -> set(CZM). -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(CZT), list(CZT)) -> set(CZT). -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(CZX), list(CZX)) -> set(CZX). -take(Set, Desired) -> - {set, gleam@dict:take(erlang:element(2, Set), Desired)}. - --file("src/gleam/set.gleam", 287). --spec order(set(DAF), set(DAF)) -> {set(DAF), set(DAF)}. -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(DAK), set(DAK)) -> set(DAK). -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(DAO), set(DAO)) -> set(DAO). -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(DAS), set(DAS)) -> 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(DAV), set(DAV)) -> 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(DBC), fun((DBC) -> 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(CYV), CYV) -> set(CYV). -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(CZG)) -> set(CZG). -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(CZP), fun((CZP) -> CZR)) -> set(CZR). -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(DAB), set(DAB)) -> set(DAB). -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(DAY), set(DAY)) -> set(DAY). -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 a441003..0000000 --- a/build/packages/gleam_stdlib/src/gleam@string.erl +++ /dev/null @@ -1,957 +0,0 @@ --module(gleam@string). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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, drop_start/2, 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]). --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.\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.\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", 190). -?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" - " ## 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", 223). -?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 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", 254). -?DOC( - " Drops *n* graphemes from the end of a `String`.\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", 282). -?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", 295). -?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", 308). -?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", 347). -?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", 378). -?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", 400). --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", 396). -?DOC( - " Creates a new `String` by joining many `String`s together.\n" - "\n" - " This function copies both `String`s and runs in linear time. If you find\n" - " yourself joining `String`s frequently consider using the [`string_tree`](../gleam/string_tree.html)\n" - " module as it can append `String`s much faster!\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", 422). --spec repeat_loop(binary(), integer(), binary()) -> binary(). -repeat_loop(String, Times, Acc) -> - case Times =< 0 of - true -> - Acc; - - false -> - repeat_loop(String, Times - 1, <>) - end. - --file("src/gleam/string.gleam", 418). -?DOC( - " Creates a new `String` by repeating a `String` a given number of times.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " repeat(\"ha\", times: 3)\n" - " // -> \"hahaha\"\n" - " ```\n" -). --spec repeat(binary(), integer()) -> binary(). -repeat(String, Times) -> - repeat_loop(String, Times, <<""/utf8>>). - --file("src/gleam/string.gleam", 447). --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", 440). -?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", 525). --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", 478). -?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", 511). -?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", 569). -?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", 583). -?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", 547). -?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", 610). -?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", 234). -?DOC( - " Drops *n* graphemes from the start of a `String`.\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 - false -> - String; - - true -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {_, String@1}} -> - drop_start(String@1, Num_graphemes - 1); - - {error, nil} -> - String - end - end. - --file("src/gleam/string.gleam", 626). --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", 621). -?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 = to_graphemes_loop(String, []), - lists:reverse(_pipe). - --file("src/gleam/string.gleam", 319). -?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", 673). --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", 668). --spec do_to_utf_codepoints(binary()) -> list(integer()). -do_to_utf_codepoints(String) -> - to_utf_codepoints_loop(<>, []). - --file("src/gleam/string.gleam", 663). -?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", 713). -?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", 719). -?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", 740). -?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", 757). -?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", 780). -?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", 803). -?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" - " ## 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", 821). -?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", 830). -?DOC(" Returns a `String` representation of a term in Gleam syntax.\n"). --spec inspect(any()) -> binary(). -inspect(Term) -> - _pipe = gleam_stdlib:inspect(Term), - unicode:characters_to_binary(_pipe). - --file("src/gleam/string.gleam", 853). -?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). 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 c36c1b2..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]). --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 3f94175..0000000 --- a/build/packages/gleam_stdlib/src/gleam@uri.erl +++ /dev/null @@ -1,1030 +0,0 @@ --module(gleam@uri). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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", 503). --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", 475). --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", 468). --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", 434). --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", 430). --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", 385). --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, _/binary>> -> - {error, nil}; - - <<"?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<"#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_path(Uri_string, Pieces); - - <<""/utf8>> -> - {ok, Pieces}; - - _ -> - {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", 534). -?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", 570). -?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", 555). --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", 547). -?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", 583). -?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", 605). --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", 601). --spec remove_dot_segments(list(binary())) -> list(binary()). -remove_dot_segments(Input) -> - remove_dot_segments_loop(Input, []). - --file("src/gleam/uri.gleam", 597). -?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", 636). -?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", 680). -?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", 759). --spec drop_last(list(DGQ)) -> list(DGQ). -drop_last(Elements) -> - gleam@list:take(Elements, erlang:length(Elements) - 1). - --file("src/gleam/uri.gleam", 763). --spec join_segments(list(binary())) -> binary(). -join_segments(Segments) -> - gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). - --file("src/gleam/uri.gleam", 703). -?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 = gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ), - _pipe@1 = remove_dot_segments(_pipe), - join_segments(_pipe@1) - 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@2 = gleam@string:split( - erlang:element(6, Base), - <<"/"/utf8>> - ), - _pipe@3 = drop_last(_pipe@2), - lists:append( - _pipe@3, - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ) - ) - end, - Path@1 = begin - _pipe@4 = Path_segments, - _pipe@5 = remove_dot_segments(_pipe@4), - join_segments(_pipe@5) - 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 2cac7ac..0000000 --- a/build/packages/gleam_stdlib/src/gleam_stdlib.app.src +++ /dev/null @@ -1,31 +0,0 @@ -{application, gleam_stdlib, [ - {vsn, "0.62.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 0bfcd2f..0000000 --- a/build/packages/gleam_stdlib/src/gleam_stdlib.erl +++ /dev/null @@ -1,529 +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, - base_decode64/1, parse_query/1, bit_array_concat/1, - bit_array_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). -bit_array_base64_encode(Bin, Padding) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - base64:encode(PaddedBin, #{padding => Padding}). --else. -bit_array_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. - -base_decode64(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 -> - {ok, {uri, - maps_get_optional(Uri, scheme), - maps_get_optional(Uri, userinfo), - maps_get_optional(Uri, host), - maps_get_optional(Uri, 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_from_string(\"", 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 2edf3ad..0000000 --- a/build/packages/gleam_stdlib/src/gleam_stdlib.mjs +++ /dev/null @@ -1,1044 +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_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 encode64(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 decode64(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/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 b79d611..0000000 --- a/build/packages/gleeunit/gleam.toml +++ /dev/null @@ -1,16 +0,0 @@ -name = "gleeunit" -version = "1.6.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.11.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 6d458ca..0000000 --- a/build/packages/gleeunit/src/gleeunit.app.src +++ /dev/null @@ -1,16 +0,0 @@ -{application, gleeunit, [ - {vsn, "1.6.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 ba208f2..0000000 --- a/build/packages/gleeunit/src/gleeunit.erl +++ /dev/null @@ -1,87 +0,0 @@ --module(gleeunit). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --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())}}. - --file("src/gleeunit.gleam", 37). --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}]}}], - 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 4e7b3ec..0000000 --- a/build/packages/gleeunit/src/gleeunit.gleam +++ /dev/null @@ -1,80 +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)]))] - - 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))) -} - -@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 cef7646..0000000 --- a/build/packages/gleeunit/src/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import { Ok, Error, Empty, NonEmpty } from "../../gleam.mjs"; -import { - GleamPanic, - Todo, - Panic, - LetAssert, - Assert, - BinaryOperator, - FunctionCall, - OtherExpression, - AssertedExpression, - Literal, - Expression, - Unevaluated, -} from "./gleam_panic.mjs"; - -export function from_dynamic(error) { - if (!(error instanceof globalThis.Error) || !error.gleam_error) { - return new Error(undefined); - } - - if (error.gleam_error === "todo") { - return wrap(error, new Todo()); - } - - if (error.gleam_error === "panic") { - return wrap(error, new Panic()); - } - - if (error.gleam_error === "let_assert") { - let kind = new LetAssert( - error.start, - error.end, - error.pattern_start, - error.pattern_end, - error.value, - ); - return wrap(error, kind); - } - - if (error.gleam_error === "assert") { - let kind = new Assert( - error.start, - error.end, - error.expression_start, - assert_kind(error), - ); - return wrap(error, kind); - } - - return new Error(undefined); -} - -function assert_kind(error) { - if (error.kind == "binary_operator") { - return new BinaryOperator( - error.operator, - expression(error.left), - expression(error.right), - ); - } - - if (error.kind == "function_call") { - let list = new Empty(); - let i = error.arguments.length; - while (i--) { - list = new NonEmpty(expression(error.arguments[i]), list); - } - return new FunctionCall(list); - } - - return new OtherExpression(expression(error.expression)); -} - -function expression(data) { - const expression = new AssertedExpression(data.start, data.end, undefined); - if (data.kind == "literal") { - expression.kind = new Literal(data.value); - } else if (data.kind == "expression") { - expression.kind = new Expression(data.value); - } else { - expression.kind = new Unevaluated(); - } - return expression; -} - -function wrap(e, kind) { - return new Ok( - new 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 97c3fcb..0000000 --- a/build/packages/gleeunit/src/gleeunit/internal/reporting.gleam +++ /dev/null @@ -1,227 +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) <> " tests, no failures" - io.println(green(message)) - 0 - } - State(skipped: 0, ..) -> { - let message = - "\n" - <> int.to_string(state.passed) - <> " tests, " - <> int.to_string(state.failed) - <> " failures" - io.println(red(message)) - 0 - } - State(failed: 0, ..) -> { - let message = - "\n" - <> int.to_string(state.passed) - <> " tests, 0 failures, " - <> int.to_string(state.skipped) - <> " skipped" - io.println(yellow(message)) - 1 - } - State(..) -> { - let message = - "\n" - <> int.to_string(state.passed) - <> " tests, " - <> int.to_string(state.failed) - <> " failures, " - <> " 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) -} - -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 11cd82b..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 f6dcb97..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]). --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 3801515..0000000 --- a/build/packages/gleeunit/src/gleeunit@internal@reporting.erl +++ /dev/null @@ -1,328 +0,0 @@ --module(gleeunit@internal@reporting). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). --define(FILEPATH, "src/gleeunit/internal/reporting.gleam"). --export([new_state/0, test_skipped/3, test_passed/1, finished/1, 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", 194). -?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", 198). -?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", 178). -?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", 202). -?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", 189). -?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", 206). -?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", 64). -?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", 210). -?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, - " tests, 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, - " tests, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures"/utf8>>, - gleam_stdlib:println(red(Message@1)), - 0; - - {state, _, 0, _} -> - Message@2 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " tests, 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, - " tests, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures, "/utf8>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(red(Message@3)), - 1 - end. - --file("src/gleeunit/internal/reporting.gleam", 214). -?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", 87). -?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", 170). -?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", 166). -?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", 147). -?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", 100). -?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", 69). -?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 736f31a..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]). --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(DRY, DRY) -> 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(DRZ, DRZ) -> 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, DSA} | {error, any()}) -> DSA. -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, DSF}) -> DSF. -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(DSI)) -> DSI. -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 29b9553..0000000 --- a/build/packages/gleeunit/src/gleeunit_ffi.erl +++ /dev/null @@ -1,14 +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 eunit:test({timeout, 60, Tests}, Options) of - ok -> {ok, nil}; - error -> {error, nil}; - {error, Term} -> {error, Term} - end. diff --git a/build/packages/gleeunit/src/gleeunit_ffi.mjs b/build/packages/gleeunit/src/gleeunit_ffi.mjs deleted file mode 100644 index ea7e301..0000000 --- a/build/packages/gleeunit/src/gleeunit_ffi.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import { readFileSync } from "node:fs"; -import { Ok, Error as GleamError } from "./gleam.mjs"; -import * as reporting from "./gleeunit/internal/reporting.mjs"; - -export function read_file(path) { - try { - return new Ok(readFileSync(path)); - } catch { - return new GleamError(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 2883008..0000000 --- a/build/packages/gleeunit/src/gleeunit_progress.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters - --module(gleeunit_progress). --behaviour(eunit_listener). --define(NOTEST, true). --include_lib("eunit/include/eunit.hrl"). - -%% 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 c5930d4..0000000 --- a/build/packages/packages.toml +++ /dev/null @@ -1,3 +0,0 @@ -[packages] -gleeunit = "1.6.0" -gleam_stdlib = "0.62.0" diff --git a/config/dev.exs b/config/dev.exs index c1d1a2c..cd171d8 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -20,7 +20,8 @@ config :aprsme, Aprsme.Repo, timeout: 30_000, queue_target: 100, queue_interval: 1_000, - log: :debug, + # log: :debug, + log: false, types: Aprsme.PostgresTypes, # Use unnamed prepared statements for better development flexibility prepare: :unnamed, diff --git a/lib/aprsme_web/components/info_map_component.ex b/lib/aprsme_web/components/info_map_component.ex new file mode 100644 index 0000000..1ced708 --- /dev/null +++ b/lib/aprsme_web/components/info_map_component.ex @@ -0,0 +1,37 @@ +defmodule AprsmeWeb.Components.InfoMapComponent do + @moduledoc """ + A simple map component for showing a single station's location on the info page. + """ + use Phoenix.Component + + @doc """ + Renders a small map showing a single station's position. + """ + attr :id, :string, default: "info-map" + attr :lat, :float, required: true + attr :lon, :float, required: true + attr :callsign, :string, required: true + attr :symbol_html, :string, default: nil + attr :height, :string, default: "300px" + attr :zoom, :integer, default: 13 + + def info_map(assigns) do + ~H""" +
+
+ +
+
+ """ + end +end diff --git a/lib/aprsme_web/live/info_live/show.ex b/lib/aprsme_web/live/info_live/show.ex index 95b17a7..bf4239b 100644 --- a/lib/aprsme_web/live/info_live/show.ex +++ b/lib/aprsme_web/live/info_live/show.ex @@ -3,6 +3,8 @@ defmodule AprsmeWeb.InfoLive.Show do use AprsmeWeb, :live_view use Gettext, backend: AprsmeWeb.Gettext + import AprsmeWeb.Components.InfoMapComponent + alias Aprsme.Callsign alias Aprsme.EncodingUtils alias Aprsme.Packets diff --git a/lib/aprsme_web/live/info_live/show.html.heex b/lib/aprsme_web/live/info_live/show.html.heex index 3ecee2f..4fdc6ae 100644 --- a/lib/aprsme_web/live/info_live/show.html.heex +++ b/lib/aprsme_web/live/info_live/show.html.heex @@ -9,7 +9,8 @@ src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="" -> +> +
@@ -184,8 +185,8 @@
- - + + <%= if @packet && @packet.lat && @packet.lon do %>
@@ -204,193 +205,205 @@
<% end %> - +
-
-
-
- - - +
+
+
+ + + +
+
+

{gettext("Device Information")}

+
-
-

{gettext("Device Information")}

-
-
-
-
-
{gettext("Device")}
-
- <%= if @packet.device_model || @packet.device_vendor do %> - {[ - @packet.device_model, - @packet.device_vendor, - @packet.device_contact - ] - |> Enum.reject(&is_nil/1) - |> Enum.join(" ")} - <%= if @packet.device_class do %> - ({@packet.device_class}) +
+
+
{gettext("Device")}
+
+ <%= if @packet.device_model || @packet.device_vendor do %> + {[ + @packet.device_model, + @packet.device_vendor, + @packet.device_contact + ] + |> Enum.reject(&is_nil/1) + |> Enum.join(" ")} + <%= if @packet.device_class do %> + ({@packet.device_class}) + <% end %> + <% else %> + + {@packet.device_identifier || gettext("Unknown")} + <% end %> - <% else %> - - {@packet.device_identifier || gettext("Unknown")} - - <% end %> -
-
-
-
{gettext("Path")}
-
- <% path_elements = parse_path_with_links(@packet.path) %> - <%= for {{type, content, display}, index} <- Enum.with_index(path_elements) do %> - <%= case type do %> - <% :link -> %> - <.link navigate={~p"/info/#{content}"} class="link link-primary"> - {display} - - <% :text -> %> - {content} - <% end %> - <%= if index < length(path_elements) - 1 do %> - , - <% end %> - <% end %> -
-
- <%= if @packet.path && @packet.path != "" do %> -
-
{gettext("Decoded Path")}
-
- {decode_aprs_path(@packet.path)}
- <% end %> -
-
{gettext("Raw Packet")}
-
- <%= if is_binary(@packet.raw_packet) do %> - {Aprsme.EncodingUtils.sanitize_string(@packet.raw_packet)} - <% else %> - {@packet.raw_packet || ""} - <% end %> -
-
-
-
-
- - - <%= if length(@other_ssids) > 0 do %> -
-
-
-
- - - -
-
-

{gettext("Other SSIDs")}

-
-
-
- - - - - - - - - - <%= for ssid_info <- @other_ssids do %> - - - - - - <% end %> - -
- {gettext("Callsign")} - - {gettext("Distance & Direction")} - - {gettext("Last Heard")} -
-
- <.link navigate={~p"/info/#{ssid_info.callsign}"} class="link link-primary"> - {ssid_info.callsign} +
+
{gettext("Path")}
+
+ <% path_elements = parse_path_with_links(@packet.path) %> + <%= for {{type, content, display}, index} <- Enum.with_index(path_elements) do %> + <%= case type do %> + <% :link -> %> + <.link navigate={~p"/info/#{content}"} class="link link-primary"> + {display} - <%= if ssid_info.packet do %> - <% {symbol_table, symbol_code} = - AprsmeWeb.AprsSymbol.extract_from_packet(ssid_info.packet) %> - <% display_symbol = - if symbol_table && String.match?(symbol_table, ~r/^[A-Z0-9]$/), - do: symbol_table, - else: - "#{AprsmeWeb.AprsSymbol.normalize_symbol_table(symbol_table)}#{AprsmeWeb.AprsSymbol.normalize_symbol_code(symbol_code)}" %> -
- {render_symbol_html(ssid_info.packet)} -
- <% end %> -
-
- <%= if ssid_info.packet && ssid_info.packet.lat && ssid_info.packet.lon && @packet && @packet.lat && @packet.lon do %> - <% dist = - haversine( - @packet.lat, - @packet.lon, - ssid_info.packet.lat, - ssid_info.packet.lon - ) %> - <% course = - calculate_course( - @packet.lat, - @packet.lon, - ssid_info.packet.lat, - ssid_info.packet.lon - ) %> - <% locale = Map.get(assigns, :locale, "en") %> - <%= if course do %> - {format_distance(dist, locale)} @ {Float.round(course, 0)}° - <% else %> - {format_distance(dist, locale)} - <% end %> - <% else %> - - - <% end %> - - <%= if ssid_info.last_heard do %> - - {ssid_info.last_heard.time_ago} - - <% else %> - {gettext("Unknown")} - <% end %> -
+ <% :text -> %> + {content} + <% end %> + <%= if index < length(path_elements) - 1 do %> + , + <% end %> + <% end %> + +
+ <%= if @packet.path && @packet.path != "" do %> +
+
{gettext("Decoded Path")}
+
+ {decode_aprs_path(@packet.path)} +
+
+ <% end %> +
+
{gettext("Raw Packet")}
+
+ <%= if is_binary(@packet.raw_packet) do %> + {Aprsme.EncodingUtils.sanitize_string(@packet.raw_packet)} + <% else %> + {@packet.raw_packet || ""} + <% end %> +
+
+
+ + + <%= if length(@other_ssids) > 0 do %> +
+
+
+
+ + + +
+
+

{gettext("Other SSIDs")}

+
+
+
+ + + + + + + + + + <%= for ssid_info <- @other_ssids do %> + + + + + + <% end %> + +
+ {gettext("Callsign")} + + {gettext("Distance & Direction")} + + {gettext("Last Heard")} +
+
+ <.link navigate={~p"/info/#{ssid_info.callsign}"} class="link link-primary"> + {ssid_info.callsign} + + <%= if ssid_info.packet do %> + <% {symbol_table, symbol_code} = + AprsmeWeb.AprsSymbol.extract_from_packet(ssid_info.packet) %> + <% display_symbol = + if symbol_table && String.match?(symbol_table, ~r/^[A-Z0-9]$/), + do: symbol_table, + else: + "#{AprsmeWeb.AprsSymbol.normalize_symbol_table(symbol_table)}#{AprsmeWeb.AprsSymbol.normalize_symbol_code(symbol_code)}" %> +
+ {render_symbol_html(ssid_info.packet)} +
+ <% end %> +
+
+ <%= if ssid_info.packet && ssid_info.packet.lat && ssid_info.packet.lon && @packet && @packet.lat && @packet.lon do %> + <% dist = + haversine( + @packet.lat, + @packet.lon, + ssid_info.packet.lat, + ssid_info.packet.lon + ) %> + <% course = + calculate_course( + @packet.lat, + @packet.lon, + ssid_info.packet.lat, + ssid_info.packet.lon + ) %> + <% locale = Map.get(assigns, :locale, "en") %> + <%= if course do %> + {format_distance(dist, locale)} @ {Float.round(course, 0)}° + <% else %> + {format_distance(dist, locale)} + <% end %> + <% else %> + - + <% end %> + + <%= if ssid_info.last_heard do %> + + {ssid_info.last_heard.time_ago} + + <% else %> + {gettext("Unknown")} + <% end %> +
+
+
+
+ <% else %> + +
+ <% end %>
- <% else %> - -
- <% end %>
-
- +