diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba7e01aa1..e172048c26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ - Remove `Stdlib_Char` module for now. https://github.com/rescript-lang/rescript/pull/7367 - Convert internal JavaScript codebase into ESM, ReScript package itself is now ESM (`"type": "module"`). https://github.com/rescript-lang/rescript/pull/6899 +#### :nail_care: Polish + +- More deprecations in `Pervasives`; add `Stdlib.Pair` and `Stdlib.Int.Ref`. https://github.com/rescript-lang/rescript/pull/7371 + # 12.0.0-alpha.10 #### :rocket: New Feature diff --git a/lib/es6/Stdlib.js b/lib/es6/Stdlib.js index 02b8cb4a33..a2e96d79ef 100644 --- a/lib/es6/Stdlib.js +++ b/lib/es6/Stdlib.js @@ -12,7 +12,7 @@ function assertEqual(a, b) { RE_EXN_ID: "Assert_failure", _1: [ "Stdlib.res", - 118, + 119, 4 ], Error: new Error() @@ -63,6 +63,8 @@ let Option; let Ordering; +let Pair; + let $$Promise; let $$RegExp; @@ -138,6 +140,7 @@ export { $$Object, Option, Ordering, + Pair, $$Promise, $$RegExp, Result, diff --git a/lib/es6/Stdlib_Int.js b/lib/es6/Stdlib_Int.js index 7163c756af..1f2f624f21 100644 --- a/lib/es6/Stdlib_Int.js +++ b/lib/es6/Stdlib_Int.js @@ -66,6 +66,8 @@ function bitwiseNot(x) { return x ^ -1; } +let Ref = {}; + let Constants = { minValue: -2147483648, maxValue: 2147483647 @@ -78,5 +80,6 @@ export { rangeWithOptions, clamp, bitwiseNot, + Ref, } /* No side effect */ diff --git a/lib/es6/Stdlib_Pair.js b/lib/es6/Stdlib_Pair.js new file mode 100644 index 0000000000..b41d7eb007 --- /dev/null +++ b/lib/es6/Stdlib_Pair.js @@ -0,0 +1,25 @@ + + + +function equal(param, param$1, eq1, eq2) { + if (eq1(param[0], param$1[0])) { + return eq2(param[1], param$1[1]); + } else { + return false; + } +} + +function compare(param, param$1, cmp1, cmp2) { + let result = cmp1(param[0], param$1[0]); + if (result !== 0) { + return result; + } else { + return cmp2(param[1], param$1[1]); + } +} + +export { + equal, + compare, +} +/* No side effect */ diff --git a/lib/js/Stdlib.js b/lib/js/Stdlib.js index ee78df23da..f7f38a6189 100644 --- a/lib/js/Stdlib.js +++ b/lib/js/Stdlib.js @@ -12,7 +12,7 @@ function assertEqual(a, b) { RE_EXN_ID: "Assert_failure", _1: [ "Stdlib.res", - 118, + 119, 4 ], Error: new Error() @@ -63,6 +63,8 @@ let Option; let Ordering; +let Pair; + let $$Promise; let $$RegExp; @@ -137,6 +139,7 @@ exports.Nullable = Nullable; exports.$$Object = $$Object; exports.Option = Option; exports.Ordering = Ordering; +exports.Pair = Pair; exports.$$Promise = $$Promise; exports.$$RegExp = $$RegExp; exports.Result = Result; diff --git a/lib/js/Stdlib_Int.js b/lib/js/Stdlib_Int.js index 0604d4d3ef..6e2858f4b2 100644 --- a/lib/js/Stdlib_Int.js +++ b/lib/js/Stdlib_Int.js @@ -66,6 +66,8 @@ function bitwiseNot(x) { return x ^ -1; } +let Ref = {}; + let Constants = { minValue: -2147483648, maxValue: 2147483647 @@ -77,4 +79,5 @@ exports.range = range; exports.rangeWithOptions = rangeWithOptions; exports.clamp = clamp; exports.bitwiseNot = bitwiseNot; +exports.Ref = Ref; /* No side effect */ diff --git a/lib/js/Stdlib_Pair.js b/lib/js/Stdlib_Pair.js new file mode 100644 index 0000000000..b0b797aa86 --- /dev/null +++ b/lib/js/Stdlib_Pair.js @@ -0,0 +1,23 @@ +'use strict'; + + +function equal(param, param$1, eq1, eq2) { + if (eq1(param[0], param$1[0])) { + return eq2(param[1], param$1[1]); + } else { + return false; + } +} + +function compare(param, param$1, cmp1, cmp2) { + let result = cmp1(param[0], param$1[0]); + if (result !== 0) { + return result; + } else { + return cmp2(param[1], param$1[1]); + } +} + +exports.equal = equal; +exports.compare = compare; +/* No side effect */ diff --git a/packages/artifacts.txt b/packages/artifacts.txt index 7be00eae08..5aec77a6a4 100644 --- a/packages/artifacts.txt +++ b/packages/artifacts.txt @@ -186,6 +186,7 @@ lib/es6/Stdlib_Nullable.js lib/es6/Stdlib_Object.js lib/es6/Stdlib_Option.js lib/es6/Stdlib_Ordering.js +lib/es6/Stdlib_Pair.js lib/es6/Stdlib_Promise.js lib/es6/Stdlib_RegExp.js lib/es6/Stdlib_Result.js @@ -358,6 +359,7 @@ lib/js/Stdlib_Nullable.js lib/js/Stdlib_Object.js lib/js/Stdlib_Option.js lib/js/Stdlib_Ordering.js +lib/js/Stdlib_Pair.js lib/js/Stdlib_Promise.js lib/js/Stdlib_RegExp.js lib/js/Stdlib_Result.js @@ -1151,6 +1153,10 @@ lib/ocaml/Stdlib_Ordering.cmi lib/ocaml/Stdlib_Ordering.cmj lib/ocaml/Stdlib_Ordering.cmt lib/ocaml/Stdlib_Ordering.res +lib/ocaml/Stdlib_Pair.cmi +lib/ocaml/Stdlib_Pair.cmj +lib/ocaml/Stdlib_Pair.cmt +lib/ocaml/Stdlib_Pair.res lib/ocaml/Stdlib_Promise.cmi lib/ocaml/Stdlib_Promise.cmj lib/ocaml/Stdlib_Promise.cmt diff --git a/runtime/Pervasives.res b/runtime/Pervasives.res index 0f73f5cc08..6d997a603f 100644 --- a/runtime/Pervasives.res +++ b/runtime/Pervasives.res @@ -1,21 +1,7 @@ @deprecated("Do not use. This will be removed in v13") -external /* Internal */ - -__unsafe_cast: 'a => 'b = "%identity" +external __unsafe_cast: 'a => 'b = "%identity" /* Exceptions */ -@deprecated( - "`raise` has been renamed to `throw` to align with JavaScript vocabulary. Please use `throw` instead" -) -external raise: exn => 'a = "%raise" - -@deprecated("Use custom exception instead") -let failwith = s => throw(Failure(s)) - -@deprecated("Use custom exception instead") -let invalid_arg = s => throw(Invalid_argument(s)) - -@deprecated("Use custom exception instead") exception Exit /** Raises the given exception, terminating execution unless caught by a surrounding try/catch block. @@ -36,9 +22,25 @@ assertEqual(result, "Caught exception: Out of milk") */ external throw: exn => 'a = "%raise" +@deprecated( + "`raise` has been renamed to `throw` to align with JavaScript vocabulary. Please use `throw` instead" +) +external raise: exn => 'a = "%raise" + +@deprecated("Use custom exception instead") +let failwith = s => throw(Failure(s)) + +@deprecated("Use custom exception instead") +let invalid_arg = s => throw(Invalid_argument(s)) + +@deprecated("Use custom exception instead") exception Exit + /* Composition operators */ +@deprecated("This will be removed in v13") external \"|>": ('a, 'a => 'b) => 'b = "%revapply" + +@deprecated("This will be removed in v13") external \"@@": ('a => 'b, 'a) => 'b = "%apply" /* Debugging */ @@ -92,7 +94,10 @@ external \"||": (bool, bool) => bool = "%sequor" /* Integer operations */ +@deprecated("Use `x => x + 1` instead. This will be removed in v13") external succ: int => int = "%succint" + +@deprecated("Use `x => x - 1` instead. This will be removed in v13") external pred: int => int = "%predint" @deprecated("Use `Math.abs` instead. This will be removed in v13") @@ -103,14 +108,25 @@ let abs = x => -x } +@deprecated("Use `Int.bitwiseAnd` instead. This will be removed in v13") external land: (int, int) => int = "%andint" + +@deprecated("Use `Int.bitwiseOr` instead. This will be removed in v13") external lor: (int, int) => int = "%orint" + +@deprecated("Use `Int.bitwiseXor` instead. This will be removed in v13") external lxor: (int, int) => int = "%xorint" +@deprecated("Use `Int.bitwiseNot` instead. This will be removed in v13") let lnot = x => lxor(x, -1) +@deprecated("Use `Int.shiftLeft` instead. This will be removed in v13") external lsl: (int, int) => int = "%lslint" + +@deprecated("Use `Int.shiftRightUnsigned` instead. This will be removed in v13") external lsr: (int, int) => int = "%lsrint" + +@deprecated("Use `Int.shiftRight` instead. This will be removed in v13") external asr: (int, int) => int = "%asrint" @deprecated("Use `Int.Constants.maxValue` instead. This will be removed in v13") @@ -266,16 +282,25 @@ external ignore: 'a => unit = "%ignore" /* Pair operations */ +@deprecated("Use `Pair.first` instead. This will be removed in v13") external fst: (('a, 'b)) => 'a = "%field0" + +@deprecated("Use `Pair.second` instead. This will be removed in v13") external snd: (('a, 'b)) => 'b = "%field1" /* References */ type ref<'a> = {mutable contents: 'a} external ref: 'a => ref<'a> = "%makeref" -external \"!": ref<'a> => 'a = "%refget" external \":=": (ref<'a>, 'a) => unit = "%refset" + +@deprecated("Do not use. This will be removed in v13") +external \"!": ref<'a> => 'a = "%refget" + +@deprecated("Use `Int.Ref.increment` instead. This will be removed in v13") external incr: ref => unit = "%incr" + +@deprecated("Use `Int.Ref.decrement` instead. This will be removed in v13") external decr: ref => unit = "%decr" /* String conversion functions */ @@ -310,6 +335,7 @@ external string_of_int: int => string = "String" @deprecated("Use `Int.fromString` instead. This will be removed in v13") @scope("Number") external int_of_string: string => int = "parseInt" +@deprecated("Use `Int.fromString` instead. This will be removed in v13") let int_of_string_opt = s => switch int_of_string(s) { | n if n == %raw("NaN") => None @@ -330,4 +356,5 @@ let rec \"@" = (l1, l2) => /* Miscellaneous */ +@deprecated("This will be removed in v13") type int32 = int diff --git a/runtime/Pervasives_mini.res b/runtime/Pervasives_mini.res deleted file mode 100644 index d888d08d29..0000000000 --- a/runtime/Pervasives_mini.res +++ /dev/null @@ -1,93 +0,0 @@ -/* Exceptions */ -external throw: exn => 'a = "%raise" - -/* Debugging */ - -external __LOC__: string = "%loc_LOC" -external __FILE__: string = "%loc_FILE" -external __LINE__: int = "%loc_LINE" -external __MODULE__: string = "%loc_MODULE" -external __POS__: (string, int, int, int) = "%loc_POS" - -external __LOC_OF__: 'a => (string, 'a) = "%loc_LOC" -external __LINE_OF__: 'a => (int, 'a) = "%loc_LINE" -external __POS_OF__: 'a => ((string, int, int, int), 'a) = "%loc_POS" - -/* Unified operations */ -/* - Note: - - Unified operations only work on `Pervasives`. - That means we can't rely on it when building stdlib until we remove the `Pervasives_mini`. -*/ - -external \"~+": int => int = "%identity" -external \"~-": int => int = "%negint" - -external \"+": (int, int) => int = "%addint" -external \"-": (int, int) => int = "%subint" -external \"*": (int, int) => int = "%mulint" -external \"/": (int, int) => int = "%divint" -external \"%": (int, int) => int = "%modint" -external mod: (int, int) => int = "%modint" -external \"**": (int, int) => int = "%powint" -external \"^": (int, int) => int = "%bitxorint" - -/* Comparisons */ -/* Note: Later comparisons will be converted to unified operations too */ - -external \"==": ('a, 'a) => bool = "%equal" -external \"!=": ('a, 'a) => bool = "%notequal" -external \"<": ('a, 'a) => bool = "%lessthan" -external \">": ('a, 'a) => bool = "%greaterthan" -external \"<=": ('a, 'a) => bool = "%lessequal" -external \">=": ('a, 'a) => bool = "%greaterequal" -external compare: ('a, 'a) => int = "%compare" -external min: ('a, 'a) => 'a = "%min" -external max: ('a, 'a) => 'a = "%max" -external \"===": ('a, 'a) => bool = "%eq" -external \"!==": ('a, 'a) => bool = "%noteq" - -/* Boolean operations */ - -external not: bool => bool = "%boolnot" - -external \"&&": (bool, bool) => bool = "%sequand" - -external \"||": (bool, bool) => bool = "%sequor" - -/* Integer operations */ - -external succ: int => int = "%succint" -external pred: int => int = "%predint" - -external land: (int, int) => int = "%andint" -external lor: (int, int) => int = "%orint" -external lxor: (int, int) => int = "%xorint" - -external lsl: (int, int) => int = "%lslint" -external lsr: (int, int) => int = "%lsrint" -external asr: (int, int) => int = "%asrint" - -/* Floating-point operations */ - -external \"~-.": float => float = "%negfloat" -external \"~+.": float => float = "%identity" -external \"+.": (float, float) => float = "%addfloat" -external \"-.": (float, float) => float = "%subfloat" -external \"*.": (float, float) => float = "%mulfloat" -external \"/.": (float, float) => float = "%divfloat" - -/* String operations */ - -external \"++": (string, string) => string = "%string_concat" - -/* Unit operations */ - -external ignore: 'a => unit = "%ignore" - -/* References */ - -type ref<'a> = {mutable contents: 'a} -external ref: 'a => ref<'a> = "%makeref" -external \":=": (ref<'a>, 'a) => unit = "%refset" diff --git a/runtime/Stdlib.res b/runtime/Stdlib.res index 012570690f..8e18d33324 100644 --- a/runtime/Stdlib.res +++ b/runtime/Stdlib.res @@ -20,6 +20,7 @@ module Nullable = Stdlib_Nullable module Object = Stdlib_Object module Option = Stdlib_Option module Ordering = Stdlib_Ordering +module Pair = Stdlib_Pair module Promise = Stdlib_Promise module RegExp = Stdlib_RegExp module Result = Stdlib_Result diff --git a/runtime/Stdlib_Int.res b/runtime/Stdlib_Int.res index 2ff536337d..01ee088058 100644 --- a/runtime/Stdlib_Int.res +++ b/runtime/Stdlib_Int.res @@ -107,3 +107,10 @@ external shiftRight: (int, int) => int = "%asrint" external shiftRightUnsigned: (int, int) => int = "%lsrint" external ignore: int => unit = "%ignore" + +module Ref = { + type t = ref + + external increment: ref => unit = "%incr" + external decrement: ref => unit = "%decr" +} diff --git a/runtime/Stdlib_Int.resi b/runtime/Stdlib_Int.resi index e4371d69e6..b9d7959e05 100644 --- a/runtime/Stdlib_Int.resi +++ b/runtime/Stdlib_Int.resi @@ -482,3 +482,33 @@ external shiftRightUnsigned: (int, int) => int = "%lsrint" without having to store or process it further. */ external ignore: int => unit = "%ignore" + +module Ref: { + type t = ref + + /** + `increment(intRef)` increments the value of the provided reference by 1. + + ## Examples + + ```rescript + let myRef = ref(4) + Int.Ref.increment(myRef) + assertEqual(myRef.contents, 5) + ``` + */ + external increment: ref => unit = "%incr" + + /** + `decrement(intRef)` decrements the value of the provided reference by 1. + + ## Examples + + ```rescript + let myRef = ref(4) + Int.Ref.decrement(myRef) + assertEqual(myRef.contents, 3) + ``` + */ + external decrement: ref => unit = "%decr" +} diff --git a/runtime/Stdlib_Pair.res b/runtime/Stdlib_Pair.res new file mode 100644 index 0000000000..767ad280ff --- /dev/null +++ b/runtime/Stdlib_Pair.res @@ -0,0 +1,68 @@ +/*** +This module provides functions to work with pairs, which are 2-element tuples. +*/ + +type t<'a, 'b> = ('a, 'b) + +/** +`first(pair)` returns the first element of a pair. + +## Examples + +```rescript +Pair.first((1, 2))->assertEqual(1) +``` +*/ +external first: (('a, 'b)) => 'a = "%field0" + +/** +`second(pair)` returns the second element of a pair. + +## Examples + +```rescript +Pair.second((1, 2))->assertEqual(2) +``` +*/ +external second: (('a, 'b)) => 'b = "%field1" + +/** + `ignore(option)` ignores the provided pair and returns unit. + + This helper is useful when you want to discard a value (for example, the result of an operation with side effects) + without having to store or process it further. +*/ +external ignore: ('a, 'b) => unit = "%ignore" + +/** +`equal(pair1, pair2, f1, f2)` check equality of `pair2` and `pair2` using `f1` for +equality on the first element and `f2` for equality on the second element. + +## Examples + +```rescript +Pair.equal((1, "test"), (1, "test"), Int.equal, String.equal)->assertEqual(true) + +Pair.equal((1, "test"), (2, "test"), Int.equal, String.equal)->assertEqual(false) +``` +*/ +let equal = ((a1, a2), (b1, b2), eq1, eq2) => eq1(a1, b1) && eq2(a2, b2) + +/** +`compare(pair1, pair2, f1, f2)` compares two pairs, using `f1` to compare the first element +and `f2` to compare the second element. Ordering is based on the first element, +if they are equal, the second element is compared. + +## Examples + +```rescript +Pair.compare((1, "a"), (1, "a"), Int.compare, String.compare)->assertEqual(Ordering.equal) +Pair.compare((1, "a"), (1, "b"), Int.compare, String.compare)->assertEqual(Ordering.less) +Pair.compare((2, "a"), (1, "b"), Int.compare, String.compare)->assertEqual(Ordering.greater) +``` +*/ +let compare = ((a1, a2), (b1, b2), cmp1, cmp2) => + switch cmp1(a1, b1) { + | 0. => cmp2(a2, b2) + | result => result + } diff --git a/runtime/rescript.json b/runtime/rescript.json index b39c522cb5..b9e194db8f 100644 --- a/runtime/rescript.json +++ b/runtime/rescript.json @@ -9,7 +9,7 @@ "-make-runtime", "-nostdlib", "-nopervasives", - "-open Pervasives_mini", + "-open Pervasives", "-no-keep-locs", "-no-alias-deps", "-bs-no-version-header",