aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2023-07-23 19:25:42 +0100
committerLouis Pilfold <louis@lpil.uk>2023-07-23 19:25:42 +0100
commit43ae440ad66571cc41fef8e20dd852b170a3dc2b (patch)
treefdf889396459242079beff03c62731850e7bc96d
parented3b2096cc9e22bec44cb1eb84285bb013b62d51 (diff)
downloadgleam_stdlib-43ae440ad66571cc41fef8e20dd852b170a3dc2b.tar.gz
gleam_stdlib-43ae440ad66571cc41fef8e20dd852b170a3dc2b.zip
Gleam fix
-rw-r--r--src/gleam/base.gleam24
-rw-r--r--src/gleam/bit_builder.gleam191
-rw-r--r--src/gleam/bit_string.gleam107
-rw-r--r--src/gleam/dynamic.gleam324
-rw-r--r--src/gleam/float.gleam117
-rw-r--r--src/gleam/int.gleam60
-rw-r--r--src/gleam/io.gleam60
-rw-r--r--src/gleam/list.gleam75
-rw-r--r--src/gleam/map.gleam321
-rw-r--r--src/gleam/regex.gleam59
-rw-r--r--src/gleam/set.gleam24
-rw-r--r--src/gleam/string.gleam456
-rw-r--r--src/gleam/string_builder.gleam224
-rw-r--r--src/gleam/uri.gleam284
-rw-r--r--test/gleam/bit_string_test.gleam22
-rw-r--r--test/gleam/dynamic_test.gleam204
-rw-r--r--test/gleam/list_test.gleam22
-rw-r--r--test/gleam/should.gleam103
-rw-r--r--test/gleam/string_test.gleam349
-rw-r--r--test/gleam_stdlib_test.gleam12
20 files changed, 1258 insertions, 1780 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),
diff --git a/test/gleam/bit_string_test.gleam b/test/gleam/bit_string_test.gleam
index 581cc1c..67e791b 100644
--- a/test/gleam/bit_string_test.gleam
+++ b/test/gleam/bit_string_test.gleam
@@ -28,12 +28,11 @@ pub fn append_test() {
|> should.equal(<<1, 2, 3, 4>>)
}
-if erlang {
- pub fn append_erlang_only_test() {
- <<1, 2:4>>
- |> bit_string.append(<<3>>)
- |> should.equal(<<1, 2:4, 3>>)
- }
+@target(erlang)
+pub fn append_erlang_only_test() {
+ <<1, 2:4>>
+ |> bit_string.append(<<3>>)
+ |> should.equal(<<1, 2:4, 3>>)
}
pub fn concat_test() {
@@ -46,12 +45,11 @@ pub fn concat_test() {
|> should.equal(<<1, 2, 3, 4>>)
}
-if erlang {
- pub fn concat_erlang_only_test() {
- [<<1, 2:4>>, <<3>>]
- |> bit_string.concat
- |> should.equal(<<1, 2:4, 3>>)
- }
+@target(erlang)
+pub fn concat_erlang_only_test() {
+ [<<1, 2:4>>, <<3>>]
+ |> bit_string.concat
+ |> should.equal(<<1, 2:4, 3>>)
}
pub fn slice_test() {
diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam
index 87eef32..ab25fb8 100644
--- a/test/gleam/dynamic_test.gleam
+++ b/test/gleam/dynamic_test.gleam
@@ -30,54 +30,49 @@ pub fn bit_string_test() {
]))
}
-if erlang {
- pub fn bit_string_erlang_test() {
- <<65_535:16>>
- |> dynamic.from
- |> dynamic.bit_string
- |> should.equal(Ok(<<65_535:16>>))
- }
+@target(erlang)
+pub fn bit_string_erlang_test() {
+ <<65_535:16>>
+ |> dynamic.from
+ |> dynamic.bit_string
+ |> should.equal(Ok(<<65_535:16>>))
}
-if javascript {
- external fn uint8array(List(Int)) -> dynamic.Dynamic =
- "../gleam_stdlib_test_ffi.mjs" "uint8array"
+@target(javascript)
+@external(javascript, "../gleam_stdlib_test_ffi.mjs", "uint8array")
+fn uint8array(a: List(Int)) -> dynamic.Dynamic
- pub fn bit_string_erlang_test() {
- [1, 1, 2, 3, 5, 8]
- |> uint8array
- |> dynamic.bit_string
- |> should.equal(Ok(<<1, 1, 2, 3, 5, 8>>))
- }
+@target(javascript)
+pub fn bit_string_erlang_test() {
+ [1, 1, 2, 3, 5, 8]
+ |> uint8array
+ |> dynamic.bit_string
+ |> should.equal(Ok(<<1, 1, 2, 3, 5, 8>>))
}
-if erlang {
- pub type MyAtom {
- ThisIsAnAtom
- }
-
- pub fn map_from_atom_test() {
- ThisIsAnAtom
- |> dynamic.from
- |> dynamic.map(dynamic.string, dynamic.int)
- |> should.equal(Error([
- DecodeError(expected: "Map", found: "Atom", path: []),
- ]))
- }
+@target(erlang)
+pub type MyAtom {
+ ThisIsAnAtom
}
-if javascript {
- external fn get_null() -> dynamic.Dynamic =
- "../gleam_stdlib_test_ffi.mjs" "get_null"
-
- pub fn map_from_null_test() {
- get_null()
- |> dynamic.from
- |> dynamic.map(dynamic.string, dynamic.int)
- |> should.equal(Error([
- DecodeError(expected: "Map", found: "Null", path: []),
- ]))
- }
+@target(erlang)
+pub fn map_from_atom_test() {
+ ThisIsAnAtom
+ |> dynamic.from
+ |> dynamic.map(dynamic.string, dynamic.int)
+ |> should.equal(Error([DecodeError(expected: "Map", found: "Atom", path: [])]))
+}
+
+@target(javascript)
+@external(javascript, "../gleam_stdlib_test_ffi.mjs", "get_null")
+fn get_null() -> dynamic.Dynamic
+
+@target(javascript)
+pub fn map_from_null_test() {
+ get_null()
+ |> dynamic.from
+ |> dynamic.map(dynamic.string, dynamic.int)
+ |> should.equal(Error([DecodeError(expected: "Map", found: "Null", path: [])]))
}
pub fn string_test() {
@@ -106,15 +101,14 @@ pub fn string_test() {
]))
}
-if erlang {
- pub fn string_non_utf8_test() {
- <<65_535:16>>
- |> dynamic.from
- |> dynamic.string
- |> should.equal(Error([
- DecodeError(expected: "String", found: "BitString", path: []),
- ]))
- }
+@target(erlang)
+pub fn string_non_utf8_test() {
+ <<65_535:16>>
+ |> dynamic.from
+ |> dynamic.string
+ |> should.equal(Error([
+ DecodeError(expected: "String", found: "BitString", path: []),
+ ]))
}
pub fn int_test() {
@@ -153,36 +147,30 @@ pub fn float_test() {
]))
}
-if erlang {
- pub fn float_on_js_is_also_int_test() {
- 1
- |> dynamic.from
- |> dynamic.float
- |> should.equal(Error([
- DecodeError(expected: "Float", found: "Int", path: []),
- ]))
-
- 1.0
- |> dynamic.from
- |> dynamic.int
- |> should.equal(Error([
- DecodeError(expected: "Int", found: "Float", path: []),
- ]))
- }
+@target(erlang)
+pub fn float_on_js_is_also_int_test() {
+ 1
+ |> dynamic.from
+ |> dynamic.float
+ |> should.equal(Error([DecodeError(expected: "Float", found: "Int", path: [])]))
+
+ 1.0
+ |> dynamic.from
+ |> dynamic.int
+ |> should.equal(Error([DecodeError(expected: "Int", found: "Float", path: [])]))
}
-if javascript {
- pub fn float_on_js_is_also_int_test() {
- 1
- |> dynamic.from
- |> dynamic.float
- |> should.equal(Ok(1.0))
-
- 1.0
- |> dynamic.from
- |> dynamic.int
- |> should.equal(Ok(1))
- }
+@target(javascript)
+pub fn float_on_js_is_also_int_test() {
+ 1
+ |> dynamic.from
+ |> dynamic.float
+ |> should.equal(Ok(1.0))
+
+ 1.0
+ |> dynamic.from
+ |> dynamic.int
+ |> should.equal(Ok(1))
}
pub fn bool_test() {
@@ -284,25 +272,24 @@ pub fn optional_test() {
|> should.be_error
}
-if javascript {
- pub fn javascript_object_field_test() {
- Ok(123)
- |> dynamic.from
- |> dynamic.field("0", dynamic.int)
- |> should.equal(Ok(123))
-
- Ok(123)
- |> dynamic.from
- |> dynamic.field(0, dynamic.int)
- |> should.equal(Ok(123))
-
- Ok(123)
- |> dynamic.from
- |> dynamic.field("Nope", dynamic.int)
- |> should.equal(Error([
- DecodeError(expected: "Map", found: "Result", path: []),
- ]))
- }
+@target(javascript)
+pub fn javascript_object_field_test() {
+ Ok(123)
+ |> dynamic.from
+ |> dynamic.field("0", dynamic.int)
+ |> should.equal(Ok(123))
+
+ Ok(123)
+ |> dynamic.from
+ |> dynamic.field(0, dynamic.int)
+ |> should.equal(Ok(123))
+
+ Ok(123)
+ |> dynamic.from
+ |> dynamic.field("Nope", dynamic.int)
+ |> should.equal(Error([
+ DecodeError(expected: "Map", found: "Result", path: []),
+ ]))
}
pub fn field_test() {
@@ -1083,18 +1070,17 @@ pub fn shallow_list_test() {
|> should.equal(Error([DecodeError(expected: "List", found: "Int", path: [])]))
}
-if javascript {
- pub fn array_on_js_is_also_list_test() {
- #()
- |> dynamic.from
- |> dynamic.shallow_list
- |> should.equal(Ok([]))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.list(of: dynamic.int)
- |> should.equal(Ok([1, 2]))
- }
+@target(javascript)
+pub fn array_on_js_is_also_list_test() {
+ #()
+ |> dynamic.from
+ |> dynamic.shallow_list
+ |> should.equal(Ok([]))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.list(of: dynamic.int)
+ |> should.equal(Ok([1, 2]))
}
pub fn result_test() {
diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam
index 2883535..c4305f5 100644
--- a/test/gleam/list_test.gleam
+++ b/test/gleam/list_test.gleam
@@ -5,18 +5,16 @@ import gleam/list
import gleam/map
import gleam/should
-if erlang {
- const recursion_test_cycles = 1_000_000
-}
-
-if javascript {
- // JavaScript engines crash when exceeding a certain stack size:
- //
- // - Chrome 106 and NodeJS V16, V18, and V19 crash around 10_000+
- // - Firefox 106 crashes around 35_000+.
- // - Safari 16 crashes around 40_000+.
- const recursion_test_cycles = 40_000
-}
+@target(erlang)
+const recursion_test_cycles = 1_000_000
+
+// JavaScript engines crash when exceeding a certain stack size:
+//
+// - Chrome 106 and NodeJS V16, V18, and V19 crash around 10_000+
+// - Firefox 106 crashes around 35_000+.
+// - Safari 16 crashes around 40_000+.
+@target(javascript)
+const recursion_test_cycles = 40_000
pub fn length_test() {
list.length([])
diff --git a/test/gleam/should.gleam b/test/gleam/should.gleam
index 7ae0408..acfeacd 100644
--- a/test/gleam/should.gleam
+++ b/test/gleam/should.gleam
@@ -4,67 +4,74 @@
//// More information on running eunit can be found in [the rebar3
//// documentation](https://rebar3.org/docs/testing/eunit/).
-if erlang {
- pub external fn equal(a, a) -> Nil =
- "gleam_stdlib_test_ffi" "should_equal"
+@target(erlang)
+@external(erlang, "gleam_stdlib_test_ffi", "should_equal")
+pub fn equal(a: a, b: a) -> Nil
- pub external fn not_equal(a, a) -> Nil =
- "gleam_stdlib_test_ffi" "should_not_equal"
+@target(erlang)
+@external(erlang, "gleam_stdlib_test_ffi", "should_not_equal")
+pub fn not_equal(a: a, b: a) -> Nil
- pub external fn be_ok(Result(a, b)) -> Nil =
- "gleam_stdlib_test_ffi" "should_be_ok"
+@target(erlang)
+@external(erlang, "gleam_stdlib_test_ffi", "should_be_ok")
+pub fn be_ok(a: Result(a, b)) -> Nil
- pub external fn be_error(Result(a, b)) -> Nil =
- "gleam_stdlib_test_ffi" "should_be_error"
-}
+@target(erlang)
+@external(erlang, "gleam_stdlib_test_ffi", "should_be_error")
+pub fn be_error(a: Result(a, b)) -> Nil
-if javascript {
- import gleam/string
+@target(javascript)
+import gleam/string
- external fn stringify(anything) -> String =
- "../gleam.mjs" "inspect"
+@target(javascript)
+@external(javascript, "../gleam.mjs", "inspect")
+fn stringify(a: anything) -> String
- external fn crash(String) -> anything =
- "../gleam_stdlib.mjs" "crash"
+@target(javascript)
+@external(javascript, "../gleam_stdlib.mjs", "crash")
+fn crash(a: String) -> anything
- pub fn equal(a, b) {
- case a == b {
- True -> Nil
- _ ->
- crash(string.concat([
- "\n\t",
- stringify(a),
- "\n\tshould equal \n\t",
- stringify(b),
- ]))
- }
+@target(javascript)
+pub fn equal(a, b) {
+ case a == b {
+ True -> Nil
+ _ ->
+ crash(string.concat([
+ "\n\t",
+ stringify(a),
+ "\n\tshould equal \n\t",
+ stringify(b),
+ ]))
}
+}
- pub fn not_equal(a, b) {
- case a != b {
- True -> Nil
- _ ->
- crash(string.concat([
- "\n",
- stringify(a),
- "\nshould not equal \n",
- stringify(b),
- ]))
- }
+@target(javascript)
+pub fn not_equal(a, b) {
+ case a != b {
+ True -> Nil
+ _ ->
+ crash(string.concat([
+ "\n",
+ stringify(a),
+ "\nshould not equal \n",
+ stringify(b),
+ ]))
}
+}
- pub fn be_ok(a) {
- case a {
- Ok(_) -> Nil
- _ -> crash(string.concat(["\n", stringify(a), "\nshould be ok"]))
- }
+@target(javascript)
+pub fn be_ok(a) {
+ case a {
+ Ok(_) -> Nil
+ _ -> crash(string.concat(["\n", stringify(a), "\nshould be ok"]))
}
+}
- pub fn be_error(a) {
- case a {
- Error(_) -> Nil
- _ -> crash(string.concat(["\n", stringify(a), "\nshould be error"]))
- }
+@target(javascript)
+pub fn be_error(a) {
+ case a {
+ Error(_) -> Nil
+ _ -> crash(string.concat(["\n", stringify(a), "\nshould be error"]))
}
}
diff --git a/test/gleam/string_test.gleam b/test/gleam/string_test.gleam
index 0fa860f..c072800 100644
--- a/test/gleam/string_test.gleam
+++ b/test/gleam/string_test.gleam
@@ -882,191 +882,202 @@ pub fn inspect_test() {
|> should.equal("<<255, 2, 0>>")
}
-if javascript {
- pub fn target_inspect_test() {
- // Due to Erlang's internal representation, on Erlang this passes, instead:
- // string.inspect(#(InspectTypeZero, InspectTypeZero))
- // |> should.equal("InspectTypeZero(InspectTypeZero)")
- string.inspect(#(InspectTypeZero, InspectTypeZero))
- |> should.equal("#(InspectTypeZero, InspectTypeZero)")
-
- // Due to JavaScript's `Number` type `Float`s without digits return as
- // `Int`s.
- string.inspect(-1.0)
- |> should.equal("-1")
-
- string.inspect(0.0)
- |> should.equal("0")
-
- string.inspect(1.0)
- |> should.equal("1")
-
- string.inspect([1.0])
- |> should.equal("[1]")
-
- string.inspect(#(1.0))
- |> should.equal("#(1)")
-
- // Unlike on Erlang, on JavaScript `BitString` and `String` do have a
- // different runtime representation.
- <<"abc":utf8>>
- |> string.inspect()
- |> should.equal("<<97, 98, 99>>")
- }
+@target(javascript)
+pub fn target_inspect_test() {
+ // Due to Erlang's internal representation, on Erlang this passes, instead:
+ // string.inspect(#(InspectTypeZero, InspectTypeZero))
+ // |> should.equal("InspectTypeZero(InspectTypeZero)")
+ string.inspect(#(InspectTypeZero, InspectTypeZero))
+ |> should.equal("#(InspectTypeZero, InspectTypeZero)")
+
+ // Due to JavaScript's `Number` type `Float`s without digits return as
+ // `Int`s.
+ string.inspect(-1.0)
+ |> should.equal("-1")
+
+ string.inspect(0.0)
+ |> should.equal("0")
+
+ string.inspect(1.0)
+ |> should.equal("1")
+
+ string.inspect([1.0])
+ |> should.equal("[1]")
+
+ string.inspect(#(1.0))
+ |> should.equal("#(1)")
+
+ // Unlike on Erlang, on JavaScript `BitString` and `String` do have a
+ // different runtime representation.
+ <<"abc":utf8>>
+ |> string.inspect()
+ |> should.equal("<<97, 98, 99>>")
}
-if erlang {
- import gleam/regex
- import gleam/dynamic.{Dynamic}
-
- // Test inspect on Erlang atoms valid and invalid in Gleam
-
- external fn create_erlang_pid() -> String =
- "erlang" "self"
-
- external fn create_erlang_reference() -> String =
- "erlang" "make_ref"
-
- pub fn target_inspect_test() {
- // Erlang's internal representation does not allow a correct
- // differentiation at runtime and thus this does not pass:
- // string.inspect(#(InspectTypeZero, InspectTypeZero))
- // |> should.equal("#(InspectTypeZero, InspectTypeZero)")
- string.inspect(#(InspectTypeZero, InspectTypeZero))
- |> should.equal("InspectTypeZero(InspectTypeZero)")
-
- // Unlike JavaScript, Erlang correctly differentiates between `1` and `1.0`
- // at runtime.
- string.inspect(-1.0)
- |> should.equal("-1.0")
-
- string.inspect(0.0)
- |> should.equal("0.0")
-
- string.inspect(1.0)
- |> should.equal("1.0")
-
- string.inspect([1.0])
- |> should.equal("[1.0]")
-
- string.inspect(#(1.0))
- |> should.equal("#(1.0)")
-
- // Looks like `//erl(<0.83.0>)`.
- let assert Ok(regular_expression) =
- regex.from_string("^\\/\\/erl\\(<[0-9]+\\.[0-9]+\\.[0-9]+>\\)$")
- string.inspect(create_erlang_pid())
- |> regex.check(regular_expression, _)
- |> should.be_true
-
- // Looks like: `//erl(#Ref<0.1809744150.4035444737.100468>)`.
- let assert Ok(regular_expression) =
- regex.from_string(
- "^\\/\\/erl\\(#Ref<[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+>\\)$",
- )
- string.inspect(create_erlang_reference())
- |> regex.check(regular_expression, _)
- |> should.be_true
-
- // On Erlang the representation between `String` and `BitString` is
- // indistinguishable at runtime.
- <<"abc":utf8>>
- |> string.inspect()
- |> should.equal("\"abc\"")
- }
+@target(erlang)
+import gleam/regex
+@target(erlang)
+import gleam/dynamic.{Dynamic}
- pub fn improper_list_inspect_test() {
- let list = improper_list_append(1, 2, 3)
- let assert "//erl([1, 2 | 3])" = string.inspect(list)
- }
+// Test inspect on Erlang atoms valid and invalid in Gleam
- // Warning: The type of this function is incorrect
- external fn improper_list_append(
- item_a,
- item_b,
- improper_tail,
- ) -> List(anything) =
- "gleam_stdlib_test_ffi" "improper_list_append"
+@target(erlang)
+@external(erlang, "erlang", "self")
+fn create_erlang_pid() -> String
- external fn string_to_erlang_atom(String) -> Dynamic =
- "erlang" "binary_to_atom"
+@target(erlang)
+@external(erlang, "erlang", "make_ref")
+fn create_erlang_reference() -> String
- pub fn inspect_erlang_atom_is_valid_in_gleam_test() {
- string_to_erlang_atom("a_common_erlang_atom_is_valid_in_gleam")
- |> string.inspect
- |> should.equal("ACommonErlangAtomIsValidInGleam")
+@target(erlang)
+pub fn target_inspect_test() {
+ // Erlang's internal representation does not allow a correct
+ // differentiation at runtime and thus this does not pass:
+ // string.inspect(#(InspectTypeZero, InspectTypeZero))
+ // |> should.equal("#(InspectTypeZero, InspectTypeZero)")
+ string.inspect(#(InspectTypeZero, InspectTypeZero))
+ |> should.equal("InspectTypeZero(InspectTypeZero)")
- string_to_erlang_atom(
- "an_erlang_atom_with_1_or_many_non_leading_digits_is_valid_in_gleam",
- )
- |> string.inspect
- |> should.equal("AnErlangAtomWith1OrManyNonLeadingDigitsIsValidInGleam")
- }
+ // Unlike JavaScript, Erlang correctly differentiates between `1` and `1.0`
+ // at runtime.
+ string.inspect(-1.0)
+ |> should.equal("-1.0")
- pub fn inspect_erlang_atom_with_a_leading_underscore_is_invalid_in_gleam_test() {
- string_to_erlang_atom(
- "_an_erlang_atom_with_a_leading_underscore_is_invalid_in_gleam",
- )
- |> string.inspect
- |> should.equal(
- "//erl('_an_erlang_atom_with_a_leading_underscore_is_invalid_in_gleam')",
- )
- }
+ string.inspect(0.0)
+ |> should.equal("0.0")
- pub fn inspect_erlang_atom_with_a_trailing_underscore_is_invalid_in_gleam_test() {
- string_to_erlang_atom(
- "an_erlang_atom_with_a_trailing_underscore_is_invalid_in_gleam_",
- )
- |> string.inspect
- |> should.equal(
- "//erl('an_erlang_atom_with_a_trailing_underscore_is_invalid_in_gleam_')",
- )
- }
+ string.inspect(1.0)
+ |> should.equal("1.0")
- pub fn inspect_erlang_atom_with_a_double_underscore_is_invalid_in_gleam_test() {
- string_to_erlang_atom("an_erlang_atom_with_a_double__underscore_is_invalid")
- |> string.inspect
- |> should.equal(
- "//erl('an_erlang_atom_with_a_double__underscore_is_invalid')",
- )
- }
+ string.inspect([1.0])
+ |> should.equal("[1.0]")
- pub fn inspect_erlang_atom_with_white_spaces_is_invalid_in_gleam_test() {
- string_to_erlang_atom(
- "an erlang atom with white spaces is invalid in gleam",
- )
- |> string.inspect
- |> should.equal(
- "//erl('an erlang atom with white spaces is invalid in gleam')",
+ string.inspect(#(1.0))
+ |> should.equal("#(1.0)")
+
+ // Looks like `//erl(<0.83.0>)`.
+ let assert Ok(regular_expression) =
+ regex.from_string("^\\/\\/erl\\(<[0-9]+\\.[0-9]+\\.[0-9]+>\\)$")
+ string.inspect(create_erlang_pid())
+ |> regex.check(regular_expression, _)
+ |> should.be_true
+
+ // Looks like: `//erl(#Ref<0.1809744150.4035444737.100468>)`.
+ let assert Ok(regular_expression) =
+ regex.from_string(
+ "^\\/\\/erl\\(#Ref<[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+>\\)$",
)
- }
+ string.inspect(create_erlang_reference())
+ |> regex.check(regular_expression, _)
+ |> should.be_true
- pub fn inspect_erlang_atom_that_is_an_empty_string_is_invalid_in_gleam_test() {
- // An empty string based atom is invalid in gleam
- string_to_erlang_atom("")
- |> string.inspect
- |> should.equal("//erl('')")
- }
+ // On Erlang the representation between `String` and `BitString` is
+ // indistinguishable at runtime.
+ <<"abc":utf8>>
+ |> string.inspect()
+ |> should.equal("\"abc\"")
+}
- pub fn inspect_erlang_atom_with_uppercases_invalid_in_gleam_test() {
- string_to_erlang_atom("AnErlangAtomWithUpperCasesIsInvalidInGleam")
- |> string.inspect
- |> should.equal("//erl('AnErlangAtomWithUpperCasesIsInvalidInGleam')")
- }
+@target(erlang)
+pub fn improper_list_inspect_test() {
+ let list = improper_list_append(1, 2, 3)
+ let assert "//erl([1, 2 | 3])" = string.inspect(list)
+}
- pub fn inspect_erlang_atom_with_leading_digit_invalid_in_gleam_test() {
- string_to_erlang_atom(
- "1_erlang_atom_with_a_leading_digit_is_invalid_in_gleam",
- )
- |> string.inspect
- |> should.equal(
- "//erl('1_erlang_atom_with_a_leading_digit_is_invalid_in_gleam')",
- )
+// Warning: The type of this function is incorrect
+@target(erlang)
+@external(erlang, "gleam_stdlib_test_ffi", "improper_list_append")
+fn improper_list_append(
+ a: item_a,
+ b: item_b,
+ c: improper_tail,
+) -> List(anything)
+
+@target(erlang)
+@external(erlang, "erlang", "binary_to_atom")
+fn string_to_erlang_atom(a: String) -> Dynamic
+
+@target(erlang)
+pub fn inspect_erlang_atom_is_valid_in_gleam_test() {
+ string_to_erlang_atom("a_common_erlang_atom_is_valid_in_gleam")
+ |> string.inspect
+ |> should.equal("ACommonErlangAtomIsValidInGleam")
+
+ string_to_erlang_atom(
+ "an_erlang_atom_with_1_or_many_non_leading_digits_is_valid_in_gleam",
+ )
+ |> string.inspect
+ |> should.equal("AnErlangAtomWith1OrManyNonLeadingDigitsIsValidInGleam")
+}
- string_to_erlang_atom("1ErlangAtomWithALeadingDigitIsInvalidInGleam")
- |> string.inspect
- |> should.equal("//erl('1ErlangAtomWithALeadingDigitIsInvalidInGleam')")
- }
+@target(erlang)
+pub fn inspect_erlang_atom_with_a_leading_underscore_is_invalid_in_gleam_test() {
+ string_to_erlang_atom(
+ "_an_erlang_atom_with_a_leading_underscore_is_invalid_in_gleam",
+ )
+ |> string.inspect
+ |> should.equal(
+ "//erl('_an_erlang_atom_with_a_leading_underscore_is_invalid_in_gleam')",
+ )
+}
+
+@target(erlang)
+pub fn inspect_erlang_atom_with_a_trailing_underscore_is_invalid_in_gleam_test() {
+ string_to_erlang_atom(
+ "an_erlang_atom_with_a_trailing_underscore_is_invalid_in_gleam_",
+ )
+ |> string.inspect
+ |> should.equal(
+ "//erl('an_erlang_atom_with_a_trailing_underscore_is_invalid_in_gleam_')",
+ )
+}
+
+@target(erlang)
+pub fn inspect_erlang_atom_with_a_double_underscore_is_invalid_in_gleam_test() {
+ string_to_erlang_atom("an_erlang_atom_with_a_double__underscore_is_invalid")
+ |> string.inspect
+ |> should.equal(
+ "//erl('an_erlang_atom_with_a_double__underscore_is_invalid')",
+ )
+}
+
+@target(erlang)
+pub fn inspect_erlang_atom_with_white_spaces_is_invalid_in_gleam_test() {
+ string_to_erlang_atom("an erlang atom with white spaces is invalid in gleam")
+ |> string.inspect
+ |> should.equal(
+ "//erl('an erlang atom with white spaces is invalid in gleam')",
+ )
+}
+
+@target(erlang)
+pub fn inspect_erlang_atom_that_is_an_empty_string_is_invalid_in_gleam_test() {
+ // An empty string based atom is invalid in gleam
+ string_to_erlang_atom("")
+ |> string.inspect
+ |> should.equal("//erl('')")
+}
+
+@target(erlang)
+pub fn inspect_erlang_atom_with_uppercases_invalid_in_gleam_test() {
+ string_to_erlang_atom("AnErlangAtomWithUpperCasesIsInvalidInGleam")
+ |> string.inspect
+ |> should.equal("//erl('AnErlangAtomWithUpperCasesIsInvalidInGleam')")
+}
+
+@target(erlang)
+pub fn inspect_erlang_atom_with_leading_digit_invalid_in_gleam_test() {
+ string_to_erlang_atom(
+ "1_erlang_atom_with_a_leading_digit_is_invalid_in_gleam",
+ )
+ |> string.inspect
+ |> should.equal(
+ "//erl('1_erlang_atom_with_a_leading_digit_is_invalid_in_gleam')",
+ )
+
+ string_to_erlang_atom("1ErlangAtomWithALeadingDigitIsInvalidInGleam")
+ |> string.inspect
+ |> should.equal("//erl('1ErlangAtomWithALeadingDigitIsInvalidInGleam')")
}
pub fn byte_size_test() {
diff --git a/test/gleam_stdlib_test.gleam b/test/gleam_stdlib_test.gleam
index fabc311..ed09793 100644
--- a/test/gleam_stdlib_test.gleam
+++ b/test/gleam_stdlib_test.gleam
@@ -1,9 +1,3 @@
-if erlang {
- pub external fn main() -> Nil =
- "gleam_stdlib_test_ffi" "main"
-}
-
-if javascript {
- pub external fn main() -> Nil =
- "././gleeunit.mjs" "main"
-}
+@external(erlang, "gleam_stdlib_test_ffi", "main")
+@external(javascript, "././gleeunit.mjs", "main")
+pub fn main() -> Nil