Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
- Fixed type signatures of `reduce` and `reduceWithIndex`. https://github.com/rescript-association/rescript-core/pull/49
- Add `panic`/`Error.panic`. https://github.com/rescript-association/rescript-core/pull/72
- The globally available `null` value now originates from `Nullable` and not `Null`, just like the globally available `undefined` value does. https://github.com/rescript-association/rescript-core/pull/88
- Add `Int.range` and `Int.rangeWithOptions`, https://github.com/rescript-association/rescript-core/pull/52

### Documentation

39 changes: 39 additions & 0 deletions src/Core__Int.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Generated by ReScript, PLEASE EDIT WITH CARE

import * as Pervasives from "rescript/lib/es6/pervasives.js";
import * as Core__Array from "./Core__Array.mjs";

function fromString(radix, x) {
var maybeInt = radix !== undefined ? parseInt(x, radix) : parseInt(x);
@@ -10,6 +12,41 @@ function fromString(radix, x) {
}
}

function rangeWithOptions(start, end, options) {
var isInverted = start > end;
var n = options.step;
var step;
if (n !== undefined) {
if (n !== 0) {
step = n;
} else {
if (start !== end) {
throw new RangeError("Incorrect range arguments");
}
step = n;
}
} else {
step = isInverted ? -1 : 1;
}
var length;
if (isInverted === step >= 0) {
length = 0;
} else if (step === 0) {
length = options.inclusive === true ? 1 : 0;
} else {
var range = isInverted ? start - end | 0 : end - start | 0;
var range$1 = options.inclusive === true ? range + 1 | 0 : range;
length = Math.ceil(range$1 / Pervasives.abs(step)) | 0;
}
return Core__Array.fromInitializer(length, (function (i) {
return start + Math.imul(i, step) | 0;
}));
}

function range(start, end) {
return rangeWithOptions(start, end, {});
}

