diff options
author | Louis Pilfold <louis@lpil.uk> | 2023-07-23 19:25:42 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2023-07-23 19:25:42 +0100 |
commit | 43ae440ad66571cc41fef8e20dd852b170a3dc2b (patch) | |
tree | fdf889396459242079beff03c62731850e7bc96d /src | |
parent | ed3b2096cc9e22bec44cb1eb84285bb013b62d51 (diff) | |
download | gleam_stdlib-43ae440ad66571cc41fef8e20dd852b170a3dc2b.tar.gz gleam_stdlib-43ae440ad66571cc41fef8e20dd852b170a3dc2b.zip |
Gleam fix
Diffstat (limited to 'src')
-rw-r--r-- | src/gleam/base.gleam | 24 | ||||
-rw-r--r-- | src/gleam/bit_builder.gleam | 191 | ||||
-rw-r--r-- | src/gleam/bit_string.gleam | 107 | ||||
-rw-r--r-- | src/gleam/dynamic.gleam | 324 | ||||
-rw-r--r-- | src/gleam/float.gleam | 117 | ||||
-rw-r--r-- | src/gleam/int.gleam | 60 | ||||
-rw-r--r-- | src/gleam/io.gleam | 60 | ||||
-rw-r--r-- | src/gleam/list.gleam | 75 | ||||
-rw-r--r-- | src/gleam/map.gleam | 321 | ||||
-rw-r--r-- | src/gleam/regex.gleam | 59 | ||||
-rw-r--r-- | src/gleam/set.gleam | 24 | ||||
-rw-r--r-- | src/gleam/string.gleam | 456 | ||||
-rw-r--r-- | src/gleam/string_builder.gleam | 224 | ||||
-rw-r--r-- | src/gleam/uri.gleam | 284 |
14 files changed, 905 insertions, 1421 deletions
diff --git a/src/gleam/base.gleam b/src/gleam/base.gleam index 7ec1558..a084a7c 100644 --- a/src/gleam/base.gleam +++ b/src/gleam/base.gleam @@ -11,15 +11,9 @@ pub fn encode64(input: BitString, padding: Bool) -> String { } } -if erlang { - external fn do_encode64(BitString) -> String = - "base64" "encode" -} - -if javascript { - external fn do_encode64(BitString) -> String = - "../gleam_stdlib.mjs" "encode64" -} +@external(erlang, "base64", "encode") +@external(javascript, "../gleam_stdlib.mjs", "encode64") +fn do_encode64(a: BitString) -> String /// Decodes a base 64 encoded string into a `BitString`. /// @@ -31,15 +25,9 @@ pub fn decode64(encoded: String) -> Result(BitString, Nil) { do_decode64(padded) } -if erlang { - external fn do_decode64(String) -> Result(BitString, Nil) = - "gleam_stdlib" "base_decode64" -} - -if javascript { - external fn do_decode64(String) -> Result(BitString, Nil) = - "../gleam_stdlib.mjs" "decode64" -} +@external(erlang, "gleam_stdlib", "base_decode64") +@external(javascript, "../gleam_stdlib.mjs", "decode64") +fn do_decode64(a: String) -> Result(BitString, Nil) /// Encodes a `BitString` into a base 64 encoded string with URL and filename safe alphabet. /// diff --git a/src/gleam/bit_builder.gleam b/src/gleam/bit_builder.gleam index 960d665..03f0bff 100644 --- a/src/gleam/bit_builder.gleam +++ b/src/gleam/bit_builder.gleam @@ -13,22 +13,19 @@ //// On Erlang this type is compatible with Erlang's iolists. import gleam/string_builder.{StringBuilder} +@target(javascript) +import gleam/list +@target(javascript) +import gleam/bit_string -if javascript { - import gleam/list - import gleam/bit_string -} - -if erlang { - pub external type BitBuilder -} +@target(erlang) +pub type BitBuilder -if javascript { - pub opaque type BitBuilder { - Bits(BitString) - Text(StringBuilder) - Many(List(BitBuilder)) - } +@target(javascript) +pub opaque type BitBuilder { + Bits(BitString) + Text(StringBuilder) + Many(List(BitBuilder)) } /// Create an empty `BitBuilder`. Useful as the start of a pipe chaning many @@ -73,20 +70,15 @@ pub fn append_builder( do_append_builder(first, second) } -if erlang { - external fn do_append_builder( - to: BitBuilder, - suffix: BitBuilder, - ) -> BitBuilder = - "gleam_stdlib" "iodata_append" -} +@target(erlang) +@external(erlang, "gleam_stdlib", "iodata_append") +fn do_append_builder(to to: BitBuilder, suffix suffix: BitBuilder) -> BitBuilder -if javascript { - fn do_append_builder(first: BitBuilder, second: BitBuilder) -> BitBuilder { - case second { - Many(builders) -> Many([first, ..builders]) - _ -> Many([first, second]) - } +@target(javascript) +fn do_append_builder(first: BitBuilder, second: BitBuilder) -> BitBuilder { + case second { + Many(builders) -> Many([first, ..builders]) + _ -> Many([first, second]) } } @@ -116,15 +108,13 @@ pub fn concat(builders: List(BitBuilder)) -> BitBuilder { do_concat(builders) } -if erlang { - external fn do_concat(List(BitBuilder)) -> BitBuilder = - "gleam_stdlib" "identity" -} +@target(erlang) +@external(erlang, "gleam_stdlib", "identity") +fn do_concat(a: List(BitBuilder)) -> BitBuilder -if javascript { - fn do_concat(builders: List(BitBuilder)) -> BitBuilder { - Many(builders) - } +@target(javascript) +fn do_concat(builders: List(BitBuilder)) -> BitBuilder { + Many(builders) } /// Joins a list of bit strings into a single builder. @@ -135,17 +125,15 @@ pub fn concat_bit_strings(bits: List(BitString)) -> BitBuilder { do_concat_bit_strings(bits) } -if erlang { - external fn do_concat_bit_strings(List(BitString)) -> BitBuilder = - "gleam_stdlib" "identity" -} +@target(erlang) +@external(erlang, "gleam_stdlib", "identity") +fn do_concat_bit_strings(a: List(BitString)) -> BitBuilder -if javascript { - fn do_concat_bit_strings(bits: List(BitString)) -> BitBuilder { - bits - |> list.map(fn(b) { from_bit_string(b) }) - |> concat() - } +@target(javascript) +fn do_concat_bit_strings(bits: List(BitString)) -> BitBuilder { + bits + |> list.map(fn(b) { from_bit_string(b) }) + |> concat() } /// Creates a new builder from a string. @@ -157,15 +145,13 @@ pub fn from_string(string: String) -> BitBuilder { do_from_string(string) } -if erlang { - external fn do_from_string(String) -> BitBuilder = - "gleam_stdlib" "wrap_list" -} +@target(erlang) +@external(erlang, "gleam_stdlib", "wrap_list") +fn do_from_string(a: String) -> BitBuilder -if javascript { - fn do_from_string(string: String) -> BitBuilder { - Text(string_builder.from_string(string)) - } +@target(javascript) +fn do_from_string(string: String) -> BitBuilder { + Text(string_builder.from_string(string)) } /// Creates a new builder from a string builder. @@ -177,15 +163,13 @@ pub fn from_string_builder(builder: StringBuilder) -> BitBuilder { do_from_string_builder(builder) } -if erlang { - external fn do_from_string_builder(StringBuilder) -> BitBuilder = - "gleam_stdlib" "wrap_list" -} +@target(erlang) +@external(erlang, "gleam_stdlib", "wrap_list") +fn do_from_string_builder(a: StringBuilder) -> BitBuilder -if javascript { - fn do_from_string_builder(builder: StringBuilder) -> BitBuilder { - Text(builder) - } +@target(javascript) +fn do_from_string_builder(builder: StringBuilder) -> BitBuilder { + Text(builder) } /// Creates a new builder from a bit string. @@ -196,15 +180,13 @@ pub fn from_bit_string(bits: BitString) -> BitBuilder { do_from_bit_string(bits) } -if erlang { - external fn do_from_bit_string(BitString) -> BitBuilder = - "gleam_stdlib" "wrap_list" -} +@target(erlang) +@external(erlang, "gleam_stdlib", "wrap_list") +fn do_from_bit_string(a: BitString) -> BitBuilder -if javascript { - fn do_from_bit_string(bits: BitString) -> BitBuilder { - Bits(bits) - } +@target(javascript) +fn do_from_bit_string(bits: BitString) -> BitBuilder { + Bits(bits) } /// Turns an builder into a bit string. @@ -218,39 +200,38 @@ pub fn to_bit_string(builder: BitBuilder) -> BitString { do_to_bit_string(builder) } -if erlang { - external fn do_to_bit_string(BitBuilder) -> BitString = - "erlang" "list_to_bitstring" -} +@target(erlang) +@external(erlang, "erlang", "list_to_bitstring") +fn do_to_bit_string(a: BitBuilder) -> BitString -if javascript { - fn do_to_bit_string(builder: BitBuilder) -> BitString { - [[builder]] - |> to_list([]) - |> list.reverse - |> bit_string.concat - } - - fn to_list( - stack: List(List(BitBuilder)), - acc: List(BitString), - ) -> List(BitString) { - case stack { - [] -> acc +@target(javascript) +fn do_to_bit_string(builder: BitBuilder) -> BitString { + [[builder]] + |> to_list([]) + |> list.reverse + |> bit_string.concat +} - [[], ..remaining_stack] -> to_list(remaining_stack, acc) +@target(javascript) +fn to_list( + stack: List(List(BitBuilder)), + acc: List(BitString), +) -> List(BitString) { + case stack { + [] -> acc - [[Bits(bits), ..rest], ..remaining_stack] -> - to_list([rest, ..remaining_stack], [bits, ..acc]) + [[], ..remaining_stack] -> to_list(remaining_stack, acc) - [[Text(builder), ..rest], ..remaining_stack] -> { - let bits = bit_string.from_string(string_builder.to_string(builder)) - to_list([rest, ..remaining_stack], [bits, ..acc]) - } + [[Bits(bits), ..rest], ..remaining_stack] -> + to_list([rest, ..remaining_stack], [bits, ..acc]) - [[Many(builders), ..rest], ..remaining_stack] -> - to_list([builders, rest, ..remaining_stack], acc) + [[Text(builder), ..rest], ..remaining_stack] -> { + let bits = bit_string.from_string(string_builder.to_string(builder)) + to_list([rest, ..remaining_stack], [bits, ..acc]) } + + [[Many(builders), ..rest], ..remaining_stack] -> + to_list([builders, rest, ..remaining_stack], acc) } } @@ -262,15 +243,13 @@ pub fn byte_size(builder: BitBuilder) -> Int { do_byte_size(builder) } -if erlang { - external fn do_byte_size(BitBuilder) -> Int = - "erlang" "iolist_size" -} +@target(erlang) +@external(erlang, "erlang", "iolist_size") +fn do_byte_size(a: BitBuilder) -> Int -if javascript { - fn do_byte_size(builder: BitBuilder) -> Int { - [[builder]] - |> to_list([]) - |> list.fold(0, fn(acc, builder) { bit_string.byte_size(builder) + acc }) - } +@target(javascript) +fn do_byte_size(builder: BitBuilder) -> Int { + [[builder]] + |> to_list([]) + |> list.fold(0, fn(acc, builder) { bit_string.byte_size(builder) + acc }) } diff --git a/src/gleam/bit_string.gleam b/src/gleam/bit_string.gleam index 6a67028..25ad686 100644 --- a/src/gleam/bit_string.gleam +++ b/src/gleam/bit_string.gleam @@ -8,15 +8,9 @@ pub fn from_string(x: String) -> BitString { do_from_string(x) } -if erlang { - external fn do_from_string(String) -> BitString = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_from_string(String) -> BitString = - "../gleam_stdlib.mjs" "bit_string_from_string" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "bit_string_from_string") +fn do_from_string(a: String) -> BitString /// Returns an integer which is the number of bytes in the bit string. /// @@ -24,15 +18,9 @@ pub fn byte_size(x: BitString) -> Int { do_byte_size(x) } -if erlang { - external fn do_byte_size(BitString) -> Int = - "erlang" "byte_size" -} - -if javascript { - external fn do_byte_size(BitString) -> Int = - "../gleam_stdlib.mjs" "length" -} +@external(erlang, "erlang", "byte_size") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn do_byte_size(a: BitString) -> Int /// Creates a new bit string by joining two binaries. /// @@ -63,23 +51,13 @@ pub fn slice( do_slice(string, position, length) } -if erlang { - external fn do_slice( - string: BitString, - position: Int, - length: Int, - ) -> Result(BitString, Nil) = - "gleam_stdlib" "bit_string_slice" -} - -if javascript { - external fn do_slice( - string: BitString, - position: Int, - length: Int, - ) -> Result(BitString, Nil) = - "../gleam_stdlib.mjs" "bit_string_slice" -} +@external(erlang, "gleam_stdlib", "bit_string_slice") +@external(javascript, "../gleam_stdlib.mjs", "bit_string_slice") +fn do_slice( + string string: BitString, + position position: Int, + length length: Int, +) -> Result(BitString, Nil) /// Tests to see whether a bit string is valid UTF-8. /// @@ -87,22 +65,20 @@ pub fn is_utf8(bits: BitString) -> Bool { do_is_utf8(bits) } -if erlang { - fn do_is_utf8(bits: BitString) -> Bool { - case bits { - <<>> -> True - <<_:utf8, rest:binary>> -> do_is_utf8(rest) - _ -> False - } +@target(erlang) +fn do_is_utf8(bits: BitString) -> Bool { + case bits { + <<>> -> True + <<_:utf8, rest:binary>> -> do_is_utf8(rest) + _ -> False } } -if javascript { - fn do_is_utf8(bits: BitString) -> Bool { - case to_string(bits) { - Ok(_) -> True - _ -> False - } +@target(javascript) +fn do_is_utf8(bits: BitString) -> Bool { + case to_string(bits) { + Ok(_) -> True + _ -> False } } @@ -114,22 +90,21 @@ pub fn to_string(bits: BitString) -> Result(String, Nil) { do_to_string(bits) } -if erlang { - external fn unsafe_to_string(BitString) -> String = - "gleam_stdlib" "identity" +@target(erlang) +@external(erlang, "gleam_stdlib", "identity") +fn unsafe_to_string(a: BitString) -> String - fn do_to_string(bits: BitString) -> Result(String, Nil) { - case is_utf8(bits) { - True -> Ok(unsafe_to_string(bits)) - False -> Error(Nil) - } +@target(erlang) +fn do_to_string(bits: BitString) -> Result(String, Nil) { + case is_utf8(bits) { + True -> Ok(unsafe_to_string(bits)) + False -> Error(Nil) } } -if javascript { - external fn do_to_string(BitString) -> Result(String, Nil) = - "../gleam_stdlib.mjs" "bit_string_to_string" -} +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "bit_string_to_string") +fn do_to_string(a: BitString) -> Result(String, Nil) /// Creates a new bit string by joining multiple binaries. /// @@ -144,12 +119,6 @@ pub fn concat(bit_strings: List(BitString)) -> BitString { do_concat(bit_strings) } -if erlang { - external fn do_concat(List(BitString)) -> BitString = - "gleam_stdlib" "bit_string_concat" -} - -if javascript { - external fn do_concat(List(BitString)) -> BitString = - "../gleam_stdlib.mjs" "bit_string_concat" -} +@external(erlang, "gleam_stdlib", "bit_string_concat") +@external(javascript, "../gleam_stdlib.mjs", "bit_string_concat") +fn do_concat(a: List(BitString)) -> BitString diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index f6b1717..c48e956 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -4,16 +4,14 @@ import gleam/map.{Map} import gleam/option.{Option} import gleam/result import gleam/string_builder - -if erlang { - import gleam/bit_string -} +@target(erlang) +import gleam/bit_string /// `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. /// -pub external type Dynamic +pub type Dynamic /// Error returned when unexpected data is encountered /// @@ -33,15 +31,9 @@ pub fn from(a) -> Dynamic { do_from(a) } -if erlang { - external fn do_from(anything) -> Dynamic = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_from(anything) -> Dynamic = - "../gleam_stdlib.mjs" "identity" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_from(a: anything) -> Dynamic /// Unsafely casts a Dynamic value into any other type. /// @@ -54,15 +46,9 @@ pub fn unsafe_coerce(a: Dynamic) -> anything { do_unsafe_coerce(a) } -if erlang { - external fn do_unsafe_coerce(Dynamic) -> a = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_unsafe_coerce(Dynamic) -> a = - "../gleam_stdlib.mjs" "identity" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_unsafe_coerce(a: Dynamic) -> a /// Decodes a `Dynamic` value from a `Dynamic` value. /// @@ -93,15 +79,9 @@ pub fn bit_string(from data: Dynamic) -> Result(BitString, DecodeErrors) { decode_bit_string(data) } -if erlang { - external fn decode_bit_string(Dynamic) -> Result(BitString, DecodeErrors) = - "gleam_stdlib" "decode_bit_string" -} - -if javascript { - external fn decode_bit_string(Dynamic) -> Result(BitString, DecodeErrors) = - "../gleam_stdlib.mjs" "decode_bit_string" -} +@external(erlang, "gleam_stdlib", "decode_bit_string") +@external(javascript, "../gleam_stdlib.mjs", "decode_bit_string") +fn decode_bit_string(a: Dynamic) -> Result(BitString, DecodeErrors) /// Checks to see whether a `Dynamic` value is a string, and returns that string if /// it is. @@ -129,29 +109,28 @@ fn map_errors( result.map_error(result, list.map(_, f)) } -if erlang { - fn decode_string(data: Dynamic) -> Result(String, DecodeErrors) { - bit_string(data) - |> map_errors(put_expected(_, "String")) - |> result.try(fn(raw) { - case bit_string.to_string(raw) { - Ok(string) -> Ok(string) - Error(Nil) -> - Error([DecodeError(expected: "String", found: "BitString", path: [])]) - } - }) - } - - fn put_expected(error: DecodeError, expected: String) -> DecodeError { - DecodeError(..error, expected: expected) - } +@target(erlang) +fn decode_string(data: Dynamic) -> Result(String, DecodeErrors) { + bit_string(data) + |> map_errors(put_expected(_, "String")) + |> result.try(fn(raw) { + case bit_string.to_string(raw) { + Ok(string) -> Ok(string) + Error(Nil) -> + Error([DecodeError(expected: "String", found: "BitString", path: [])]) + } + }) } -if javascript { - external fn decode_string(Dynamic) -> Result(String, DecodeErrors) = - "../gleam_stdlib.mjs" "decode_string" +@target(erlang) +fn put_expected(error: DecodeError, expected: String) -> DecodeError { + DecodeError(..error, expected: expected) } +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "decode_string") +fn decode_string(a: Dynamic) -> Result(String, DecodeErrors) + /// Return a string indicating the type of the dynamic value. /// /// ```gleam @@ -163,15 +142,9 @@ pub fn classify(data: Dynamic) -> String { do_classify(data) } -if erlang { - external fn do_classify(Dynamic) -> String = - "gleam_stdlib" "classify_dynamic" -} - -if javascript { - external fn do_classify(Dynamic) -> String = - "../gleam_stdlib.mjs" "classify_dynamic" -} +@external(erlang, "gleam_stdlib", "classify_dynamic") +@external(javascript, "../gleam_stdlib.mjs", "classify_dynamic") +fn do_classify(a: Dynamic) -> String /// Checks to see whether a `Dynamic` value is an int, and returns that int if it /// is. @@ -192,15 +165,9 @@ pub fn int(from data: Dynamic) -> Result(Int, DecodeErrors) { decode_int(data) } -if erlang { - external fn decode_int(Dynamic) -> Result(Int, DecodeErrors) = - "gleam_stdlib" "decode_int" -} - -if javascript { - external fn decode_int(Dynamic) -> Result(Int, DecodeErrors) = - "../gleam_stdlib.mjs" "decode_int" -} +@external(erlang, "gleam_stdlib", "decode_int") +@external(javascript, "../gleam_stdlib.mjs", "decode_int") +fn decode_int(a: Dynamic) -> Result(Int, DecodeErrors) /// Checks to see whether a `Dynamic` value is a float, and returns that float if /// it is. @@ -221,15 +188,9 @@ pub fn float(from data: Dynamic) -> Result(Float, DecodeErrors) { decode_float(data) } -if erlang { - external fn decode_float(Dynamic) -> Result(Float, DecodeErrors) = - "gleam_stdlib" "decode_float" -} - -if javascript { - external fn decode_float(Dynamic) -> Result(Float, DecodeErrors) = - "../gleam_stdlib.mjs" "decode_float" -} +@external(erlang, "gleam_stdlib", "decode_float") +@external(javascript, "../gleam_stdlib.mjs", "decode_float") +fn decode_float(a: Dynamic) -> Result(Float, DecodeErrors) /// Checks to see whether a `Dynamic` value is a bool, and returns that bool if /// it is. @@ -250,15 +211,9 @@ pub fn bool(from data: Dynamic) -> Result(Bool, DecodeErrors) { decode_bool(data) } -if erlang { - external fn decode_bool(Dynamic) -> Result(Bool, DecodeErrors) = - "gleam_stdlib" "decode_bool" -} - -if javascript { - external fn decode_bool(Dynamic) -> Result(Bool, DecodeErrors) = - "../gleam_stdlib.mjs" "decode_bool" -} +@external(erlang, "gleam_stdlib", "decode_bool") +@external(javascript, "../gleam_stdlib.mjs", "decode_bool") +fn decode_bool(a: Dynamic) -> Result(Bool, DecodeErrors) /// Checks to see whether a `Dynamic` value is a list, and returns that list if it /// is. The types of the elements are not checked. @@ -282,25 +237,13 @@ pub fn shallow_list(from value: Dynamic) -> Result(List(Dynamic), DecodeErrors) decode_list(value) } -if erlang { - external fn decode_list(Dynamic) -> Result(List(Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_list" -} - -if javascript { - external fn decode_list(Dynamic) -> Result(List(Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_list" -} +@external(erlang, "gleam_stdlib", "decode_list") +@external(javascript, "../gleam_stdlib.mjs", "decode_list") +fn decode_list(a: Dynamic) -> Result(List(Dynamic), DecodeErrors) -if erlang { - external fn decode_result(Dynamic) -> Result(Result(a, e), DecodeErrors) = - "gleam_stdlib" "decode_result" -} - -if javascript { - external fn decode_result(Dynamic) -> Result(Result(a, e), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_result" -} +@external(erlang, "gleam_stdlib", "decode_result") +@external(javascript, "../gleam_stdlib.mjs", "decode_result") +fn decode_result(a: Dynamic) -> Result(Result(a, e), DecodeErrors) /// Checks to see whether a `Dynamic` value is a result of a particular type, and /// returns that result if it is. @@ -440,21 +383,9 @@ pub fn optional(of decode: Decoder(inner)) -> Decoder(Option(inner)) { fn(value) { decode_optional(value, decode) } } -if erlang { - external fn decode_optional( - Dynamic, - Decoder(a), - ) -> Result(Option(a), DecodeErrors) = - "gleam_stdlib" "decode_option" -} - -if javascript { - external fn decode_optional( - Dynamic, - Decoder(a), - ) -> Result(Option(a), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_option" -} +@external(erlang, "gleam_stdlib", "decode_option") +@external(javascript, "../gleam_stdlib.mjs", "decode_option") +fn decode_optional(a: Dynamic, b: Decoder(a)) -> Result(Option(a), DecodeErrors) /// Checks to see if a `Dynamic` value is a map with a specific field, and returns /// the value of that field if it is. @@ -536,21 +467,9 @@ pub fn optional_field( } } -if erlang { - external fn decode_field( - Dynamic, - name, - ) -> Result(Option(Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_field" -} - -if javascript { - external fn decode_field( - Dynamic, - name, - ) -> Result(Option(Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_field" -} +@external(erlang, "gleam_stdlib", "decode_field") +@external(javascript, "../gleam_stdlib.mjs", "decode_field") +fn decode_field(a: Dynamic, b: name) -> Result(Option(Dynamic), DecodeErrors) /// Checks to see if a `Dynamic` value is a tuple large enough to have a certain /// index, and returns the value of that index if it is. @@ -613,85 +532,50 @@ fn at_least_decode_tuple_error( } // A tuple of unknown size -external type UnknownTuple - -if erlang { - external fn decode_tuple(Dynamic) -> Result(UnknownTuple, DecodeErrors) = - "gleam_stdlib" "decode_tuple" - - external fn decode_tuple2( - Dynamic, - ) -> Result(#(Dynamic, Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_tuple2" - - external fn decode_tuple3( - Dynamic, - ) -> Result(#(Dynamic, Dynamic, Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_tuple3" - - external fn decode_tuple4( - Dynamic, - ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_tuple4" - - external fn decode_tuple5( - Dynamic, - ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_tuple5" - - external fn decode_tuple6( - Dynamic, - ) -> Result( - #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), - DecodeErrors, - ) = - "gleam_stdlib" "decode_tuple6" - - external fn tuple_get(UnknownTuple, Int) -> Result(Dynamic, DecodeErrors) = - "gleam_stdlib" "tuple_get" - - external fn tuple_size(UnknownTuple) -> Int = - "gleam_stdlib" "size_of_tuple" -} - -if javascript { - external fn decode_tuple(Dynamic) -> Result(UnknownTuple, DecodeErrors) = - "../gleam_stdlib.mjs" "decode_tuple" - - external fn decode_tuple2( - Dynamic, - ) -> Result(#(Dynamic, Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_tuple2" - - external fn decode_tuple3( - Dynamic, - ) -> Result(#(Dynamic, Dynamic, Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_tuple3" - - external fn decode_tuple4( - Dynamic, - ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_tuple4" - - external fn decode_tuple5( - Dynamic, - ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_tuple5" - - external fn decode_tuple6( - Dynamic, - ) -> Result( - #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), - DecodeErrors, - ) = - "../gleam_stdlib.mjs" "decode_tuple6" - - external fn tuple_get(UnknownTuple, Int) -> Result(Dynamic, DecodeErrors) = - "../gleam_stdlib.mjs" "tuple_get" - - external fn tuple_size(UnknownTuple) -> Int = - "../gleam_stdlib.mjs" "length" -} +type UnknownTuple + +@external(erlang, "gleam_stdlib", "decode_tuple") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple") +fn decode_tuple(a: Dynamic) -> Result(UnknownTuple, DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple2") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple2") +fn decode_tuple2(a: Dynamic) -> Result(#(Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple3") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple3") +fn decode_tuple3( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple4") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple4") +fn decode_tuple4( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple5") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple5") +fn decode_tuple5( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple6") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple6") +fn decode_tuple6( + a: Dynamic, +) -> Result( + #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), + DecodeErrors, +) + +@external(erlang, "gleam_stdlib", "tuple_get") +@external(javascript, "../gleam_stdlib.mjs", "tuple_get") +fn tuple_get(a: UnknownTuple, b: Int) -> Result(Dynamic, DecodeErrors) + +@external(erlang, "gleam_stdlib", "size_of_tuple") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn tuple_size(a: UnknownTuple) -> Int fn tuple_errors( result: Result(a, List(DecodeError)), @@ -1084,15 +968,9 @@ pub fn map( } } -if erlang { - external fn decode_map(Dynamic) -> Result(Map(Dynamic, Dynamic), DecodeErrors) = - "gleam_stdlib" "decode_map" -} - -if javascript { - external fn decode_map(Dynamic) -> Result(Map(Dynamic, Dynamic), DecodeErrors) = - "../gleam_stdlib.mjs" "decode_map" -} +@external(erlang, "gleam_stdlib", "decode_map") +@external(javascript, "../gleam_stdlib.mjs", "decode_map") +fn decode_map(a: Dynamic) -> Result(Map(Dynamic, Dynamic), DecodeErrors) /// Joins multiple decoders into one. When run they will each be tried in turn /// until one succeeds, or they all fail. diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam index 1ee175c..a70a2e9 100644 --- a/src/gleam/float.gleam +++ b/src/gleam/float.gleam @@ -19,15 +19,9 @@ pub fn parse(string: String) -> Result(Float, Nil) { do_parse(string) } -if erlang { - external fn do_parse(String) -> Result(Float, Nil) = - "gleam_stdlib" "parse_float" -} - -if javascript { - external fn do_parse(String) -> Result(Float, Nil) = - "../gleam_stdlib.mjs" "parse_float" -} +@external(erlang, "gleam_stdlib", "parse_float") +@external(javascript, "../gleam_stdlib.mjs", "parse_float") +fn do_parse(a: String) -> Result(Float, Nil) /// Returns the string representation of the provided `Float`. /// @@ -42,15 +36,9 @@ pub fn to_string(x: Float) -> String { do_to_string(x) } -if erlang { - external fn do_to_string(Float) -> String = - "gleam_stdlib" "float_to_string" -} - -if javascript { - external fn do_to_string(Float) -> String = - "../gleam_stdlib.mjs" "float_to_string" -} +@external(erlang, "gleam_stdlib", "float_to_string") +@external(javascript, "../gleam_stdlib.mjs", "float_to_string") +fn do_to_string(a: Float) -> String /// Restricts a `Float` between a lower and upper bound. /// @@ -198,15 +186,9 @@ pub fn ceiling(x: Float) -> Float { do_ceiling(x) } -if erlang { - external fn do_ceiling(Float) -> Float = - "math" "ceil" -} - -if javascript { - external fn do_ceiling(Float) -> Float = - "../gleam_stdlib.mjs" "ceiling" -} +@external(erlang, "math", "ceil") +@external(javascript, "../gleam_stdlib.mjs", "ceiling") +fn do_ceiling(a: Float) -> Float /// Rounds the value to the next lowest whole number as a `Float`. /// @@ -221,15 +203,9 @@ pub fn floor(x: Float) -> Float { do_floor(x) } -if erlang { - external fn do_floor(Float) -> Float = - "math" "floor" -} - -if javascript { - external fn do_floor(Float) -> Float = - "../gleam_stdlib.mjs" "floor" -} +@external(erlang, "math", "floor") +@external(javascript, "../gleam_stdlib.mjs", "floor") +fn do_floor(a: Float) -> Float /// Rounds the value to the nearest whole number as an `Int`. /// @@ -249,23 +225,22 @@ pub fn round(x: Float) -> Int { do_round(x) } -if erlang { - external fn do_round(Float) -> Int = - "erlang" "round" -} +@target(erlang) +@external(erlang, "erlang", "round") +fn do_round(a: Float) -> Int -if javascript { - fn do_round(x: Float) -> Int { - case x >=. 0.0 { - True -> js_round(x) - _ -> 0 - js_round(negate(x)) - } +@target(javascript) +fn do_round(x: Float) -> Int { + case x >=. 0.0 { + True -> js_round(x) + _ -> 0 - js_round(negate(x)) } - - external fn js_round(Float) -> Int = - "../gleam_stdlib.mjs" "round" } +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "round") +fn js_round(a: Float) -> Int + /// Returns the value as an `Int`, truncating all decimal digits. /// /// ## Examples @@ -279,15 +254,9 @@ pub fn truncate(x: Float) -> Int { do_truncate(x) } -if erlang { - external fn do_truncate(Float) -> Int = - "erlang" "trunc" -} - -if javascript { - external fn do_truncate(Float) -> Int = - "../gleam_stdlib.mjs" "truncate" -} +@external(erlang, "erlang", "trunc") +@external(javascript, "../gleam_stdlib.mjs", "truncate") +fn do_truncate(a: Float) -> Int /// Returns the absolute value of the input as a `Float`. /// @@ -354,15 +323,9 @@ pub fn power(base: Float, of exponent: Float) -> Result(Float, Nil) { } } -if erlang { - external fn do_power(Float, Float) -> Float = - "math" "pow" -} - -if javascript { - external fn do_power(Float, Float) -> Float = - "../gleam_stdlib.mjs" "power" -} +@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`. /// @@ -467,19 +430,13 @@ pub fn random(boundary_a: Float, boundary_b: Float) -> Float { } } -if erlang { - /// Returns a random float uniformly distributed in the value range - /// 0.0 =< X < 1.0 and updates the state in the process dictionary. - /// See: <https://www.erlang.org/doc/man/rand.html#uniform-0> - /// - external fn do_random_uniform() -> Float = - "rand" "uniform" -} - -if javascript { - external fn do_random_uniform() -> Float = - "../gleam_stdlib.mjs" "random_uniform" -} +/// Returns a random float uniformly distributed in the value range +/// 0.0 =< X < 1.0 and updates the state in the process dictionary. +/// See: <https://www.erlang.org/doc/man/rand.html#uniform-0> +/// +@external(erlang, "rand", "uniform") +@external(javascript, "../gleam_stdlib.mjs", "random_uniform") +fn do_random_uniform() -> Float /// Returns division of the inputs as a `Result`. /// diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam index 793a85e..c49df37 100644 --- a/src/gleam/int.gleam +++ b/src/gleam/int.gleam @@ -96,15 +96,9 @@ pub fn parse(string: String) -> Result(Int, Nil) { do_parse(string) } -if erlang { - external fn do_parse(String) -> Result(Int, Nil) = - "gleam_stdlib" "parse_int" -} - -if javascript { - external fn do_parse(String) -> Result(Int, Nil) = - "../gleam_stdlib.mjs" "parse_int" -} +@external(erlang, "gleam_stdlib", "parse_int") +@external(javascript, "../gleam_stdlib.mjs", "parse_int") +fn do_parse(a: 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)`. @@ -135,15 +129,9 @@ pub fn base_parse(string: String, base: Int) -> Result(Int, Nil) { } } -if erlang { - external fn do_base_parse(String, Int) -> Result(Int, Nil) = - "gleam_stdlib" "int_from_base_string" -} - -if javascript { - external fn do_base_parse(String, Int) -> Result(Int, Nil) = - "../gleam_stdlib.mjs" "int_from_base_string" -} +@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. /// @@ -158,15 +146,9 @@ pub fn to_string(x: Int) { do_to_string(x) } -if erlang { - external fn do_to_string(Int) -> String = - "erlang" "integer_to_binary" -} - -if javascript { - external fn do_to_string(Int) -> String = - "../gleam_stdlib.mjs" "to_string" -} +@external(erlang, "erlang", "integer_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "to_string") +fn do_to_string(a: Int) -> String /// Error value when trying to operate with a base out of the allowed range. /// @@ -212,15 +194,9 @@ pub fn to_base_string(x: Int, base: Int) -> Result(String, InvalidBase) { } } -if erlang { - external fn do_to_base_string(Int, Int) -> String = - "erlang" "integer_to_binary" -} - -if javascript { - external fn do_to_base_string(Int, Int) -> String = - "../gleam_stdlib.mjs" "int_to_base_string" -} +@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. /// @@ -297,15 +273,9 @@ pub fn to_float(x: Int) -> Float { do_to_float(x) } -if erlang { - external fn do_to_float(Int) -> Float = - "erlang" "float" -} - -if javascript { - external fn do_to_float(Int) -> Float = - "../gleam_stdlib.mjs" "identity" -} +@external(erlang, "erlang", "float") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_to_float(a: Int) -> Float /// Restricts an int between a lower and upper bound. /// diff --git a/src/gleam/io.gleam b/src/gleam/io.gleam index c8524f1..0c0a3ee 100644 --- a/src/gleam/io.gleam +++ b/src/gleam/io.gleam @@ -16,15 +16,9 @@ pub fn print(string: String) -> Nil { do_print(string) } -if erlang { - external fn do_print(string: String) -> Nil = - "gleam_stdlib" "print" -} - -if javascript { - external fn do_print(String) -> Nil = - "../gleam_stdlib.mjs" "print" -} +@external(erlang, "gleam_stdlib", "print") +@external(javascript, "../gleam_stdlib.mjs", "print") +fn do_print(string string: String) -> Nil /// Writes a string to standard error. /// @@ -42,15 +36,9 @@ pub fn print_error(string: String) -> Nil { do_print_error(string) } -if erlang { - external fn do_print_error(string: String) -> Nil = - "gleam_stdlib" "print_error" -} - -if javascript { - external fn do_print_error(String) -> Nil = - "../gleam_stdlib.mjs" "print_error" -} +@external(erlang, "gleam_stdlib", "print_error") +@external(javascript, "../gleam_stdlib.mjs", "print_error") +fn do_print_error(string string: String) -> Nil /// Writes a string to standard output, appending a newline to the end. /// @@ -66,15 +54,9 @@ pub fn println(string: String) -> Nil { do_println(string) } -if erlang { - external fn do_println(string: String) -> Nil = - "gleam_stdlib" "println" -} - -if javascript { - external fn do_println(String) -> Nil = - "../gleam_stdlib.mjs" "console_log" -} +@external(erlang, "gleam_stdlib", "println") +@external(javascript, "../gleam_stdlib.mjs", "console_log") +fn do_println(string string: String) -> Nil /// Writes a string to standard error, appending a newline to the end. /// @@ -90,15 +72,9 @@ pub fn println_error(string: String) -> Nil { do_println_error(string) } -if erlang { - external fn do_println_error(string: String) -> Nil = - "gleam_stdlib" "println_error" -} - -if javascript { - external fn do_println_error(String) -> Nil = - "../gleam_stdlib.mjs" "console_error" -} +@external(erlang, "gleam_stdlib", "println_error") +@external(javascript, "../gleam_stdlib.mjs", "console_error") +fn do_println_error(string string: String) -> Nil /// Prints a value to standard error (stderr) yielding Gleam syntax. /// @@ -136,12 +112,6 @@ pub fn debug(term: anything) -> anything { term } -if erlang { - external fn do_debug_println(string: String) -> Nil = - "gleam_stdlib" "println_error" -} - -if javascript { - external fn do_debug_println(String) -> Nil = - "../gleam_stdlib.mjs" "print_debug" -} +@external(erlang, "gleam_stdlib", "println_error") +@external(javascript, "../gleam_stdlib.mjs", "print_debug") +fn do_debug_println(string string: String) -> Nil diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam index b5bc6f5..e63ecd2 100644 --- a/src/gleam/list.gleam +++ b/src/gleam/list.gleam @@ -63,21 +63,20 @@ pub fn length(of list: List(a)) -> Int { do_length(list) } -if erlang { - external fn do_length(List(a)) -> Int = - "erlang" "length" -} +@target(erlang) +@external(erlang, "erlang", "length") +fn do_length(a: List(a)) -> Int -if javascript { - fn do_length(list: List(a)) -> Int { - do_length_acc(list, 0) - } +@target(javascript) +fn do_length(list: List(a)) -> Int { + do_length_acc(list, 0) +} - fn do_length_acc(list: List(a), count: Int) -> Int { - case list { - [_, ..list] -> do_length_acc(list, count + 1) - _ -> count - } +@target(javascript) +fn do_length_acc(list: List(a), count: Int) -> Int { + case list { + [_, ..list] -> do_length_acc(list, count + 1) + _ -> count } } @@ -111,21 +110,20 @@ pub fn reverse(xs: List(a)) -> List(a) { do_reverse(xs) } -if erlang { - external fn do_reverse(List(a)) -> List(a) = - "lists" "reverse" -} +@target(erlang) +@external(erlang, "lists", "reverse") +fn do_reverse(a: List(a)) -> List(a) -if javascript { - fn do_reverse(list) { - do_reverse_acc(list, []) - } +@target(javascript) +fn do_reverse(list) { + do_reverse_acc(list, []) +} - fn do_reverse_acc(remaining, accumulator) { - case remaining { - [] -> accumulator - [item, ..rest] -> do_reverse_acc(rest, [item, ..accumulator]) - } +@target(javascript) +fn do_reverse_acc(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> do_reverse_acc(rest, [item, ..accumulator]) } } @@ -623,21 +621,20 @@ pub fn append(first: List(a), second: List(a)) -> List(a) { do_append(first, second) } -if erlang { - external fn do_append(List(a), List(a)) -> List(a) = - "lists" "append" -} +@target(erlang) +@external(erlang, "lists", "append") +fn do_append(a: List(a), b: List(a)) -> List(a) -if javascript { - fn do_append(first: List(a), second: List(a)) -> List(a) { - do_append_acc(reverse(first), second) - } +@target(javascript) +fn do_append(first: List(a), second: List(a)) -> List(a) { + do_append_acc(reverse(first), second) +} - fn do_append_acc(first: List(a), second: List(a)) -> List(a) { - case first { - [] -> second - [item, ..rest] -> do_append_acc(rest, [item, ..second]) - } +@target(javascript) +fn do_append_acc(first: List(a), second: List(a)) -> List(a) { + case first { + [] -> second + [item, ..rest] -> do_append_acc(rest, [item, ..second]) } } diff --git a/src/gleam/map.gleam b/src/gleam/map.gleam index 6f963bc..07d9234 100644 --- a/src/gleam/map.gleam +++ b/src/gleam/map.gleam @@ -14,7 +14,7 @@ import gleam/option.{Option} /// See [the Erlang map module](https://erlang.org/doc/man/maps.html) for more /// information. /// -pub external type Map(key, value) +pub type Map(key, value) /// Determines the number of key-value pairs in the map. /// This function runs in constant time and does not need to iterate the map. @@ -35,15 +35,9 @@ pub fn size(map: Map(k, v)) -> Int { do_size(map) } -if erlang { - external fn do_size(Map(k, v)) -> Int = - "maps" "size" -} - -if javascript { - external fn do_size(Map(k, v)) -> Int = - "../gleam_stdlib.mjs" "map_size" -} +@external(erlang, "maps", "size") +@external(javascript, "../gleam_stdlib.mjs", "map_size") +fn do_size(a: Map(k, v)) -> Int /// Converts the map to a list of 2-element tuples `#(key, value)`, one for /// each key-value pair in the map. @@ -66,15 +60,9 @@ pub fn to_list(map: Map(key, value)) -> List(#(key, value)) { do_to_list(map) } -if erlang { - external fn do_to_list(Map(key, value)) -> List(#(key, value)) = - "maps" "to_list" -} - -if javascript { - external fn do_to_list(Map(key, value)) -> List(#(key, value)) = - "../gleam_stdlib.mjs" "map_to_list" -} +@external(erlang, "maps", "to_list") +@external(javascript, "../gleam_stdlib.mjs", "map_to_list") +fn do_to_list(a: Map(key, value)) -> List(#(key, value)) /// Converts a list of 2-element tuples `#(key, value)` to a map. /// @@ -85,25 +73,24 @@ pub fn from_list(list: List(#(k, v))) -> Map(k, v) { do_from_list(list) } -if erlang { - external fn do_from_list(List(#(key, value))) -> Map(key, value) = - "maps" "from_list" -} +@target(erlang) +@external(erlang, "maps", "from_list") +fn do_from_list(a: List(#(key, value))) -> Map(key, value) -if javascript { - fn fold_list_of_pair( - over list: List(#(k, v)), - from initial: Map(k, v), - ) -> Map(k, v) { - case list { - [] -> initial - [x, ..rest] -> fold_list_of_pair(rest, insert(initial, x.0, x.1)) - } +@target(javascript) +fn fold_list_of_pair( + over list: List(#(k, v)), + from initial: Map(k, v), +) -> Map(k, v) { + case list { + [] -> initial + [x, ..rest] -> fold_list_of_pair(rest, insert(initial, x.0, x.1)) } +} - fn do_from_list(list: List(#(k, v))) -> Map(k, v) { - fold_list_of_pair(list, new()) - } +@target(javascript) +fn do_from_list(list: List(#(k, v))) -> Map(k, v) { + fold_list_of_pair(list, new()) } /// Determines whether or not a value present in the map for a given key. @@ -124,15 +111,13 @@ pub fn has_key(map: Map(k, v), key: k) -> Bool { do_has_key(key, map) } -if erlang { - external fn do_has_key(key, Map(key, v)) -> Bool = - "maps" "is_key" -} +@target(erlang) +@external(erlang, "maps", "is_key") +fn do_has_key(a: key, b: Map(key, v)) -> Bool -if javascript { - fn do_has_key(key: k, map: Map(k, v)) -> Bool { - get(map, key) != Error(Nil) - } +@target(javascript) +fn do_has_key(key: k, map: Map(k, v)) -> Bool { + get(map, key) != Error(Nil) } /// Creates a fresh map that contains no values. @@ -141,15 +126,9 @@ pub fn new() -> Map(key, value) { do_new() } -if erlang { - external fn do_new() -> Map(key, value) = - "maps" "new" -} - -if javascript { - external fn do_new() -> Map(key, value) = - "../gleam_stdlib.mjs" "new_map" -} +@external(erlang, "maps", "new") +@external(javascript, "../gleam_stdlib.mjs", "new_map") +fn do_new() -> Map(key, value) /// Fetches a value from a map for a given key. /// @@ -172,15 +151,9 @@ pub fn get(from: Map(key, value), get: key) -> Result(value, Nil) { do_get(from, get) } -if erlang { - external fn do_get(Map(key, value), key) -> Result(value, Nil) = - "gleam_stdlib" "map_get" -} - -if javascript { - external fn do_get(Map(key, value), key) -> Result(value, Nil) = - "../gleam_stdlib.mjs" "map_get" -} +@external(erlang, "gleam_stdlib", "map_get") +@external(javascript, "../gleam_stdlib.mjs", "map_get") +fn do_get(a: Map(key, value), b: key) -> Result(value, Nil) /// Inserts a value into the map with the given key. /// @@ -203,15 +176,9 @@ pub fn insert(into map: Map(k, v), for key: k, insert value: v) -> Map(k, v) { do_insert(key, value, map) } -if erlang { - external fn do_insert(key, value, Map(key, value)) -> Map(key, value) = - "maps" "put" -} - -if javascript { - external fn do_insert(key, value, Map(key, value)) -> Map(key, value) = - "../gleam_stdlib.mjs" "map_insert" -} +@external(erlang, "maps", "put") +@external(javascript, "../gleam_stdlib.mjs", "map_insert") +fn do_insert(a: key, b: value, c: Map(key, value)) -> Map(key, value) /// Updates all values in a given map by calling a given function on each key /// and value. @@ -229,17 +196,15 @@ pub fn map_values(in map: Map(k, v), with fun: fn(k, v) -> w) -> Map(k, w) { do_map_values(fun, map) } -if erlang { - external fn do_map_values(fn(key, value) -> b, Map(key, value)) -> Map(key, b) = - "maps" "map" -} +@target(erlang) +@external(erlang, "maps", "map") +fn do_map_values(a: fn(key, value) -> b, b: Map(key, value)) -> Map(key, b) -if javascript { - fn do_map_values(f: fn(key, value) -> b, map: Map(key, value)) -> Map(key, b) { - let f = fn(map, k, v) { insert(map, k, f(k, v)) } - map - |> fold(from: new(), with: f) - } +@target(javascript) +fn do_map_values(f: fn(key, value) -> b, map: Map(key, value)) -> Map(key, b) { + let f = fn(map, k, v) { insert(map, k, f(k, v)) } + map + |> fold(from: new(), with: f) } /// Gets a list of all keys in a given map. @@ -259,32 +224,32 @@ pub fn keys(map: Map(keys, v)) -> List(keys) { do_keys(map) } -if erlang { - external fn do_keys(Map(keys, v)) -> List(keys) = - "maps" "keys" -} +@target(erlang) +@external(erlang, "maps", "keys") +fn do_keys(a: Map(keys, v)) -> List(keys) -if javascript { - fn reverse_and_concat(remaining, accumulator) { - case remaining { - [] -> accumulator - [item, ..rest] -> reverse_and_concat(rest, [item, ..accumulator]) - } +@target(javascript) +fn reverse_and_concat(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> reverse_and_concat(rest, [item, ..accumulator]) } +} - fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) { - case list { - [] -> reverse_and_concat(acc, []) - [x, ..xs] -> do_keys_acc(xs, [x.0, ..acc]) - } +@target(javascript) +fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_keys_acc(xs, [x.0, ..acc]) } +} - fn do_keys(map: Map(k, v)) -> List(k) { - let list_of_pairs = - map - |> to_list - do_keys_acc(list_of_pairs, []) - } +@target(javascript) +fn do_keys(map: Map(k, v)) -> List(k) { + let list_of_pairs = + map + |> to_list + do_keys_acc(list_of_pairs, []) } /// Gets a list of all values in a given map. @@ -304,25 +269,24 @@ pub fn values(map: Map(k, values)) -> List(values) { do_values(map) } -if erlang { - external fn do_values(Map(k, values)) -> List(values) = - "maps" "values" -} +@target(erlang) +@external(erlang, "maps", "values") +fn do_values(a: Map(k, values)) -> List(values) -if javascript { - fn do_values_acc(list: List(#(k, v)), acc: List(v)) -> List(v) { - case list { - [] -> reverse_and_concat(acc, []) - [x, ..xs] -> do_values_acc(xs, [x.1, ..acc]) - } +@target(javascript) +fn do_values_acc(list: List(#(k, v)), acc: List(v)) -> List(v) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_values_acc(xs, [x.1, ..acc]) } +} - fn do_values(map: Map(k, v)) -> List(v) { - let list_of_pairs = - map - |> to_list - do_values_acc(list_of_pairs, []) - } +@target(javascript) +fn do_values(map: Map(k, v)) -> List(v) { + let list_of_pairs = + map + |> to_list + do_values_acc(list_of_pairs, []) } /// Creates a new map from a given map, minus any entries that a given function @@ -346,28 +310,20 @@ pub fn filter(in map: Map(k, v), for property: fn(k, v) -> Bool) -> Map(k, v) { do_filter(property, map) } -if erlang { - external fn do_filter( - fn(key, value) -> Bool, - Map(key, value), - ) -> Map(key, value) = - "maps" "filter" -} - -if javascript { - fn do_filter( - f: fn(key, value) -> Bool, - map: Map(key, value), - ) -> Map(key, value) { - let insert = fn(map, k, v) { - case f(k, v) { - True -> insert(map, k, v) - _ -> map - } +@target(erlang) +@external(erlang, "maps", "filter") +fn do_filter(a: fn(key, value) -> Bool, b: Map(key, value)) -> Map(key, value) + +@target(javascript) +fn do_filter(f: fn(key, value) -> Bool, map: Map(key, value)) -> Map(key, value) { + let insert = fn(map, k, v) { + case f(k, v) { + True -> insert(map, k, v) + _ -> map } - map - |> fold(from: new(), with: insert) } + map + |> fold(from: new(), with: insert) } /// Creates a new map from a given map, only including any entries for which the @@ -391,34 +347,33 @@ pub fn take(from map: Map(k, v), keeping desired_keys: List(k)) -> Map(k, v) { do_take(desired_keys, map) } -if erlang { - external fn do_take(List(k), Map(k, v)) -> Map(k, v) = - "maps" "with" -} +@target(erlang) +@external(erlang, "maps", "with") +fn do_take(a: List(k), b: Map(k, v)) -> Map(k, v) -if javascript { - fn insert_taken( - map: Map(k, v), - desired_keys: List(k), - acc: Map(k, v), - ) -> Map(k, v) { - let insert = fn(taken, key) { - case get(map, key) { - Ok(value) -> insert(taken, key, value) - _ -> taken - } - } - case desired_keys { - [] -> acc - [x, ..xs] -> insert_taken(map, xs, insert(acc, x)) +@target(javascript) +fn insert_taken( + map: Map(k, v), + desired_keys: List(k), + acc: Map(k, v), +) -> Map(k, v) { + let insert = fn(taken, key) { + case get(map, key) { + Ok(value) -> insert(taken, key, value) + _ -> taken } } - - fn do_take(desired_keys: List(k), map: Map(k, v)) -> Map(k, v) { - insert_taken(map, desired_keys, new()) + case desired_keys { + [] -> acc + [x, ..xs] -> insert_taken(map, xs, insert(acc, x)) } } +@target(javascript) +fn do_take(desired_keys: List(k), map: Map(k, v)) -> Map(k, v) { + insert_taken(map, desired_keys, new()) +} + /// Creates a new map from a pair of given maps by combining their entries. /// /// If there are entries with the same keys in both maps the entry from the @@ -437,28 +392,28 @@ pub fn merge(into map: Map(k, v), from new_entries: Map(k, v)) -> Map(k, v) { do_merge(map, new_entries) } -if erlang { - external fn do_merge(Map(k, v), Map(k, v)) -> Map(k, v) = - "maps" "merge" -} +@target(erlang) +@external(erlang, "maps", "merge") +fn do_merge(a: Map(k, v), b: Map(k, v)) -> Map(k, v) -if javascript { - fn insert_pair(map: Map(k, v), pair: #(k, v)) -> Map(k, v) { - insert(map, pair.0, pair.1) - } +@target(javascript) +fn insert_pair(map: Map(k, v), pair: #(k, v)) -> Map(k, v) { + insert(map, pair.0, pair.1) +} - fn fold_inserts(new_entries: List(#(k, v)), map: Map(k, v)) -> Map(k, v) { - case new_entries { - [] -> map - [x, ..xs] -> fold_inserts(xs, insert_pair(map, x)) - } +@target(javascript) +fn fold_inserts(new_entries: List(#(k, v)), map: Map(k, v)) -> Map(k, v) { + case new_entries { + [] -> map + [x, ..xs] -> fold_inserts(xs, insert_pair(map, x)) } +} - fn do_merge(map: Map(k, v), new_entries: Map(k, v)) -> Map(k, v) { - new_entries - |> to_list - |> fold_inserts(map) - } +@target(javascript) +fn do_merge(map: Map(k, v), new_entries: Map(k, v)) -> Map(k, v) { + new_entries + |> to_list + |> fold_inserts(map) } /// Creates a new map from a given map with all the same entries except for the @@ -480,15 +435,9 @@ pub fn delete(from map: Map(k, v), delete key: k) -> Map(k, v) { do_delete(key, map) } -if erlang { - external fn do_delete(k, Map(k, v)) -> Map(k, v) = - "maps" "remove" -} - -if javascript { - external fn do_delete(k, Map(k, v)) -> Map(k, v) = - "../gleam_stdlib.mjs" "map_remove" -} +@external(erlang, "maps", "remove") +@external(javascript, "../gleam_stdlib.mjs", "map_remove") +fn do_delete(a: k, b: Map(k, v)) -> Map(k, v) /// Creates a new map from a given map with all the same entries except any with /// keys found in a given list. diff --git a/src/gleam/regex.gleam b/src/gleam/regex.gleam index f1161cc..10b09e2 100644 --- a/src/gleam/regex.gleam +++ b/src/gleam/regex.gleam @@ -5,7 +5,7 @@ import gleam/option.{Option} -pub external type Regex +pub type Regex /// The details about a particular match: /// @@ -59,15 +59,9 @@ pub fn compile( do_compile(pattern, options) } -if erlang { - external fn do_compile(String, with: Options) -> Result(Regex, CompileError) = - "gleam_stdlib" "compile_regex" -} - -if javascript { - external fn do_compile(String, with: Options) -> Result(Regex, CompileError) = - "../gleam_stdlib.mjs" "compile_regex" -} +@external(erlang, "gleam_stdlib", "compile_regex") +@external(javascript, "../gleam_stdlib.mjs", "compile_regex") +fn do_compile(a: String, with with: Options) -> Result(Regex, CompileError) /// Creates a new `Regex`. /// @@ -117,15 +111,9 @@ pub fn check(with regex: Regex, content content: String) -> Bool { do_check(regex, content) } -if erlang { - external fn do_check(Regex, String) -> Bool = - "gleam_stdlib" "regex_check" -} - -if javascript { - external fn do_check(Regex, String) -> Bool = - "../gleam_stdlib.mjs" "regex_check" -} +@external(erlang, "gleam_stdlib", "regex_check") +@external(javascript, "../gleam_stdlib.mjs", "regex_check") +fn do_check(a: Regex, b: String) -> Bool /// Splits a string. /// @@ -141,20 +129,19 @@ pub fn split(with regex: Regex, content string: String) -> List(String) { do_split(regex, string) } -if erlang { - external fn do_split(Regex, String) -> List(String) = - "gleam_stdlib" "regex_split" -} - -if javascript { - fn do_split(regex, string) -> List(String) { - js_split(string, regex) - } +@target(erlang) +@external(erlang, "gleam_stdlib", "regex_split") +fn do_split(a: Regex, b: String) -> List(String) - external fn js_split(String, Regex) -> List(String) = - "../gleam_stdlib.mjs" "split" +@target(javascript) +fn do_split(regex, string) -> List(String) { + js_split(string, regex) } +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split") +fn js_split(a: String, b: Regex) -> List(String) + /// Collects all matches of the regular expression. /// /// ## Examples @@ -222,12 +209,6 @@ pub fn scan(with regex: Regex, content string: String) -> List(Match) { do_scan(regex, string) } -if erlang { - external fn do_scan(Regex, String) -> List(Match) = - "gleam_stdlib" "regex_scan" -} - -if javascript { - external fn do_scan(Regex, String) -> List(Match) = - "../gleam_stdlib.mjs" "regex_scan" -} +@external(erlang, "gleam_stdlib", "regex_scan") +@external(javascript, "../gleam_stdlib.mjs", "regex_scan") +fn do_scan(a: Regex, b: String) -> List(Match) diff --git a/src/gleam/set.gleam b/src/gleam/set.gleam index 2440986..9ca8e44 100644 --- a/src/gleam/set.gleam +++ b/src/gleam/set.gleam @@ -2,21 +2,21 @@ import gleam/list import gleam/map.{Map} import gleam/result -if erlang { - // A list is used as the map value as an empty list has the smallest - // representation in Erlang's binary format - type Token = - List(Nil) +// A list is used as the map value as an empty list has the smallest +// representation in Erlang's binary format +@target(erlang) +type Token = + List(Nil) - const token = [] -} +@target(erlang) +const token = [] -if javascript { - type Token = - Nil +@target(javascript) +type Token = + Nil - const token = Nil -} +@target(javascript) +const token = Nil /// A set is a collection of unique members of the same type. /// diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam index 2e6f28d..7cf4243 100644 --- a/src/gleam/string.gleam +++ b/src/gleam/string.gleam @@ -6,12 +6,12 @@ import gleam/list import gleam/option.{None, Option, Some} import gleam/order import gleam/string_builder.{StringBuilder} - -if erlang { - import gleam/bit_string - import gleam/dynamic.{Dynamic} - import gleam/result -} +@target(erlang) +import gleam/bit_string +@target(erlang) +import gleam/dynamic.{Dynamic} +@target(erlang) +import gleam/result /// Determines if a `String` is empty. /// @@ -57,15 +57,9 @@ pub fn length(string: String) -> Int { do_length(string) } -if erlang { - external fn do_length(String) -> Int = - "string" "length" -} - -if javascript { - external fn do_length(String) -> Int = - "../gleam_stdlib.mjs" "string_length" -} +@external(erlang, "string", "length") +@external(javascript, "../gleam_stdlib.mjs", "string_length") +fn do_length(a: String) -> Int /// Reverses a `String`. /// @@ -83,22 +77,20 @@ pub fn reverse(string: String) -> String { do_reverse(string) } -if erlang { - fn do_reverse(string: String) -> String { - string - |> string_builder.from_string - |> string_builder.reverse - |> string_builder.to_string - } +@target(erlang) +fn do_reverse(string: String) -> String { + string + |> string_builder.from_string + |> string_builder.reverse + |> string_builder.to_string } -if javascript { - fn do_reverse(string: String) -> String { - string - |> to_graphemes - |> list.reverse - |> concat - } +@target(javascript) +fn do_reverse(string: String) -> String { + string + |> to_graphemes + |> list.reverse + |> concat } /// Creates a new `String` by replacing all occurrences of a given substring. @@ -142,15 +134,9 @@ pub fn lowercase(string: String) -> String { do_lowercase(string) } -if erlang { - external fn do_lowercase(String) -> String = - "string" "lowercase" -} - -if javascript { - external fn do_lowercase(String) -> String = - "../gleam_stdlib.mjs" "lowercase" -} +@external(erlang, "string", "lowercase") +@external(javascript, "../gleam_stdlib.mjs", "lowercase") +fn do_lowercase(a: String) -> String /// Creates a new `String` with all the graphemes in the input `String` converted to /// uppercase. @@ -168,15 +154,9 @@ pub fn uppercase(string: String) -> String { do_uppercase(string) } -if erlang { - external fn do_uppercase(String) -> String = - "string" "uppercase" -} - -if javascript { - external fn do_uppercase(String) -> String = - "../gleam_stdlib.mjs" "uppercase" -} +@external(erlang, "string", "uppercase") +@external(javascript, "../gleam_stdlib.mjs", "uppercase") +fn do_uppercase(a: String) -> String /// Compares two `String`s to see which is "larger" by comparing their graphemes. /// @@ -205,15 +185,9 @@ pub fn compare(a: String, b: String) -> order.Order { } } -if erlang { - external fn less_than(String, String) -> Bool = - "gleam_stdlib" "less_than" -} - -if javascript { - external fn less_than(String, String) -> Bool = - "../gleam_stdlib.mjs" "less_than" -} +@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 and end grapheme indexes. Negative indexes /// are taken starting from the *end* of the list. @@ -262,19 +236,17 @@ pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String } } -if erlang { - external fn do_slice(String, Int, Int) -> String = - "string" "slice" -} +@target(erlang) +@external(erlang, "string", "slice") +fn do_slice(a: String, b: Int, c: Int) -> String -if javascript { - fn do_slice(string: String, idx: Int, len: Int) -> String { - string - |> to_graphemes - |> list.drop(idx) - |> list.take(len) - |> concat - } +@target(javascript) +fn do_slice(string: String, idx: Int, len: Int) -> String { + string + |> to_graphemes + |> list.drop(idx) + |> list.take(len) + |> concat } /// Drops contents of the first `String` that occur before the second `String`. @@ -291,22 +263,21 @@ pub fn crop(from string: String, before substring: String) -> String { do_crop(string, substring) } -if erlang { - fn do_crop(string: String, substring: String) -> String { - string - |> erl_contains(substring) - |> dynamic.string() - |> result.unwrap(string) - } - - external fn erl_contains(String, String) -> Dynamic = - "string" "find" +@target(erlang) +fn do_crop(string: String, substring: String) -> String { + string + |> erl_contains(substring) + |> dynamic.string() + |> result.unwrap(string) } -if javascript { - external fn do_crop(String, String) -> String = - "../gleam_stdlib.mjs" "crop_string" -} +@target(erlang) +@external(erlang, "string", "find") +fn erl_contains(a: String, b: String) -> Dynamic + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "crop_string") +fn do_crop(a: String, b: String) -> String /// Drops *n* graphemes from the left side of a `String`. /// @@ -363,24 +334,23 @@ pub fn contains(does haystack: String, contain needle: String) -> Bool { do_contains(haystack, needle) } -if erlang { - fn do_contains(haystack: String, needle: String) -> Bool { - haystack - |> erl_contains(needle) - |> dynamic.bit_string - |> result.is_ok - } +@target(erlang) +fn do_contains(haystack: String, needle: String) -> Bool { + haystack + |> erl_contains(needle) + |> dynamic.bit_string + |> result.is_ok } -if javascript { - fn do_contains(haystack: String, needle: String) -> Bool { - index_of(haystack, needle) != -1 - } - - external fn index_of(String, String) -> Int = - "../gleam_stdlib.mjs" "index_of" +@target(javascript) +fn do_contains(haystack: String, needle: String) -> Bool { + index_of(haystack, needle) != -1 } +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "index_of") +fn index_of(a: String, b: String) -> Int + /// Checks whether the first `String` starts with the second one. /// /// ## Examples @@ -394,15 +364,9 @@ pub fn starts_with(string: String, prefix: String) -> Bool { do_starts_with(string, prefix) } -if erlang { - external fn do_starts_with(String, String) -> Bool = - "gleam_stdlib" "string_starts_with" -} - -if javascript { - external fn do_starts_with(String, String) -> Bool = - "../gleam_stdlib.mjs" "starts_with" -} +@external(erlang, "gleam_stdlib", "string_starts_with") +@external(javascript, "../gleam_stdlib.mjs", "starts_with") +fn do_starts_with(a: String, b: String) -> Bool /// Checks whether the first `String` ends with the second one. /// @@ -417,15 +381,9 @@ pub fn ends_with(string: String, suffix: String) -> Bool { do_ends_with(string, suffix) } -if erlang { - external fn do_ends_with(String, String) -> Bool = - "gleam_stdlib" "string_ends_with" -} - -if javascript { - external fn do_ends_with(String, String) -> Bool = - "../gleam_stdlib.mjs" "ends_with" -} +@external(erlang, "gleam_stdlib", "string_ends_with") +@external(javascript, "../gleam_stdlib.mjs", "ends_with") +fn do_ends_with(a: String, b: String) -> Bool /// Creates a list of `String`s by splitting a given string on a given substring. /// @@ -470,28 +428,24 @@ pub fn split_once( do_split_once(x, substring) } -if erlang { - external fn erl_split(String, String) -> List(String) = - "string" "split" - - fn do_split_once( - x: String, - substring: String, - ) -> Result(#(String, String), Nil) { - case erl_split(x, substring) { - [first, rest] -> Ok(#(first, rest)) - _ -> Error(Nil) - } +@target(erlang) +@external(erlang, "string", "split") +fn erl_split(a: String, b: String) -> List(String) + +@target(erlang) +fn do_split_once(x: String, substring: String) -> Result(#(String, String), Nil) { + case erl_split(x, substring) { + [first, rest] -> Ok(#(first, rest)) + _ -> Error(Nil) } } -if javascript { - external fn do_split_once( - x: String, - substring: String, - ) -> Result(#(String, String), Nil) = - "../gleam_stdlib.mjs" "split_once" -} +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split_once") +fn do_split_once( + x x: String, + substring substring: String, +) -> Result(#(String, String), Nil) /// Creates a new `String` by joining two `String`s together. /// @@ -565,18 +519,16 @@ pub fn join(strings: List(String), with separator: String) -> String { do_join(strings, separator) } -if erlang { - fn do_join(strings: List(String), separator: String) -> String { - strings - |> list.intersperse(with: separator) - |> concat - } +@target(erlang) +fn do_join(strings: List(String), separator: String) -> String { + strings + |> list.intersperse(with: separator) + |> concat } -if javascript { - external fn do_join(strings: List(String), string: String) -> String = - "../gleam_stdlib.mjs" "join" -} +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "join") +fn do_join(strings strings: List(String), string string: String) -> String /// Pads a `String` on the left until it has at least given number of graphemes. /// @@ -660,26 +612,26 @@ pub fn trim(string: String) -> String { do_trim(string) } -if erlang { - fn do_trim(string: String) -> String { - erl_trim(string, Both) - } - - type Direction { - Leading - Trailing - Both - } - - external fn erl_trim(String, Direction) -> String = - "string" "trim" +@target(erlang) +fn do_trim(string: String) -> String { + erl_trim(string, Both) } -if javascript { - external fn do_trim(string: String) -> String = - "../gleam_stdlib.mjs" "trim" +@target(erlang) +type Direction { + Leading + Trailing + Both } +@target(erlang) +@external(erlang, "string", "trim") +fn erl_trim(a: String, b: Direction) -> String + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim") +fn do_trim(string string: String) -> String + /// Removes whitespace on the left of a `String`. /// /// ## Examples @@ -693,16 +645,14 @@ pub fn trim_left(string: String) -> String { do_trim_left(string) } -if erlang { - fn do_trim_left(string: String) -> String { - erl_trim(string, Leading) - } +@target(erlang) +fn do_trim_left(string: String) -> String { + erl_trim(string, Leading) } -if javascript { - external fn do_trim_left(string: String) -> String = - "../gleam_stdlib.mjs" "trim_left" -} +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim_left") +fn do_trim_left(string string: String) -> String /// Removes whitespace on the right of a `String`. /// @@ -717,16 +667,14 @@ pub fn trim_right(string: String) -> String { do_trim_right(string) } -if erlang { - fn do_trim_right(string: String) -> String { - erl_trim(string, Trailing) - } +@target(erlang) +fn do_trim_right(string: String) -> String { + erl_trim(string, Trailing) } -if javascript { - external fn do_trim_right(string: String) -> String = - "../gleam_stdlib.mjs" "trim_right" -} +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim_right") +fn do_trim_right(string string: String) -> String /// 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. @@ -747,15 +695,9 @@ pub fn pop_grapheme(string: String) -> Result(#(String, String), Nil) { do_pop_grapheme(string) } -if erlang { - external fn do_pop_grapheme(string: String) -> Result(#(String, String), Nil) = - "gleam_stdlib" "string_pop_grapheme" -} - -if javascript { - external fn do_pop_grapheme(string: String) -> Result(#(String, String), Nil) = - "../gleam_stdlib.mjs" "pop_grapheme" -} +@external(erlang, "gleam_stdlib", "string_pop_grapheme") +@external(javascript, "../gleam_stdlib.mjs", "pop_grapheme") +fn do_pop_grapheme(string string: String) -> Result(#(String, String), Nil) /// Converts a `String` to a list of /// [graphemes](https://en.wikipedia.org/wiki/Grapheme). @@ -777,15 +719,9 @@ fn do_to_graphemes(string: String, acc: List(String)) -> List(String) { } } -if erlang { - external fn unsafe_int_to_utf_codepoint(Int) -> UtfCodepoint = - "gleam_stdlib" "identity" -} - -if javascript { - external fn unsafe_int_to_utf_codepoint(Int) -> UtfCodepoint = - "../gleam_stdlib.mjs" "codepoint" -} +@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`. /// @@ -812,35 +748,35 @@ pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) { do_to_utf_codepoints(string) } -if erlang { - fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { - do_to_utf_codepoints_impl(bit_string.from_string(string), []) - |> list.reverse - } - - fn do_to_utf_codepoints_impl( - bit_string: BitString, - acc: List(UtfCodepoint), - ) -> List(UtfCodepoint) { - case bit_string { - <<first:utf8_codepoint, rest:binary>> -> - do_to_utf_codepoints_impl(rest, [first, ..acc]) - <<>> -> acc - } - } +@target(erlang) +fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { + do_to_utf_codepoints_impl(bit_string.from_string(string), []) + |> list.reverse } -if javascript { - fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { - string - |> string_to_codepoint_integer_list - |> list.map(unsafe_int_to_utf_codepoint) +@target(erlang) +fn do_to_utf_codepoints_impl( + bit_string: BitString, + acc: List(UtfCodepoint), +) -> List(UtfCodepoint) { + case bit_string { + <<first:utf8_codepoint, rest:binary>> -> + do_to_utf_codepoints_impl(rest, [first, ..acc]) + <<>> -> acc } +} - external fn string_to_codepoint_integer_list(String) -> List(Int) = - "../gleam_stdlib.mjs" "string_to_codepoint_integer_list" +@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(a: String) -> List(Int) + /// Converts a `List` of `UtfCodepoint`s to a `String`. /// /// See <https://en.wikipedia.org/wiki/Code_point> and @@ -866,38 +802,38 @@ pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String { do_from_utf_codepoints(utf_codepoints) } -if erlang { - fn do_from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String { - let assert Ok(string) = - do_from_utf_codepoints_impl(utf_codepoints, bit_string.from_string("")) - |> bit_string.to_string - string - } - - fn do_from_utf_codepoints_impl( - utf_codepoints: List(UtfCodepoint), - acc: BitString, - ) -> BitString { - case utf_codepoints { - [first, ..rest] -> - do_from_utf_codepoints_impl( - rest, - <<acc:bit_string, first:utf8_codepoint>>, - ) - [] -> acc - } - } +@target(erlang) +fn do_from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String { + let assert Ok(string) = + do_from_utf_codepoints_impl(utf_codepoints, bit_string.from_string("")) + |> bit_string.to_string + string } -if javascript { - fn do_from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String { - utf_codepoint_list_to_string(utf_codepoints) +@target(erlang) +fn do_from_utf_codepoints_impl( + utf_codepoints: List(UtfCodepoint), + acc: BitString, +) -> BitString { + case utf_codepoints { + [first, ..rest] -> + do_from_utf_codepoints_impl( + rest, + <<acc:bit_string, first:utf8_codepoint>>, + ) + [] -> acc } +} - external fn utf_codepoint_list_to_string(List(UtfCodepoint)) -> String = - "../gleam_stdlib.mjs" "utf_codepoint_list_to_string" +@target(javascript) +fn do_from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String { + utf_codepoint_list_to_string(utf_codepoints) } +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_list_to_string") +fn utf_codepoint_list_to_string(a: List(UtfCodepoint)) -> String + /// Converts an integer to a `UtfCodepoint`. /// /// Returns an `Error` if the integer does not represent a valid UTF codepoint. @@ -924,15 +860,9 @@ pub fn utf_codepoint_to_int(cp: UtfCodepoint) -> Int { do_utf_codepoint_to_int(cp) } -if erlang { - external fn do_utf_codepoint_to_int(cp: UtfCodepoint) -> Int = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_utf_codepoint_to_int(cp: UtfCodepoint) -> Int = - "../gleam_stdlib.mjs" "utf_codepoint_to_int" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_to_int") +fn do_utf_codepoint_to_int(cp cp: UtfCodepoint) -> Int /// Converts a `String` into `Option(String)` where an empty `String` becomes /// `None`. @@ -1027,15 +957,9 @@ pub fn inspect(term: anything) -> String { |> string_builder.to_string } -if javascript { - external fn do_inspect(term: anything) -> StringBuilder = - "../gleam.mjs" "inspect" -} - -if erlang { - external fn do_inspect(term: anything) -> StringBuilder = - "gleam_stdlib" "inspect" -} +@external(erlang, "gleam_stdlib", "inspect") +@external(javascript, "../gleam.mjs", "inspect") +fn do_inspect(term term: anything) -> StringBuilder /// Returns the number of bytes in a `String`. /// @@ -1046,12 +970,6 @@ pub fn byte_size(string: String) -> Int { do_byte_size(string) } -if javascript { - external fn do_byte_size(String) -> Int = - "../gleam_stdlib.mjs" "byte_size" -} - -if erlang { - external fn do_byte_size(String) -> Int = - "erlang" "byte_size" -} +@external(erlang, "erlang", "byte_size") +@external(javascript, "../gleam_stdlib.mjs", "byte_size") +fn do_byte_size(a: String) -> Int diff --git a/src/gleam/string_builder.gleam b/src/gleam/string_builder.gleam index bb88455..5792ca8 100644 --- a/src/gleam/string_builder.gleam +++ b/src/gleam/string_builder.gleam @@ -14,7 +14,7 @@ import gleam/list /// On Erlang this type is compatible with Erlang's iodata. On JavaScript this /// type is compatible with normal strings. /// -pub external type StringBuilder +pub type StringBuilder /// Create an empty `StringBuilder`. Useful as the start of a pipe chaining many /// builders together. @@ -64,15 +64,9 @@ pub fn append_builder( do_append(builder, suffix) } -if erlang { - external fn do_append(StringBuilder, StringBuilder) -> StringBuilder = - "gleam_stdlib" "iodata_append" -} - -if javascript { - external fn do_append(StringBuilder, StringBuilder) -> StringBuilder = - "../gleam_stdlib.mjs" "add" -} +@external(erlang, "gleam_stdlib", "iodata_append") +@external(javascript, "../gleam_stdlib.mjs", "add") +fn do_append(a: StringBuilder, b: StringBuilder) -> StringBuilder /// Converts a list of strings into a builder. /// @@ -82,15 +76,9 @@ pub fn from_strings(strings: List(String)) -> StringBuilder { do_from_strings(strings) } -if erlang { - external fn do_from_strings(List(String)) -> StringBuilder = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_from_strings(List(String)) -> StringBuilder = - "../gleam_stdlib.mjs" "concat" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "concat") +fn do_from_strings(a: List(String)) -> StringBuilder /// Joins a list of builders into a single builder. /// @@ -100,15 +88,9 @@ pub fn concat(builders: List(StringBuilder)) -> StringBuilder { do_concat(builders) } -if erlang { - external fn do_concat(List(StringBuilder)) -> StringBuilder = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_concat(List(StringBuilder)) -> StringBuilder = - "../gleam_stdlib.mjs" "concat" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "concat") +fn do_concat(a: List(StringBuilder)) -> StringBuilder /// Converts a string into a builder. /// @@ -118,15 +100,9 @@ pub fn from_string(string: String) -> StringBuilder { do_from_string(string) } -if erlang { - external fn do_from_string(String) -> StringBuilder = - "gleam_stdlib" "identity" -} - -if javascript { - external fn do_from_string(String) -> StringBuilder = - "../gleam_stdlib.mjs" "identity" -} +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_from_string(a: String) -> StringBuilder /// Turns an `StringBuilder` into a `String` /// @@ -137,15 +113,9 @@ pub fn to_string(builder: StringBuilder) -> String { do_to_string(builder) } -if erlang { - external fn do_to_string(StringBuilder) -> String = - "unicode" "characters_to_binary" -} - -if javascript { - external fn do_to_string(StringBuilder) -> String = - "../gleam_stdlib.mjs" "identity" -} +@external(erlang, "unicode", "characters_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_to_string(a: StringBuilder) -> String /// Returns the size of the `StringBuilder` in bytes. /// @@ -153,15 +123,9 @@ pub fn byte_size(builder: StringBuilder) -> Int { do_byte_size(builder) } -if erlang { - external fn do_byte_size(StringBuilder) -> Int = - "erlang" "iolist_size" -} - -if javascript { - external fn do_byte_size(StringBuilder) -> Int = - "../gleam_stdlib.mjs" "length" -} +@external(erlang, "erlang", "iolist_size") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn do_byte_size(a: StringBuilder) -> Int /// Joins the given builders into a new builder separated with the given string /// @@ -178,15 +142,9 @@ pub fn lowercase(builder: StringBuilder) -> StringBuilder { do_lowercase(builder) } -if erlang { - external fn do_lowercase(StringBuilder) -> StringBuilder = - "string" "lowercase" -} - -if javascript { - external fn do_lowercase(StringBuilder) -> StringBuilder = - "../gleam_stdlib.mjs" "lowercase" -} +@external(erlang, "string", "lowercase") +@external(javascript, "../gleam_stdlib.mjs", "lowercase") +fn do_lowercase(a: StringBuilder) -> StringBuilder /// Converts a builder to a new builder where the contents have been /// uppercased. @@ -195,15 +153,9 @@ pub fn uppercase(builder: StringBuilder) -> StringBuilder { do_uppercase(builder) } -if erlang { - external fn do_uppercase(StringBuilder) -> StringBuilder = - "string" "uppercase" -} - -if javascript { - external fn do_uppercase(StringBuilder) -> StringBuilder = - "../gleam_stdlib.mjs" "uppercase" -} +@external(erlang, "string", "uppercase") +@external(javascript, "../gleam_stdlib.mjs", "uppercase") +fn do_uppercase(a: StringBuilder) -> StringBuilder /// Converts a builder to a new builder with the contents reversed. /// @@ -211,50 +163,49 @@ pub fn reverse(builder: StringBuilder) -> StringBuilder { do_reverse(builder) } -if erlang { - external fn do_reverse(StringBuilder) -> StringBuilder = - "string" "reverse" -} +@target(erlang) +@external(erlang, "string", "reverse") +fn do_reverse(a: StringBuilder) -> StringBuilder -if javascript { - fn do_reverse(builder: StringBuilder) -> StringBuilder { - builder - |> to_string - |> do_to_graphemes - |> list.reverse - |> from_strings - } - - external fn do_to_graphemes(string: String) -> List(String) = - "../gleam_stdlib.mjs" "graphemes" +@target(javascript) +fn do_reverse(builder: StringBuilder) -> StringBuilder { + builder + |> to_string + |> do_to_graphemes + |> list.reverse + |> from_strings } +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "graphemes") +fn do_to_graphemes(string string: String) -> List(String) + /// Splits a builder on a given pattern into a list of builders. /// pub fn split(iodata: StringBuilder, on pattern: String) -> List(StringBuilder) { do_split(iodata, pattern) } -if erlang { - type Direction { - All - } +@target(erlang) +type Direction { + All +} - external fn erl_split(StringBuilder, String, Direction) -> List(StringBuilder) = - "string" "split" +@target(erlang) +@external(erlang, "string", "split") +fn erl_split(a: StringBuilder, b: String, c: Direction) -> List(StringBuilder) - fn do_split(iodata: StringBuilder, pattern: String) -> List(StringBuilder) { - erl_split(iodata, pattern, All) - } +@target(erlang) +fn do_split(iodata: StringBuilder, pattern: String) -> List(StringBuilder) { + erl_split(iodata, pattern, All) } -if javascript { - external fn do_split( - builder: StringBuilder, - pattern: String, - ) -> List(StringBuilder) = - "../gleam_stdlib.mjs" "split" -} +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split") +fn do_split( + builder builder: StringBuilder, + pattern pattern: String, +) -> List(StringBuilder) /// Replaces all instances of a pattern with a given string substitute. /// @@ -266,28 +217,27 @@ pub fn replace( do_replace(builder, pattern, substitute) } -if erlang { - fn do_replace( - iodata: StringBuilder, - pattern: String, - substitute: String, - ) -> StringBuilder { - erl_replace(iodata, pattern, substitute, All) - } - - external fn erl_replace( - StringBuilder, - String, - String, - Direction, - ) -> StringBuilder = - "string" "replace" +@target(erlang) +fn do_replace( + iodata: StringBuilder, + pattern: String, + substitute: String, +) -> StringBuilder { + erl_replace(iodata, pattern, substitute, All) } -if javascript { - external fn do_replace(StringBuilder, String, String) -> StringBuilder = - "../gleam_stdlib.mjs" "string_replace" -} +@target(erlang) +@external(erlang, "string", "replace") +fn erl_replace( + a: StringBuilder, + b: String, + c: String, + d: Direction, +) -> StringBuilder + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "string_replace") +fn do_replace(a: StringBuilder, b: String, c: String) -> StringBuilder /// Compares two builders to determine if they have the same textual content. /// @@ -311,15 +261,9 @@ pub fn is_equal(a: StringBuilder, b: StringBuilder) -> Bool { do_is_equal(a, b) } -if erlang { - external fn do_is_equal(StringBuilder, StringBuilder) -> Bool = - "string" "equal" -} - -if javascript { - external fn do_is_equal(StringBuilder, StringBuilder) -> Bool = - "../gleam_stdlib.mjs" "equal" -} +@external(erlang, "string", "equal") +@external(javascript, "../gleam_stdlib.mjs", "equal") +fn do_is_equal(a: StringBuilder, b: StringBuilder) -> Bool /// Inspects a builder to determine if it is equivalent to an empty string. /// @@ -344,13 +288,11 @@ pub fn is_empty(builder: StringBuilder) -> Bool { do_is_empty(builder) } -if erlang { - external fn do_is_empty(StringBuilder) -> Bool = - "string" "is_empty" -} +@target(erlang) +@external(erlang, "string", "is_empty") +fn do_is_empty(a: StringBuilder) -> Bool -if javascript { - fn do_is_empty(builder: StringBuilder) -> Bool { - from_string("") == builder - } +@target(javascript) +fn do_is_empty(builder: StringBuilder) -> Bool { + from_string("") == builder } diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam index 3fdfc6d..2565771 100644 --- a/src/gleam/uri.gleam +++ b/src/gleam/uri.gleam @@ -12,12 +12,12 @@ import gleam/list import gleam/option.{None, Option, Some} import gleam/string import gleam/string_builder.{StringBuilder} - -if javascript { - import gleam/pair - import gleam/regex - import gleam/result -} +@target(javascript) +import gleam/pair +@target(javascript) +import gleam/regex +@target(javascript) +import gleam/result /// Type representing holding the parsed components of an URI. /// All components of a URI are optional, except the path. @@ -60,135 +60,139 @@ pub fn parse(uri_string: String) -> Result(Uri, Nil) { do_parse(uri_string) } -if erlang { - external fn do_parse(String) -> Result(Uri, Nil) = - "gleam_stdlib" "uri_parse" -} - -if javascript { - fn do_parse(uri_string: String) -> Result(Uri, Nil) { - // From https://tools.ietf.org/html/rfc3986#appendix-B - let pattern = - // 12 3 4 5 6 7 8 - "^(([a-z][a-z0-9\\+\\-\\.]*):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#.*)?" - let matches = - pattern - |> regex_submatches(uri_string) - |> pad_list(8) +@target(erlang) +@external(erlang, "gleam_stdlib", "uri_parse") +fn do_parse(a: String) -> Result(Uri, Nil) + +@target(javascript) +fn do_parse(uri_string: String) -> Result(Uri, Nil) { + // From https://tools.ietf.org/html/rfc3986#appendix-B + let pattern = + // 12 3 4 5 6 7 8 + "^(([a-z][a-z0-9\\+\\-\\.]*):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#.*)?" + let matches = + pattern + |> regex_submatches(uri_string) + |> pad_list(8) + + let #(scheme, authority, path, query, fragment) = case matches { + [ + _scheme_with_colon, + scheme, + authority_with_slashes, + _authority, + path, + query_with_question_mark, + _query, + fragment, + ] -> #( + scheme, + authority_with_slashes, + path, + query_with_question_mark, + fragment, + ) + _ -> #(None, None, None, None, None) + } - let #(scheme, authority, path, query, fragment) = case matches { - [ - _scheme_with_colon, - scheme, - authority_with_slashes, - _authority, - path, - query_with_question_mark, - _query, - fragment, - ] -> #( - scheme, - authority_with_slashes, - path, - query_with_question_mark, - fragment, - ) - _ -> #(None, None, None, None, None) - } + let scheme = noneify_empty_string(scheme) + let path = option.unwrap(path, "") + let query = noneify_query(query) + let #(userinfo, host, port) = split_authority(authority) + let fragment = + fragment + |> option.to_result(Nil) + |> result.try(string.pop_grapheme) + |> result.map(pair.second) + |> option.from_result + let scheme = + scheme + |> noneify_empty_string + |> option.map(string.lowercase) + Ok(Uri( + scheme: scheme, + userinfo: userinfo, + host: host, + port: port, + path: path, + query: query, + fragment: fragment, + )) +} - let scheme = noneify_empty_string(scheme) - let path = option.unwrap(path, "") - let query = noneify_query(query) - let #(userinfo, host, port) = split_authority(authority) - let fragment = - fragment - |> option.to_result(Nil) - |> result.try(string.pop_grapheme) - |> result.map(pair.second) - |> option.from_result - let scheme = - scheme - |> noneify_empty_string - |> option.map(string.lowercase) - Ok(Uri( - scheme: scheme, - userinfo: userinfo, - host: host, - port: port, - path: path, - query: query, - fragment: fragment, - )) - } +@target(javascript) +fn regex_submatches(pattern: String, string: String) -> List(Option(String)) { + pattern + |> regex.compile(regex.Options(case_insensitive: True, multi_line: False)) + |> result.nil_error + |> result.map(regex.scan(_, string)) + |> result.try(list.first) + |> result.map(fn(m: regex.Match) { m.submatches }) + |> result.unwrap([]) +} - fn regex_submatches(pattern: String, string: String) -> List(Option(String)) { - pattern - |> regex.compile(regex.Options(case_insensitive: True, multi_line: False)) - |> result.nil_error - |> result.map(regex.scan(_, string)) - |> result.try(list.first) - |> result.map(fn(m: regex.Match) { m.submatches }) - |> result.unwrap([]) +@target(javascript) +fn noneify_query(x: Option(String)) -> Option(String) { + case x { + None -> None + Some(x) -> + case string.pop_grapheme(x) { + Ok(#("?", query)) -> Some(query) + _ -> None + } } +} - fn noneify_query(x: Option(String)) -> Option(String) { - case x { - None -> None - Some(x) -> - case string.pop_grapheme(x) { - Ok(#("?", query)) -> Some(query) - _ -> None - } - } - } - - fn noneify_empty_string(x: Option(String)) -> Option(String) { - case x { - Some("") | None -> None - Some(_) -> x - } +@target(javascript) +fn noneify_empty_string(x: Option(String)) -> Option(String) { + case x { + Some("") | None -> None + Some(_) -> x } +} - // Split an authority into its userinfo, host and port parts. - fn split_authority( - authority: Option(String), - ) -> #(Option(String), Option(String), Option(Int)) { - case option.unwrap(authority, "") { - "" -> #(None, None, None) - "//" -> #(None, Some(""), None) - authority -> { - let matches = - "^(//)?((.*)@)?(\\[[a-zA-Z0-9:.]*\\]|[^:]*)(:(\\d*))?" - |> regex_submatches(authority) - |> pad_list(6) - case matches { - [_, _, userinfo, host, _, port] -> { - let userinfo = noneify_empty_string(userinfo) - let host = noneify_empty_string(host) - let port = - port - |> option.unwrap("") - |> int.parse - |> option.from_result - #(userinfo, host, port) - } - _ -> #(None, None, None) +// Split an authority into its userinfo, host and port parts. +@target(javascript) +fn split_authority( + authority: Option(String), +) -> #(Option(String), Option(String), Option(Int)) { + case option.unwrap(authority, "") { + "" -> #(None, None, None) + "//" -> #(None, Some(""), None) + authority -> { + let matches = + "^(//)?((.*)@)?(\\[[a-zA-Z0-9:.]*\\]|[^:]*)(:(\\d*))?" + |> regex_submatches(authority) + |> pad_list(6) + case matches { + [_, _, userinfo, host, _, port] -> { + let userinfo = noneify_empty_string(userinfo) + let host = noneify_empty_string(host) + let port = + port + |> option.unwrap("") + |> int.parse + |> option.from_result + #(userinfo, host, port) } + _ -> #(None, None, None) } } } +} - fn pad_list(list: List(Option(a)), size: Int) -> List(Option(a)) { - list - |> list.append(list.repeat(None, extra_required(list, size))) - } +@target(javascript) +fn pad_list(list: List(Option(a)), size: Int) -> List(Option(a)) { + list + |> list.append(list.repeat(None, extra_required(list, size))) +} - fn extra_required(list: List(a), remaining: Int) -> Int { - case list { - _ if remaining == 0 -> 0 - [] -> remaining - [_, ..xs] -> extra_required(xs, remaining - 1) - } +@target(javascript) +fn extra_required(list: List(a), remaining: Int) -> Int { + case list { + _ if remaining == 0 -> 0 + [] -> remaining + [_, ..xs] -> extra_required(xs, remaining - 1) } } @@ -208,15 +212,9 @@ pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) { do_parse_query(query) } -if erlang { - external fn do_parse_query(String) -> Result(List(#(String, String)), Nil) = - "gleam_stdlib" "parse_query" -} - -if javascript { - external fn do_parse_query(String) -> Result(List(#(String, String)), Nil) = - "../gleam_stdlib.mjs" "parse_query" -} +@external(erlang, "gleam_stdlib", "parse_query") +@external(javascript, "../gleam_stdlib.mjs", "parse_query") +fn do_parse_query(a: String) -> Result(List(#(String, String)), Nil) /// Encodes a list of key value pairs as a URI query string. /// @@ -258,15 +256,9 @@ pub fn percent_encode(value: String) -> String { do_percent_encode(value) } -if erlang { - external fn do_percent_encode(String) -> String = - "gleam_stdlib" "percent_encode" -} - -if javascript { - external fn do_percent_encode(String) -> String = - "../gleam_stdlib.mjs" "percent_encode" -} +@external(erlang, "gleam_stdlib", "percent_encode") +@external(javascript, "../gleam_stdlib.mjs", "percent_encode") +fn do_percent_encode(a: String) -> String /// Decodes a percent encoded string. /// @@ -281,15 +273,9 @@ pub fn percent_decode(value: String) -> Result(String, Nil) { do_percent_decode(value) } -if erlang { - external fn do_percent_decode(String) -> Result(String, Nil) = - "gleam_stdlib" "percent_decode" -} - -if javascript { - external fn do_percent_decode(String) -> Result(String, Nil) = - "../gleam_stdlib.mjs" "percent_decode" -} +@external(erlang, "gleam_stdlib", "percent_decode") +@external(javascript, "../gleam_stdlib.mjs", "percent_decode") +fn do_percent_decode(a: String) -> Result(String, Nil) fn do_remove_dot_segments( input: List(String), |