From b5535d14f17fb5bd5f70598bc92e238182477ae4 Mon Sep 17 00:00:00 2001 From: Louis Pilfold Date: Sun, 19 Dec 2021 13:57:26 +0000 Subject: Flip/flop --- CHANGELOG.md | 1 + bin/test.sh | 2 +- src/gleam/base.gleam | 4 +- src/gleam/bit_string.gleam | 10 +- src/gleam/dynamic.gleam | 32 +-- src/gleam/float.gleam | 12 +- src/gleam/int.gleam | 8 +- src/gleam/io.gleam | 6 +- src/gleam/map.gleam | 12 +- src/gleam/regex.gleam | 8 +- src/gleam/string.gleam | 30 +-- src/gleam/string_builder.gleam | 26 +- src/gleam/uri.gleam | 6 +- src/gleam_stdlib.js | 569 ----------------------------------------- src/gleam_stdlib.mjs | 569 +++++++++++++++++++++++++++++++++++++++++ test/gleam/should.gleam | 2 +- 16 files changed, 649 insertions(+), 648 deletions(-) delete mode 100644 src/gleam_stdlib.js create mode 100644 src/gleam_stdlib.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b22c34..2aabec5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - The `function` module gains the `constant` function. +- The internal `gleam_stdlib.js` module has been renamed to `gleam_stdlib.mjs`. ## v0.18.0 - 2021-11-23 ## v0.18.0-rc1 - 2021-11-23 diff --git a/bin/test.sh b/bin/test.sh index 777c50b..97bd34d 100755 --- a/bin/test.sh +++ b/bin/test.sh @@ -3,5 +3,5 @@ set -eu OUT=gen/javascript rm -fr $OUT gleam compile-package --name gleam_stdlib --target javascript --src src --test test --out $OUT -cp src/*.js $OUT/ +cp src/*.*js $OUT/ node bin/run-tests.js diff --git a/src/gleam/base.gleam b/src/gleam/base.gleam index 5134cc0..7ec1558 100644 --- a/src/gleam/base.gleam +++ b/src/gleam/base.gleam @@ -18,7 +18,7 @@ if erlang { if javascript { external fn do_encode64(BitString) -> String = - "../gleam_stdlib.js" "encode64" + "../gleam_stdlib.mjs" "encode64" } /// Decodes a base 64 encoded string into a `BitString`. @@ -38,7 +38,7 @@ if erlang { if javascript { external fn do_decode64(String) -> Result(BitString, Nil) = - "../gleam_stdlib.js" "decode64" + "../gleam_stdlib.mjs" "decode64" } /// Encodes a `BitString` into a base 64 encoded string with URL and filename safe alphabet. diff --git a/src/gleam/bit_string.gleam b/src/gleam/bit_string.gleam index a30b40d..eee006c 100644 --- a/src/gleam/bit_string.gleam +++ b/src/gleam/bit_string.gleam @@ -15,7 +15,7 @@ if erlang { if javascript { external fn do_from_string(String) -> BitString = - "../gleam_stdlib.js" "bit_string_from_string" + "../gleam_stdlib.mjs" "bit_string_from_string" } /// Returns an integer which is the number of bytes in the bit string. @@ -31,7 +31,7 @@ if erlang { if javascript { external fn do_byte_size(BitString) -> Int = - "../gleam_stdlib.js" "length" + "../gleam_stdlib.mjs" "length" } /// Creates a new bit string by joining two binaries. @@ -76,7 +76,7 @@ if javascript { position: Int, length: Int, ) -> Result(BitString, Nil) = - "../gleam_stdlib.js" "bit_string_slice" + "../gleam_stdlib.mjs" "bit_string_slice" } /// Tests to see whether a bit string is valid UTF-8. @@ -126,7 +126,7 @@ if erlang { if javascript { external fn do_to_string(BitString) -> Result(String, Nil) = - "../gleam_stdlib.js" "bit_string_to_string" + "../gleam_stdlib.mjs" "bit_string_to_string" } /// Creates a new bit string by joining multiple binaries. @@ -147,5 +147,5 @@ if erlang { if javascript { external fn do_concat(List(BitString)) -> BitString = - "../gleam_stdlib.js" "bit_string_concat" + "../gleam_stdlib.mjs" "bit_string_concat" } diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index d48bd24..a3c43d8 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -34,7 +34,7 @@ if erlang { if javascript { external fn do_from(anything) -> Dynamic = - "../gleam_stdlib.js" "identity" + "../gleam_stdlib.mjs" "identity" } /// Unsafely casts a Dynamic value into any other type. @@ -55,7 +55,7 @@ if erlang { if javascript { external fn do_unsafe_coerce(Dynamic) -> a = - "../gleam_stdlib.js" "identity" + "../gleam_stdlib.mjs" "identity" } /// Checks to see whether a `Dynamic` value is a bit_string, and returns that bit string if @@ -80,7 +80,7 @@ if erlang { if javascript { external fn decode_bit_string(Dynamic) -> Result(BitString, DecodeError) = - "../gleam_stdlib.js" "decode_bit_string" + "../gleam_stdlib.mjs" "decode_bit_string" } /// Checks to see whether a `Dynamic` value is a string, and returns that string if @@ -113,7 +113,7 @@ if erlang { if javascript { external fn decode_string(Dynamic) -> Result(String, DecodeError) = - "../gleam_stdlib.js" "decode_string" + "../gleam_stdlib.mjs" "decode_string" } /// Return a string indicating the type of the dynamic value. @@ -134,7 +134,7 @@ if erlang { if javascript { external fn do_classify(Dynamic) -> String = - "../gleam_stdlib.js" "classify_dynamic" + "../gleam_stdlib.mjs" "classify_dynamic" } /// Checks to see whether a `Dynamic` value is an int, and returns that int if it @@ -159,7 +159,7 @@ if erlang { if javascript { external fn decode_int(Dynamic) -> Result(Int, DecodeError) = - "../gleam_stdlib.js" "decode_int" + "../gleam_stdlib.mjs" "decode_int" } /// Checks to see whether a `Dynamic` value is a float, and returns that float if @@ -184,7 +184,7 @@ if erlang { if javascript { external fn decode_float(Dynamic) -> Result(Float, DecodeError) = - "../gleam_stdlib.js" "decode_float" + "../gleam_stdlib.mjs" "decode_float" } /// Checks to see whether a `Dynamic` value is a bool, and returns that bool if @@ -209,7 +209,7 @@ if erlang { if javascript { external fn decode_bool(Dynamic) -> Result(Bool, DecodeError) = - "../gleam_stdlib.js" "decode_bool" + "../gleam_stdlib.mjs" "decode_bool" } /// Checks to see whether a `Dynamic` value is a list, and returns that list if it @@ -237,7 +237,7 @@ if erlang { if javascript { external fn decode_list(Dynamic) -> Result(List(Dynamic), DecodeError) = - "../gleam_stdlib.js" "decode_list" + "../gleam_stdlib.mjs" "decode_list" } /// Checks to see whether a `Dynamic` value is a result, and returns that result if @@ -267,7 +267,7 @@ if erlang { if javascript { external fn decode_result(Dynamic) -> Result(Result(a, e), DecodeError) = - "../gleam_stdlib.js" "decode_result" + "../gleam_stdlib.mjs" "decode_result" } /// Checks to see whether a `Dynamic` value is a result of a particular type, and @@ -379,7 +379,7 @@ if javascript { Dynamic, Decoder(a), ) -> Result(Option(a), DecodeError) = - "../gleam_stdlib.js" "decode_option" + "../gleam_stdlib.mjs" "decode_option" } /// Checks to see if a `Dynamic` value is a map with a specific field, and returns @@ -407,7 +407,7 @@ if erlang { if javascript { external fn decode_field(Dynamic, name) -> Result(Dynamic, DecodeError) = - "../gleam_stdlib.js" "decode_field" + "../gleam_stdlib.mjs" "decode_field" } /// Checks to see if a `Dynamic` value is a tuple large enough to have a certain @@ -487,13 +487,13 @@ if erlang { if javascript { external fn decode_tuple(Dynamic) -> Result(UnknownTuple, DecodeError) = - "../gleam_stdlib.js" "decode_tuple" + "../gleam_stdlib.mjs" "decode_tuple" external fn tuple_get(UnknownTuple, Int) -> Result(Dynamic, DecodeError) = - "../gleam_stdlib.js" "tuple_get" + "../gleam_stdlib.mjs" "tuple_get" external fn tuple_size(UnknownTuple) -> Int = - "../gleam_stdlib.js" "length" + "../gleam_stdlib.mjs" "length" } /// Checks to see if a `Dynamic` value is a 2-element tuple. @@ -840,7 +840,7 @@ if erlang { if javascript { external fn decode_map(Dynamic) -> Result(Map(Dynamic, Dynamic), DecodeError) = - "../gleam_stdlib.js" "decode_map" + "../gleam_stdlib.mjs" "decode_map" } if erlang { diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam index e714bcb..3f5399e 100644 --- a/src/gleam/float.gleam +++ b/src/gleam/float.gleam @@ -22,7 +22,7 @@ if erlang { if javascript { external fn do_parse(String) -> Result(Float, Nil) = - "../gleam_stdlib.js" "parse_float" + "../gleam_stdlib.mjs" "parse_float" } /// Returns the string representation of the provided `Float`. @@ -115,7 +115,7 @@ if erlang { if javascript { external fn do_ceiling(Float) -> Float = - "../gleam_stdlib.js" "ceiling" + "../gleam_stdlib.mjs" "ceiling" } /// Rounds the value to the next lowest whole number as a `Float`. @@ -136,7 +136,7 @@ if erlang { if javascript { external fn do_floor(Float) -> Float = - "../gleam_stdlib.js" "floor" + "../gleam_stdlib.mjs" "floor" } /// Rounds the value to the nearest whole number as an `Int`. @@ -167,7 +167,7 @@ if javascript { } external fn js_round(Float) -> Int = - "../gleam_stdlib.js" "round" + "../gleam_stdlib.mjs" "round" } /// Returns the value as an `Int`, truncating all decimal digits. @@ -188,7 +188,7 @@ if erlang { if javascript { external fn do_truncate(Float) -> Int = - "../gleam_stdlib.js" "truncate" + "../gleam_stdlib.mjs" "truncate" } /// Returns the absolute value of the input as a `Float`. @@ -230,7 +230,7 @@ if erlang { if javascript { external fn do_power(Float, Float) -> Float = - "../gleam_stdlib.js" "power" + "../gleam_stdlib.mjs" "power" } /// Returns the square root of the input as a `Float`. diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam index 756e0eb..fa794d3 100644 --- a/src/gleam/int.gleam +++ b/src/gleam/int.gleam @@ -38,7 +38,7 @@ if erlang { if javascript { external fn do_parse(String) -> Result(Int, Nil) = - "../gleam_stdlib.js" "parse_int" + "../gleam_stdlib.mjs" "parse_int" } /// Prints a given int to a string. @@ -59,7 +59,7 @@ if erlang { if javascript { external fn do_to_string(Int) -> String = - "../gleam_stdlib.js" "to_string" + "../gleam_stdlib.mjs" "to_string" } /// For use in `to_base_string` when base is outside of the allowed range. @@ -102,7 +102,7 @@ if erlang { if javascript { external fn do_to_base_string(Int, Int) -> String = - "../gleam_stdlib.js" "int_to_base_string" + "../gleam_stdlib.mjs" "int_to_base_string" } /// Prints a given int to a string using base2. @@ -173,7 +173,7 @@ if erlang { if javascript { external fn do_to_float(a: Int) -> Float = - "../gleam_stdlib.js" "identity" + "../gleam_stdlib.mjs" "identity" } /// Restricts an int between a lower and upper bound. diff --git a/src/gleam/io.gleam b/src/gleam/io.gleam index 3139e73..4b3e998 100644 --- a/src/gleam/io.gleam +++ b/src/gleam/io.gleam @@ -23,7 +23,7 @@ if erlang { if javascript { external fn do_print(String) -> Nil = - "../gleam_stdlib.js" "print" + "../gleam_stdlib.mjs" "print" } /// Writes a string to standard output, appending a newline to the end. @@ -47,7 +47,7 @@ if erlang { if javascript { external fn do_println(String) -> Nil = - "../gleam_stdlib.js" "log" + "../gleam_stdlib.mjs" "log" } /// Prints a value to standard output using Erlang syntax. @@ -85,7 +85,7 @@ if erlang { if javascript { external fn debug_print(anything) -> Nil = - "../gleam_stdlib.js" "debug" + "../gleam_stdlib.mjs" "debug" } if erlang { diff --git a/src/gleam/map.gleam b/src/gleam/map.gleam index 41decf1..ad3b184 100644 --- a/src/gleam/map.gleam +++ b/src/gleam/map.gleam @@ -42,7 +42,7 @@ if erlang { if javascript { external fn do_size(Map(k, v)) -> Int = - "../gleam_stdlib.js" "map_size" + "../gleam_stdlib.mjs" "map_size" } /// Converts the map to a list of 2-element tuples `#(key, value)`, one for @@ -69,7 +69,7 @@ if erlang { if javascript { external fn do_to_list(Map(key, value)) -> List(#(key, value)) = - "../gleam_stdlib.js" "map_to_list" + "../gleam_stdlib.mjs" "map_to_list" } /// Converts a list of 2-element tuples `#(key, value)` to a map. @@ -130,7 +130,7 @@ if erlang { if javascript { external fn do_new() -> Map(key, value) = - "../gleam_stdlib.js" "new_map" + "../gleam_stdlib.mjs" "new_map" } /// Fetches a value from a map for a given key. @@ -157,7 +157,7 @@ if erlang { if javascript { external fn do_get(Map(key, value), key) -> Result(value, Nil) = - "../gleam_stdlib.js" "map_get" + "../gleam_stdlib.mjs" "map_get" } /// Inserts a value into the map with the given key. @@ -184,7 +184,7 @@ if erlang { if javascript { external fn do_insert(key, value, Map(key, value)) -> Map(key, value) = - "../gleam_stdlib.js" "map_insert" + "../gleam_stdlib.mjs" "map_insert" } /// Updates all values in a given map by calling a given function on each key @@ -401,7 +401,7 @@ if erlang { if javascript { external fn do_delete(k, Map(k, v)) -> Map(k, v) = - "../gleam_stdlib.js" "map_remove" + "../gleam_stdlib.mjs" "map_remove" } /// Creates a new map from a given map with all the same entries except any with diff --git a/src/gleam/regex.gleam b/src/gleam/regex.gleam index 99d8dd6..79c6620 100644 --- a/src/gleam/regex.gleam +++ b/src/gleam/regex.gleam @@ -62,7 +62,7 @@ if erlang { if javascript { external fn do_compile(String, with: Options) -> Result(Regex, CompileError) = - "../gleam_stdlib.js" "compile_regex" + "../gleam_stdlib.mjs" "compile_regex" } /// Creates a new `Regex`. @@ -110,7 +110,7 @@ if erlang { if javascript { external fn do_check(Regex, String) -> Bool = - "../gleam_stdlib.js" "regex_check" + "../gleam_stdlib.mjs" "regex_check" } /// Splits a string. @@ -136,7 +136,7 @@ if javascript { } external fn js_split(String, Regex) -> List(String) = - "../gleam_stdlib.js" "split" + "../gleam_stdlib.mjs" "split" } /// Collects all matches of the regular expression. @@ -167,5 +167,5 @@ if erlang { if javascript { external fn do_scan(Regex, String) -> List(Match) = - "../gleam_stdlib.js" "regex_scan" + "../gleam_stdlib.mjs" "regex_scan" } diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam index ff41a6c..d54a0f6 100644 --- a/src/gleam/string.gleam +++ b/src/gleam/string.gleam @@ -53,7 +53,7 @@ if erlang { if javascript { external fn do_length(String) -> Int = - "../gleam_stdlib.js" "string_length" + "../gleam_stdlib.mjs" "string_length" } /// Reverses a `String`. @@ -115,7 +115,7 @@ if erlang { if javascript { external fn do_lowercase(String) -> String = - "../gleam_stdlib.js" "lowercase" + "../gleam_stdlib.mjs" "lowercase" } /// Creates a new `String` with all the graphemes in the input `String` converted to @@ -139,7 +139,7 @@ if erlang { if javascript { external fn do_uppercase(String) -> String = - "../gleam_stdlib.js" "uppercase" + "../gleam_stdlib.mjs" "uppercase" } /// Compares two `String`s to see which is "larger" by comparing their graphemes. @@ -172,7 +172,7 @@ if erlang { if javascript { external fn less_than(String, String) -> Bool = - "../gleam_stdlib.js" "less_than" + "../gleam_stdlib.mjs" "less_than" } /// Takes a substring given a start and end grapheme indexes. Negative indexes @@ -218,7 +218,7 @@ if erlang { if javascript { external fn do_slice(String, Int, Int) -> String = - "../gleam_stdlib.js" "slice_string" + "../gleam_stdlib.mjs" "slice_string" } /// Drops contents of the first `String` that occur before the second `String`. @@ -246,7 +246,7 @@ if erlang { if javascript { external fn do_crop(String, String) -> String = - "../gleam_stdlib.js" "crop_string" + "../gleam_stdlib.mjs" "crop_string" } /// Drops *n* graphemes from the left side of a `String`. @@ -307,7 +307,7 @@ if javascript { } external fn index_of(String, String) -> Int = - "../gleam_stdlib.js" "index_of" + "../gleam_stdlib.mjs" "index_of" } /// Checks whether the first `String` starts with the second one. @@ -328,7 +328,7 @@ if erlang { if javascript { external fn do_starts_with(String, String) -> Bool = - "../gleam_stdlib.js" "starts_with" + "../gleam_stdlib.mjs" "starts_with" } /// Checks whether the first `String` ends with the second one. @@ -349,7 +349,7 @@ if erlang { if javascript { external fn do_ends_with(String, String) -> Bool = - "../gleam_stdlib.js" "ends_with" + "../gleam_stdlib.mjs" "ends_with" } /// Creates a list of `String`s by splitting a given string on a given substring. @@ -405,7 +405,7 @@ if javascript { x: String, substring: String, ) -> Result(#(String, String), Nil) = - "../gleam_stdlib.js" "split_once" + "../gleam_stdlib.mjs" "split_once" } /// Creates a new `String` by joining two `String`s together. @@ -559,7 +559,7 @@ if erlang { if javascript { external fn do_trim(string: String) -> String = - "../gleam_stdlib.js" "trim" + "../gleam_stdlib.mjs" "trim" } /// Removes whitespace on the left of a `String`. @@ -581,7 +581,7 @@ if erlang { if javascript { external fn do_trim_left(string: String) -> String = - "../gleam_stdlib.js" "trim_left" + "../gleam_stdlib.mjs" "trim_left" } /// Removes whitespace on the right of a `String`. @@ -603,7 +603,7 @@ if erlang { if javascript { external fn do_trim_right(string: String) -> String = - "../gleam_stdlib.js" "trim_right" + "../gleam_stdlib.mjs" "trim_right" } /// Splits a non-empty `String` into its head and tail. This lets you @@ -627,7 +627,7 @@ if erlang { if javascript { external fn do_pop_grapheme(string: String) -> Result(#(String, String), Nil) = - "../gleam_stdlib.js" "pop_grapheme" + "../gleam_stdlib.mjs" "pop_grapheme" } /// Converts a `String` to a list of graphemes. @@ -649,7 +649,7 @@ if erlang { if javascript { external fn unsafe_int_to_utf_codepoint(Int) -> UtfCodepoint = - "../gleam_stdlib.js" "codepoint" + "../gleam_stdlib.mjs" "codepoint" } /// Converts an integer to a `UtfCodepoint`. diff --git a/src/gleam/string_builder.gleam b/src/gleam/string_builder.gleam index f1cc22a..e6562a0 100644 --- a/src/gleam/string_builder.gleam +++ b/src/gleam/string_builder.gleam @@ -62,7 +62,7 @@ if erlang { if javascript { external fn do_append(StringBuilder, StringBuilder) -> StringBuilder = - "../gleam_stdlib.js" "add" + "../gleam_stdlib.mjs" "add" } /// Converts a list of strings into a builder. @@ -80,7 +80,7 @@ if erlang { if javascript { external fn do_from_strings(List(String)) -> StringBuilder = - "../gleam_stdlib.js" "join" + "../gleam_stdlib.mjs" "join" } /// Joins a list of builders into a single builder. @@ -98,7 +98,7 @@ if erlang { if javascript { external fn do_concat(List(StringBuilder)) -> StringBuilder = - "../gleam_stdlib.js" "join" + "../gleam_stdlib.mjs" "join" } /// Converts a string into a builder. @@ -116,7 +116,7 @@ if erlang { if javascript { external fn do_from_string(String) -> StringBuilder = - "../gleam_stdlib.js" "identity" + "../gleam_stdlib.mjs" "identity" } /// Turns an `StringBuilder` into a `String` @@ -135,7 +135,7 @@ if erlang { if javascript { external fn do_to_string(StringBuilder) -> String = - "../gleam_stdlib.js" "identity" + "../gleam_stdlib.mjs" "identity" } /// Returns the size of the `StringBuilder` in bytes. @@ -151,7 +151,7 @@ if erlang { if javascript { external fn do_byte_size(StringBuilder) -> Int = - "../gleam_stdlib.js" "length" + "../gleam_stdlib.mjs" "length" } /// Creates a builder containing the textual representation of a given float. @@ -167,7 +167,7 @@ if erlang { if javascript { external fn do_from_float(Float) -> StringBuilder = - "../gleam_stdlib.js" "float_to_string" + "../gleam_stdlib.mjs" "float_to_string" } /// Converts a builder to a new builder where the contents have been @@ -184,7 +184,7 @@ if erlang { if javascript { external fn do_lowercase(StringBuilder) -> StringBuilder = - "../gleam_stdlib.js" "lowercase" + "../gleam_stdlib.mjs" "lowercase" } /// Converts a builder to a new builder where the contents have been @@ -201,7 +201,7 @@ if erlang { if javascript { external fn do_uppercase(StringBuilder) -> StringBuilder = - "../gleam_stdlib.js" "uppercase" + "../gleam_stdlib.mjs" "uppercase" } /// Converts a builder to a new builder with the contents reversed. @@ -217,7 +217,7 @@ if erlang { if javascript { external fn do_reverse(StringBuilder) -> StringBuilder = - "../gleam_stdlib.js" "string_reverse" + "../gleam_stdlib.mjs" "string_reverse" } /// Splits a builder on a given pattern into a list of builders. @@ -244,7 +244,7 @@ if javascript { builder: StringBuilder, pattern: String, ) -> List(StringBuilder) = - "../gleam_stdlib.js" "split" + "../gleam_stdlib.mjs" "split" } /// Replaces all instances of a pattern with a given string substitute. @@ -277,7 +277,7 @@ if erlang { if javascript { external fn do_replace(StringBuilder, String, String) -> StringBuilder = - "../gleam_stdlib.js" "string_replace" + "../gleam_stdlib.mjs" "string_replace" } /// Compares two builders to determine if they have the same textual content. @@ -306,7 +306,7 @@ if erlang { if javascript { external fn do_is_equal(StringBuilder, StringBuilder) -> Bool = - "../gleam_stdlib.js" "equal" + "../gleam_stdlib.mjs" "equal" } /// Inspects a builder to determine if it is equivalent to an empty string. diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam index 3b1c731..514a7ff 100644 --- a/src/gleam/uri.gleam +++ b/src/gleam/uri.gleam @@ -206,7 +206,7 @@ if erlang { if javascript { external fn do_parse_query(String) -> Result(List(#(String, String)), Nil) = - "../gleam_stdlib.js" "parse_query" + "../gleam_stdlib.mjs" "parse_query" } /// Encodes a list of key value pairs as a URI query string. @@ -258,7 +258,7 @@ if erlang { if javascript { external fn do_percent_encode(String) -> String = - "../gleam_stdlib.js" "percent_encode" + "../gleam_stdlib.mjs" "percent_encode" } /// Decodes a percent encoded string. @@ -282,7 +282,7 @@ if erlang { if javascript { external fn do_percent_decode(String) -> Result(String, Nil) = - "../gleam_stdlib.js" "percent_decode" + "../gleam_stdlib.mjs" "percent_decode" } fn do_remove_dot_segments( diff --git a/src/gleam_stdlib.js b/src/gleam_stdlib.js deleted file mode 100644 index 96fa4f1..0000000 --- a/src/gleam_stdlib.js +++ /dev/null @@ -1,569 +0,0 @@ -import { - BitString, - Error, - List, - Ok, - Result, - UtfCodepoint, - inspect, - stringBits, - toBitString, -} from "./gleam.js"; -import { - CompileError as RegexCompileError, - Match as RegexMatch, -} from "./gleam/regex.js"; -import { DecodeError } from "./gleam/dynamic.js"; -import { Some, None } from "./gleam/option.js"; - -const HASHCODE_CACHE = new WeakMap(); - -const Nil = undefined; - -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+)$/.test(value)) { - return new Ok(parseFloat(value)); - } else { - return new Error(Nil); - } -} - -export function to_string(term) { - return term.toString(); -} - -export function float_to_string(float) { - let string = float.toString(); - if (string.indexOf(".") >= 0) { - return string; - } else { - return string + ".0"; - } -} - -export function int_to_base_string(int, base) { - return int.toString(base).toUpperCase(); -} - -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) { - let iterator = graphemes_iterator(string); - if (iterator) { - let i = 0; - for (let _ of iterator) { - i++; - } - return i; - } else { - return string.match(/./gu).length; - } -} - -function graphemes_iterator(string) { - if (Intl && Intl.Segmenter) { - return new Intl.Segmenter("en-gb").segment(string)[Symbol.iterator](); - } -} - -export function pop_grapheme(string) { - let first; - let iterator = graphemes_iterator(string); - if (iterator) { - first = iterator.next().value?.segment; - } else { - first = string.match(/./u)?.[0]; - } - if (first) { - return new Ok([first, string.slice(first.length)]); - } else { - return new Error(Nil); - } -} - -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 equal(a, b) { - return a === b; -} - -export function split(xs, pattern) { - return List.fromArray(xs.split(pattern)); -} - -export function join(xs) { - return xs.toArray().join(""); -} - -export function length(data) { - return data.length; -} - -export function slice_string(string, from, length) { - return string.slice(from, from + length); -} - -export function crop_string(string, substring) { - return string.substring(string.indexOf(substring)); -} - -export function index_of(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) { - let index = haystack.indexOf(needle); - if (index >= 0) { - let before = haystack.slice(0, index); - let after = haystack.slice(index + needle.length); - return new Ok([before, after]); - } else { - return new Error(Nil); - } -} - -export function trim(string) { - return string.trim(); -} - -export function trim_left(string) { - return string.trimLeft(); -} - -export function trim_right(string) { - return string.trimRight(); -} - -export function bit_string_from_string(string) { - return new toBitString([stringBits(string)]); -} - -export function bit_string_concat(bit_strings) { - return toBitString(bit_strings.toArray().map((b) => b.buffer)); -} - -export function log(term) { - console.log(term); -} - -export function debug(term) { - console.log(inspect(term)); -} - -export function crash(message) { - throw new globalThis.Error(message); -} - -export function bit_string_to_string(bit_string) { - try { - let decoder = new TextDecoder("utf-8", { fatal: true }); - return new Ok(decoder.decode(bit_string.buffer)); - } catch (_error) { - return new Error(undefined); - } -} - -export function print(string) { - if (typeof process === "object") { - process.stdout.write(string); // We can write without a trailing newline - } else { - console.log(string); // We're in a browser. Newlines are mandated - } -} - -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) { - return Math.pow(base, exponent); -} - -export function bit_string_slice(bits, position, length) { - let start = Math.min(position, position + length); - let end = Math.max(position, position + length); - if (start < 0 || end > bits.length) return new Error(Nil); - let buffer = new Uint8Array(bits.buffer.buffer, start, Math.abs(length)); - return new Ok(new BitString(buffer)); -} - -export function codepoint(int) { - return new UtfCodepoint(int); -} - -export function regex_check(regex, string) { - return regex.test(string); -} - -export function compile_regex(pattern, options) { - try { - let flags = "gu"; - if (options.case_insensitive) flags += "i"; - if (options.multi_line) flags += "m"; - return new Ok(new RegExp(pattern, flags)); - } catch (error) { - let number = (error.columnNumber || 0) | 0; - return new Error(new RegexCompileError(error.message, number)); - } -} - -export function regex_scan(regex, string) { - let matches = Array.from(string.matchAll(regex)).map((match) => { - let content = match.shift(); - let submatches = match.map((x) => (x ? new Some(x) : new None())); - return new RegexMatch(content, List.fromArray(submatches)); - }); - return List.fromArray(matches); -} - -class Map { - static #hashcode_cache = new WeakMap(); - - static hash(value) { - let existing = this.#hashcode_cache.get(value); - if (existing) { - return existing; - } else if (value instanceof Object) { - let hashcode = JSON.stringify(value); - HASHCODE_CACHE.set(value, hashcode); - return hashcode; - } else { - return value.toString(); - } - } - - constructor() { - this.entries = new globalThis.Map(); - } - - get size() { - return this.entries.size; - } - - inspect() { - let entries = [...this.entries.values()] - .map((pair) => inspect(pair)) - .join(", "); - return `map.from_list([${entries}])`; - } - - copy() { - let map = new Map(); - map.entries = new globalThis.Map(this.entries); - return map; - } - - toList() { - return List.fromArray([...this.entries.values()]); - } - - insert(k, v) { - let map = this.copy(); - map.entries.set(Map.hash(k), [k, v]); - return map; - } - - delete(k) { - let map = this.copy(); - map.entries.delete(Map.hash(k)); - return map; - } - - get(key) { - let code = Map.hash(key); - if (this.entries.has(code)) { - return new Ok(this.entries.get(code)[1]); - } else { - return new Error(Nil); - } - } -} - -export function new_map() { - return new Map(); -} - -export function map_size(map) { - return map.size; -} - -export function map_to_list(map) { - return map.toList(); -} - -export function map_remove(k, map) { - return map.delete(k); -} - -export function map_get(map, key) { - return map.get(key); -} - -export function map_insert(key, value, map) { - return map.insert(key, value); -} - -function unsafe_percent_decode(string) { - return decodeURIComponent((string || "").replace("+", " ")); -} - -export function percent_decode(string) { - try { - return new Ok(unsafe_percent_decode(string)); - } catch (error) { - return new Error(Nil); - } -} - -export function percent_encode(string) { - return encodeURIComponent(string); -} - -export function parse_query(query) { - try { - let pairs = []; - for (let section of query.split("&")) { - let [key, value] = section.split("="); - if (!key) continue; - pairs.push([unsafe_percent_decode(key), unsafe_percent_decode(value)]); - } - return new Ok(List.fromArray(pairs)); - } catch (error) { - return new Error(Nil); - } -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -export function encode64(bit_string) { - let aBytes = bit_string.buffer; - let nMod3 = 2, - sB64Enc = ""; - - for (let nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { - nMod3 = nIdx % 3; - if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) { - sB64Enc += "\r\n"; - } - nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24); - if (nMod3 === 2 || aBytes.length - nIdx === 1) { - sB64Enc += String.fromCharCode( - uint6ToB64((nUint24 >>> 18) & 63), - uint6ToB64((nUint24 >>> 12) & 63), - uint6ToB64((nUint24 >>> 6) & 63), - uint6ToB64(nUint24 & 63) - ); - nUint24 = 0; - } - } - - return ( - sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + - (nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") - ); -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function uint6ToB64(nUint6) { - return nUint6 < 26 - ? nUint6 + 65 - : nUint6 < 52 - ? nUint6 + 71 - : nUint6 < 62 - ? nUint6 - 4 - : nUint6 === 62 - ? 43 - : nUint6 === 63 - ? 47 - : 65; -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64ToUint6(nChr) { - return nChr > 64 && nChr < 91 - ? nChr - 65 - : nChr > 96 && nChr < 123 - ? nChr - 71 - : nChr > 47 && nChr < 58 - ? nChr + 4 - : nChr === 43 - ? 62 - : nChr === 47 - ? 63 - : 0; -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -export function decode64(sBase64) { - if (sBase64.match(/[^A-Za-z0-9\+\/=]/g)) return new Error(Nil); - let sB64Enc = sBase64.replace(/=/g, ""); - let nInLen = sB64Enc.length; - let nOutLen = (nInLen * 3 + 1) >> 2; - let taBytes = new Uint8Array(nOutLen); - - for ( - let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; - nInIdx < nInLen; - nInIdx++ - ) { - nMod4 = nInIdx & 3; - nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4)); - if (nMod4 === 3 || nInLen - nInIdx === 1) { - for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { - taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255; - } - nUint24 = 0; - } - } - - return new Ok(new BitString(taBytes)); -} - -export function classify_dynamic(data) { - if (typeof data === "string") { - return "String"; - } else if (Result.isResult(data)) { - return "Result"; - } else if (List.isList(data)) { - return "List"; - } else if (Number.isInteger(data)) { - return "Int"; - } else if (Array.isArray(data)) { - return `Tuple of ${data.length} elements`; - } else if (BitString.isBitString(data)) { - return "BitString"; - } else if (data instanceof Map) { - return "Map"; - } else if (typeof data === "number") { - return "Float"; - } else { - let type = typeof data; - return type.charAt(0).toUpperCase() + type.slice(1); - } -} - -function decoder_error(expected, got) { - return new Error(new DecodeError(expected, classify_dynamic(got))); -} - -export function decode_string(data) { - return typeof data === "string" - ? new Ok(data) - : decoder_error("String", data); -} - -export function decode_int(data) { - return Number.isInteger(data) ? new Ok(data) : decoder_error("Int", data); -} - -export function decode_float(data) { - return typeof data === "number" ? new Ok(data) : decoder_error("Float", data); -} - -export function decode_bool(data) { - return typeof data === "boolean" ? new Ok(data) : decoder_error("Bool", data); -} - -export function decode_bit_string(data) { - return BitString.isBitString(data) - ? new Ok(data) - : decoder_error("BitString", data); -} - -export function decode_tuple(data) { - return Array.isArray(data) ? new Ok(data) : decoder_error("Tuple", data); -} - -export function tuple_get(data, index) { - return index >= 0 && data.length > index - ? new Ok(data[index]) - : new Error(Nil); -} - -export function decode_list(data) { - return List.isList(data) ? new Ok(data) : decoder_error("List", data); -} - -export function decode_result(data) { - return Result.isResult(data) ? new Ok(data) : decoder_error("Result", data); -} - -export function decode_map(data) { - return data instanceof Map ? new Ok(data) : decoder_error("Map", data); -} - -export function decode_option(data, decoder) { - if (data === null || data === undefined || data instanceof None) - return new Ok(new None()); - if (data instanceof Some) data = data[0]; - let result = decoder(data); - if (result.isOk()) { - return new Ok(new Some(result[0])); - } else { - return result; - } -} - -export function decode_field(value, name) { - let error = () => decoder_error(`Value with field ${inspect(name)}`, value); - if (value instanceof Map) { - let entry = value.get(name); - return entry.isOk() ? entry : error(); - } - try { - return name in value ? new Ok(value[name]) : error(); - } catch { - return error(); - } -} diff --git a/src/gleam_stdlib.mjs b/src/gleam_stdlib.mjs new file mode 100644 index 0000000..96fa4f1 --- /dev/null +++ b/src/gleam_stdlib.mjs @@ -0,0 +1,569 @@ +import { + BitString, + Error, + List, + Ok, + Result, + UtfCodepoint, + inspect, + stringBits, + toBitString, +} from "./gleam.js"; +import { + CompileError as RegexCompileError, + Match as RegexMatch, +} from "./gleam/regex.js"; +import { DecodeError } from "./gleam/dynamic.js"; +import { Some, None } from "./gleam/option.js"; + +const HASHCODE_CACHE = new WeakMap(); + +const Nil = undefined; + +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+)$/.test(value)) { + return new Ok(parseFloat(value)); + } else { + return new Error(Nil); + } +} + +export function to_string(term) { + return term.toString(); +} + +export function float_to_string(float) { + let string = float.toString(); + if (string.indexOf(".") >= 0) { + return string; + } else { + return string + ".0"; + } +} + +export function int_to_base_string(int, base) { + return int.toString(base).toUpperCase(); +} + +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) { + let iterator = graphemes_iterator(string); + if (iterator) { + let i = 0; + for (let _ of iterator) { + i++; + } + return i; + } else { + return string.match(/./gu).length; + } +} + +function graphemes_iterator(string) { + if (Intl && Intl.Segmenter) { + return new Intl.Segmenter("en-gb").segment(string)[Symbol.iterator](); + } +} + +export function pop_grapheme(string) { + let first; + let iterator = graphemes_iterator(string); + if (iterator) { + first = iterator.next().value?.segment; + } else { + first = string.match(/./u)?.[0]; + } + if (first) { + return new Ok([first, string.slice(first.length)]); + } else { + return new Error(Nil); + } +} + +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 equal(a, b) { + return a === b; +} + +export function split(xs, pattern) { + return List.fromArray(xs.split(pattern)); +} + +export function join(xs) { + return xs.toArray().join(""); +} + +export function length(data) { + return data.length; +} + +export function slice_string(string, from, length) { + return string.slice(from, from + length); +} + +export function crop_string(string, substring) { + return string.substring(string.indexOf(substring)); +} + +export function index_of(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) { + let index = haystack.indexOf(needle); + if (index >= 0) { + let before = haystack.slice(0, index); + let after = haystack.slice(index + needle.length); + return new Ok([before, after]); + } else { + return new Error(Nil); + } +} + +export function trim(string) { + return string.trim(); +} + +export function trim_left(string) { + return string.trimLeft(); +} + +export function trim_right(string) { + return string.trimRight(); +} + +export function bit_string_from_string(string) { + return new toBitString([stringBits(string)]); +} + +export function bit_string_concat(bit_strings) { + return toBitString(bit_strings.toArray().map((b) => b.buffer)); +} + +export function log(term) { + console.log(term); +} + +export function debug(term) { + console.log(inspect(term)); +} + +export function crash(message) { + throw new globalThis.Error(message); +} + +export function bit_string_to_string(bit_string) { + try { + let decoder = new TextDecoder("utf-8", { fatal: true }); + return new Ok(decoder.decode(bit_string.buffer)); + } catch (_error) { + return new Error(undefined); + } +} + +export function print(string) { + if (typeof process === "object") { + process.stdout.write(string); // We can write without a trailing newline + } else { + console.log(string); // We're in a browser. Newlines are mandated + } +} + +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) { + return Math.pow(base, exponent); +} + +export function bit_string_slice(bits, position, length) { + let start = Math.min(position, position + length); + let end = Math.max(position, position + length); + if (start < 0 || end > bits.length) return new Error(Nil); + let buffer = new Uint8Array(bits.buffer.buffer, start, Math.abs(length)); + return new Ok(new BitString(buffer)); +} + +export function codepoint(int) { + return new UtfCodepoint(int); +} + +export function regex_check(regex, string) { + return regex.test(string); +} + +export function compile_regex(pattern, options) { + try { + let flags = "gu"; + if (options.case_insensitive) flags += "i"; + if (options.multi_line) flags += "m"; + return new Ok(new RegExp(pattern, flags)); + } catch (error) { + let number = (error.columnNumber || 0) | 0; + return new Error(new RegexCompileError(error.message, number)); + } +} + +export function regex_scan(regex, string) { + let matches = Array.from(string.matchAll(regex)).map((match) => { + let content = match.shift(); + let submatches = match.map((x) => (x ? new Some(x) : new None())); + return new RegexMatch(content, List.fromArray(submatches)); + }); + return List.fromArray(matches); +} + +class Map { + static #hashcode_cache = new WeakMap(); + + static hash(value) { + let existing = this.#hashcode_cache.get(value); + if (existing) { + return existing; + } else if (value instanceof Object) { + let hashcode = JSON.stringify(value); + HASHCODE_CACHE.set(value, hashcode); + return hashcode; + } else { + return value.toString(); + } + } + + constructor() { + this.entries = new globalThis.Map(); + } + + get size() { + return this.entries.size; + } + + inspect() { + let entries = [...this.entries.values()] + .map((pair) => inspect(pair)) + .join(", "); + return `map.from_list([${entries}])`; + } + + copy() { + let map = new Map(); + map.entries = new globalThis.Map(this.entries); + return map; + } + + toList() { + return List.fromArray([...this.entries.values()]); + } + + insert(k, v) { + let map = this.copy(); + map.entries.set(Map.hash(k), [k, v]); + return map; + } + + delete(k) { + let map = this.copy(); + map.entries.delete(Map.hash(k)); + return map; + } + + get(key) { + let code = Map.hash(key); + if (this.entries.has(code)) { + return new Ok(this.entries.get(code)[1]); + } else { + return new Error(Nil); + } + } +} + +export function new_map() { + return new Map(); +} + +export function map_size(map) { + return map.size; +} + +export function map_to_list(map) { + return map.toList(); +} + +export function map_remove(k, map) { + return map.delete(k); +} + +export function map_get(map, key) { + return map.get(key); +} + +export function map_insert(key, value, map) { + return map.insert(key, value); +} + +function unsafe_percent_decode(string) { + return decodeURIComponent((string || "").replace("+", " ")); +} + +export function percent_decode(string) { + try { + return new Ok(unsafe_percent_decode(string)); + } catch (error) { + return new Error(Nil); + } +} + +export function percent_encode(string) { + return encodeURIComponent(string); +} + +export function parse_query(query) { + try { + let pairs = []; + for (let section of query.split("&")) { + let [key, value] = section.split("="); + if (!key) continue; + pairs.push([unsafe_percent_decode(key), unsafe_percent_decode(value)]); + } + return new Ok(List.fromArray(pairs)); + } catch (error) { + return new Error(Nil); + } +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function encode64(bit_string) { + let aBytes = bit_string.buffer; + let nMod3 = 2, + sB64Enc = ""; + + for (let nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { + nMod3 = nIdx % 3; + if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) { + sB64Enc += "\r\n"; + } + nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24); + if (nMod3 === 2 || aBytes.length - nIdx === 1) { + sB64Enc += String.fromCharCode( + uint6ToB64((nUint24 >>> 18) & 63), + uint6ToB64((nUint24 >>> 12) & 63), + uint6ToB64((nUint24 >>> 6) & 63), + uint6ToB64(nUint24 & 63) + ); + nUint24 = 0; + } + } + + return ( + sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + + (nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") + ); +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function uint6ToB64(nUint6) { + return nUint6 < 26 + ? nUint6 + 65 + : nUint6 < 52 + ? nUint6 + 71 + : nUint6 < 62 + ? nUint6 - 4 + : nUint6 === 62 + ? 43 + : nUint6 === 63 + ? 47 + : 65; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64ToUint6(nChr) { + return nChr > 64 && nChr < 91 + ? nChr - 65 + : nChr > 96 && nChr < 123 + ? nChr - 71 + : nChr > 47 && nChr < 58 + ? nChr + 4 + : nChr === 43 + ? 62 + : nChr === 47 + ? 63 + : 0; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function decode64(sBase64) { + if (sBase64.match(/[^A-Za-z0-9\+\/=]/g)) return new Error(Nil); + let sB64Enc = sBase64.replace(/=/g, ""); + let nInLen = sB64Enc.length; + let nOutLen = (nInLen * 3 + 1) >> 2; + let taBytes = new Uint8Array(nOutLen); + + for ( + let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; + nInIdx < nInLen; + nInIdx++ + ) { + nMod4 = nInIdx & 3; + nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4)); + if (nMod4 === 3 || nInLen - nInIdx === 1) { + for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { + taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255; + } + nUint24 = 0; + } + } + + return new Ok(new BitString(taBytes)); +} + +export function classify_dynamic(data) { + if (typeof data === "string") { + return "String"; + } else if (Result.isResult(data)) { + return "Result"; + } else if (List.isList(data)) { + return "List"; + } else if (Number.isInteger(data)) { + return "Int"; + } else if (Array.isArray(data)) { + return `Tuple of ${data.length} elements`; + } else if (BitString.isBitString(data)) { + return "BitString"; + } else if (data instanceof Map) { + return "Map"; + } else if (typeof data === "number") { + return "Float"; + } else { + let type = typeof data; + return type.charAt(0).toUpperCase() + type.slice(1); + } +} + +function decoder_error(expected, got) { + return new Error(new DecodeError(expected, classify_dynamic(got))); +} + +export function decode_string(data) { + return typeof data === "string" + ? new Ok(data) + : decoder_error("String", data); +} + +export function decode_int(data) { + return Number.isInteger(data) ? new Ok(data) : decoder_error("Int", data); +} + +export function decode_float(data) { + return typeof data === "number" ? new Ok(data) : decoder_error("Float", data); +} + +export function decode_bool(data) { + return typeof data === "boolean" ? new Ok(data) : decoder_error("Bool", data); +} + +export function decode_bit_string(data) { + return BitString.isBitString(data) + ? new Ok(data) + : decoder_error("BitString", data); +} + +export function decode_tuple(data) { + return Array.isArray(data) ? new Ok(data) : decoder_error("Tuple", data); +} + +export function tuple_get(data, index) { + return index >= 0 && data.length > index + ? new Ok(data[index]) + : new Error(Nil); +} + +export function decode_list(data) { + return List.isList(data) ? new Ok(data) : decoder_error("List", data); +} + +export function decode_result(data) { + return Result.isResult(data) ? new Ok(data) : decoder_error("Result", data); +} + +export function decode_map(data) { + return data instanceof Map ? new Ok(data) : decoder_error("Map", data); +} + +export function decode_option(data, decoder) { + if (data === null || data === undefined || data instanceof None) + return new Ok(new None()); + if (data instanceof Some) data = data[0]; + let result = decoder(data); + if (result.isOk()) { + return new Ok(new Some(result[0])); + } else { + return result; + } +} + +export function decode_field(value, name) { + let error = () => decoder_error(`Value with field ${inspect(name)}`, value); + if (value instanceof Map) { + let entry = value.get(name); + return entry.isOk() ? entry : error(); + } + try { + return name in value ? new Ok(value[name]) : error(); + } catch { + return error(); + } +} diff --git a/test/gleam/should.gleam b/test/gleam/should.gleam index 483b1a3..3cedbcd 100644 --- a/test/gleam/should.gleam +++ b/test/gleam/should.gleam @@ -25,7 +25,7 @@ if javascript { "../gleam.js" "inspect" external fn crash(String) -> anything = - "../gleam_stdlib.js" "crash" + "../gleam_stdlib.mjs" "crash" pub fn equal(a, b) { case a == b { -- cgit v1.2.3