var Constants = {
minValue: -2147483648,
maxValue: 2147483647
@@ -18,5 +55,7 @@ var Constants = {
export {
Constants ,
fromString ,
range ,
rangeWithOptions ,
}
/* No side effect */
26 changes: 26 additions & 0 deletions src/Core__Int.res
Original file line number Diff line number Diff line change
@@ -35,3 +35,29 @@ let fromString = (~radix=?, x) => {
}

external mod: (int, int) => int = "%modint"

type rangeOptions = {step?: int, inclusive?: bool}
let rangeWithOptions = (start, end, options) => {
let isInverted = start > end

let step = switch options.step {
| None => isInverted ? -1 : 1
| Some(0) if start !== end =>
Core__Error.raise(Core__Error.RangeError.make("Incorrect range arguments"))
| Some(n) => n
}

let length = if isInverted === (step >= 0) {
0 // infinite because step goes in opposite direction of end
} else if step == 0 {
options.inclusive === Some(true) ? 1 : 0
} else {
let range = isInverted ? start - end : end - start
let range = options.inclusive === Some(true) ? range + 1 : range
ceil(float(range) /. float(abs(step)))->Core__Float.toInt
}

Core__Array.fromInitializer(~length, i => start + i * step)
}

let range = (start, end) => rangeWithOptions(start, end, {})
54 changes: 54 additions & 0 deletions src/Core__Int.resi
Original file line number Diff line number Diff line change
@@ -268,3 +268,57 @@ Int.mod(7, 4) == 3
```
*/
external mod: (int, int) => int = "%modint"

/**
`range(start, end)` returns an int array of the sequence of integers in the
range `[start, end)`. That is, including `start` but excluding `end`.
If `start < end` the sequence will be increasing in steps of 1.
If `start > end` the sequence will be decreasing in steps of -1.
This is equivalent to `rangeWithOptions` with `inclusive` set to `false` and
`step` set to `1` if `start < end` and `-1` otherwise.
## Examples
```rescript
Int.range(3, 6) == [3, 4, 5]
Int.range(-3, -1) == [-3, -2]
Int.range(3, 1) == [3, 2]
```
*/
let range: (int, int) => array<int>

/**
The options for `rangeWithOptions`.
*/
type rangeOptions = {step?: int, inclusive?: bool}

/**
`rangeWithOptions(start, end, options)` is like `range`, but with `step` and
`inclusive` options configurable.
If `step` is set, the sequence will increase or decrease by that amount for each
step. If `start < end` and `step` is negative, or vice versa, an empty array is
returned since the sequence would otherwise never reach or exceed the end value
and hence be infinite. If `step` is `0` and `start !=` end, a `RangeError` is
raised as the sequence would never reach or exceed the end value and hence be
infinite.
If `inclusive` is set to `true`, the sequence will include `end` if `step` is
set such that the sequence includes it.
## Examples
```rescript
Int.rangeWithOptions(3, 7, {step: 2}) == [3, 5]
Int.rangeWithOptions(3, 7, {step: 2, inclusive: true}) == [3, 5, 7]
Int.rangeWithOptions(3, 6, {step: -2}) // RangeError
```
## Exceptions
- Raises `RangeError` if `step == 0 && start != end`.
*/
let rangeWithOptions: (int, int, rangeOptions) => array<int>
466 changes: 466 additions & 0 deletions test/IntTests.mjs

Large diffs are not rendered by default.

163 changes: 163 additions & 0 deletions test/IntTests.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
open RescriptCore

let eq = (a, b) => a == b

let catch = f =>
try {
let _ = f()
failwith("no exception raised")
} catch {
| Exn.Error(err) => err
}

Test.run(__POS_OF__("range - positive, increasing"), Int.range(3, 6), eq, [3, 4, 5])
Test.run(__POS_OF__("range - negative, increasing"), Int.range(-3, -1), eq, [-3, -2])
Test.run(__POS_OF__("range - cross-zero, incresing"), Int.range(-1, 2), eq, [-1, 0, 1])
Test.run(__POS_OF__("range - start == end"), Int.range(3, 3), eq, [])
Test.run(__POS_OF__("range - positive, decreasing"), Int.range(3, 1), eq, [3, 2])
Test.run(__POS_OF__("range - negative, decreasing"), Int.range(-1, -3), eq, [-1, -2])

Test.run(
__POS_OF__("rangeWithOptions - positive, increasing, step 2"),
Int.rangeWithOptions(3, 6, {step: 2}),
eq,
[3, 5],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step 2"),
Int.rangeWithOptions(3, 7, {step: 2}),
eq,
[3, 5],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step 2"),
Int.rangeWithOptions(3, 8, {step: 2}),
eq,
[3, 5, 7],
)
Test.run(
__POS_OF__("rangeWithOptions - negative, increasing, step 2"),
Int.rangeWithOptions(-6, -3, {step: 2}),
eq,
[-6, -4],
)
Test.run(
__POS_OF__("rangeWithOptions - positive, increasing, step 0"),
catch(() => Int.rangeWithOptions(3, 6, {step: 0})),
eq,
Error.RangeError.make("Incorrect range arguments"),
)
Test.run(
__POS_OF__("rangeWithOptions - start == end, step 0"),
Int.rangeWithOptions(3, 3, {step: 0}),
eq,
[],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step -1"),
Int.rangeWithOptions(3, 6, {step: -1}),
eq,
[],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, decreasing, step 1"),
Int.rangeWithOptions(6, 3, {step: 1}),
eq,
[],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, decreasing, step -2"),
Int.rangeWithOptions(6, 3, {step: -2}),
eq,
[6, 4],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step -2"),
Int.rangeWithOptions(6, 2, {step: -2}),
eq,
[6, 4],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step -2"),
Int.rangeWithOptions(6, 1, {step: -2}),
eq,
[6, 4, 2],
)
Test.run(
__POS_OF__("rangeWithOptions + negative, decreasing, step -2"),
Int.rangeWithOptions(-3, -6, {step: -2}),
eq,
[-3, -5],
)
Test.run(
__POS_OF__("rangeWithOptions - positive, increasing, step 2, inclusive"),
Int.rangeWithOptions(3, 6, {step: 2, inclusive: true}),
eq,
[3, 5],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step 2, inclusive"),
Int.rangeWithOptions(3, 7, {step: 2, inclusive: true}),
eq,
[3, 5, 7],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step 2, inclusive"),
Int.rangeWithOptions(3, 8, {step: 2, inclusive: true}),
eq,
[3, 5, 7],
)
Test.run(
__POS_OF__("rangeWithOptions - negative, increasing, step 2, inclusive"),
Int.rangeWithOptions(-6, -3, {step: 2, inclusive: true}),
eq,
[-6, -4],
)
Test.run(
__POS_OF__("rangeWithOptions - positive, increasing, step 0, inclusive"),
catch(() => Int.rangeWithOptions(3, 6, {step: 0, inclusive: true})),
eq,
Error.RangeError.make("Incorrect range arguments"),
)
Test.run(
__POS_OF__("rangeWithOptions - start == end, step 0, inclusive"),
Int.rangeWithOptions(3, 3, {step: 0, inclusive: true}),
eq,
[3],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step -1, inclusive"),
Int.rangeWithOptions(3, 6, {step: -1, inclusive: true}),
eq,
[],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, decreasing, step 1, inclusive"),
Int.rangeWithOptions(6, 3, {step: 1, inclusive: true}),
eq,
[],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, decreasing, step -2, inclusive"),
Int.rangeWithOptions(6, 3, {step: -2, inclusive: true}),
eq,
[6, 4],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step -2, inclusive"),
Int.rangeWithOptions(6, 2, {step: -2, inclusive: true}),
eq,
[6, 4, 2],
)
Test.run(
__POS_OF__("rangeWithOptions + positive, increasing, step -2, inclusive"),
Int.rangeWithOptions(6, 1, {step: -2, inclusive: true}),
eq,
[6, 4, 2],
)
Test.run(
__POS_OF__("rangeWithOptions + negative, decreasing, step -2, inclusive"),
Int.rangeWithOptions(-3, -6, {step: -2, inclusive: true}),
eq,
[-3, -5],
)
10 changes: 7 additions & 3 deletions test/TestSuite.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Generated by ReScript, PLEASE EDIT WITH CARE

import * as ErrorTests from "./ErrorTests.mjs";
import * as IntTests from "./IntTests.mjs";
import * as ArrayTests from "./ArrayTests.mjs";
import * as ErrorTests from "./ErrorTests.mjs";
import * as PromiseTest from "./PromiseTest.mjs";

var TestError = PromiseTest.TestError;
@@ -22,7 +23,9 @@ var Concurrently = PromiseTest.Concurrently;

var panicTest = ErrorTests.panicTest;

var eq = ArrayTests.eq;
var eq = IntTests.eq;

var $$catch = IntTests.$$catch;

export {
TestError ,
@@ -35,5 +38,6 @@ export {
Concurrently ,
panicTest ,
eq ,
$$catch ,
}
/* ArrayTests Not a pure module */
/* IntTests Not a pure module */
1 change: 1 addition & 0 deletions test/TestSuite.res
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include PromiseTest
include ErrorTests
include ArrayTests
include IntTests