From 36b197dc28dbe6a6229119c4867efdfd9b54a778 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 1 Apr 2024 12:59:16 -0300 Subject: [PATCH 01/22] initial --- scripts/DocTests.mjs | 52 +++++++++++++++++++++++++++++++++++++------- scripts/DocTests.res | 52 ++++++++++++++++++++++++++++++++++++-------- src/Core__Test.mjs | 2 ++ src/Core__Test.res | 14 ++++++++++++ 4 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 src/Core__Test.mjs create mode 100644 src/Core__Test.res diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index d07cd4bd..67b2d7fd 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -135,7 +135,7 @@ function createFileInTempDir(id) { return Path.join(Os.tmpdir(), id); } -async function testCode(id, code) { +async function compileTest(id, code) { var tempFileName = Path.join(Os.tmpdir(), id); await Promises.writeFile(tempFileName + ".res", code); var args = [ @@ -150,29 +150,64 @@ async function testCode(id, code) { ]; var promise = await new Promise((function (resolve, _reject) { var spawn = Child_process.spawn(bscBin, args); + var stdout = []; var stderr = []; + spawn.stdout.on("data", (function (data) { + stdout.push(data); + })); spawn.stderr.on("data", (function (data) { stderr.push(data); })); spawn.once("close", (function (_code, _signal) { - resolve(stderr); + resolve([ + stdout, + stderr + ]); })); })); - if (promise.length > 0) { + var stderr = promise[1]; + if (stderr.length > 0) { return { TAG: "Error", - _0: promise.map(function (e) { + _0: stderr.map(function (e) { return e.toString(); }).join("") }; } else { return { TAG: "Ok", - _0: undefined + _0: promise[0].map(function (e) { + return e.toString(); + }).join("") }; } } +async function run(command, args) { + return await new Promise((function (resolve, _reject) { + var spawn = Child_process.spawn(command, args); + var stdout = []; + var stderr = []; + spawn.stdout.on("data", (function (data) { + stdout.push(data); + })); + spawn.stderr.on("data", (function (data) { + stderr.push(data); + })); + spawn.once("close", (function (code, _signal) { + resolve({ + stdout: stdout, + stderr: stderr, + code: code + }); + })); + })); +} + +var SpawnAsync = { + run: run +}; + function extractDocFromFile(file) { var toolsBin = Path.join(Path.dirname(dirname), "node_modules", ".bin", "rescript-tools"); var spawn = Child_process.spawnSync(toolsBin, [ @@ -302,12 +337,12 @@ function getCodeBlocks(example) { } async function main() { - var results = await Promise.all(getExamples(extractDocFromFile("src/RescriptCore.res")).map(async function (example) { + var results = await Promise.all(getExamples(extractDocFromFile("src/Core__Test.res")).map(async function (example) { var id = example.id.replaceAll(".", "_"); var codes = getCodeBlocks(example); var results = await Promise.all(codes.map(async function (code, $$int) { var id$1 = id + "_" + $$int.toString(); - return await testCode(id$1, code); + return await compileTest(id$1, code); })); return [ example, @@ -370,7 +405,8 @@ export { rescriptJson , prepareCompiler , createFileInTempDir , - testCode , + compileTest , + SpawnAsync , extractDocFromFile , getExamples , getCodeBlocks , diff --git a/scripts/DocTests.res b/scripts/DocTests.res index 2eb81eb2..07aada35 100644 --- a/scripts/DocTests.res +++ b/scripts/DocTests.res @@ -40,7 +40,7 @@ module Node = { external spawnSync: (string, array) => spawnSyncReturns = "spawnSync" type readable - type spawnReturns = {stderr: readable} + type spawnReturns = {stderr: readable, stdout: readable} @module("child_process") external spawn: (string, array) => spawnReturns = "spawn" @@ -153,7 +153,7 @@ type example = { let createFileInTempDir = id => Path.join2(OS.tmpdir(), id) -let testCode = async (~id, ~code) => { +let compileTest = async (~id, ~code) => { let tempFileName = createFileInTempDir(id) let () = await Fs.writeFile(tempFileName ++ ".res", code) @@ -171,22 +171,56 @@ let testCode = async (~id, ~code) => { let promise = await Promise.make((resolve, _reject) => { let spawn = ChildProcess.spawn(bscBin, args) + let stdout = [] let stderr = [] + spawn.stdout->ChildProcess.on("data", data => { + Array.push(stdout, data) + }) spawn.stderr->ChildProcess.on("data", data => { Array.push(stderr, data) }) spawn->ChildProcess.once("close", (_code, _signal) => { - resolve(stderr) + resolve((stdout, stderr)) }) }) - switch Array.length(promise) > 0 { + let (stdout, stderr) = promise + + switch Array.length(stderr) > 0 { | true => - promise + stderr ->Array.map(e => e->Buffer.toString) ->Array.joinWith("") ->Error - | false => Ok() + | false => + stdout + ->Array.map(e => e->Buffer.toString) + ->Array.joinWith("") + ->Ok + } +} + +module SpawnAsync = { + type t = { + stdout: array, + stderr: array, + code: Null.t, + } + let run = async (~command, ~args) => { + await Promise.make((resolve, _reject) => { + let spawn = ChildProcess.spawn(command, args) + let stdout = [] + let stderr = [] + spawn.stdout->ChildProcess.on("data", data => { + Array.push(stdout, data) + }) + spawn.stderr->ChildProcess.on("data", data => { + Array.push(stderr, data) + }) + spawn->ChildProcess.once("close", (code, _signal) => { + resolve({stdout, stderr, code}) + }) + }) } } @@ -278,7 +312,7 @@ let getCodeBlocks = example => { let main = async () => { let results = - await extractDocFromFile("src/RescriptCore.res") + await extractDocFromFile("src/Core__Test.res") ->getExamples ->Array.map(async example => { let id = example.id->String.replaceAll(".", "_") @@ -287,7 +321,7 @@ let main = async () => { await codes ->Array.mapWithIndex(async (code, int) => { let id = `${id}_${Int.toString(int)}` - await testCode(~id, ~code) + await compileTest(~id, ~code) }) ->Promise.all (example, results) @@ -297,7 +331,7 @@ let main = async () => { let errors = results->Belt.Array.keepMap(((example, results)) => { let errors = results->Belt.Array.keepMap(result => switch result { - | Ok() => None + | Ok(_) => None | Error(msg) => Some(msg) } ) diff --git a/src/Core__Test.mjs b/src/Core__Test.mjs new file mode 100644 index 00000000..d856702b --- /dev/null +++ b/src/Core__Test.mjs @@ -0,0 +1,2 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/src/Core__Test.res b/src/Core__Test.res new file mode 100644 index 00000000..70de0930 --- /dev/null +++ b/src/Core__Test.res @@ -0,0 +1,14 @@ +/** +`last(array)` returns the last element of `array`. + +Returns `None` if the array is empty. + +## Examples +```rescript +let array = ["Hello", "Hi", "Good bye"] + +array->Array.last == Some("Good bye") // true +[]->Array.last == None // true +``` +*/ +@send external at: (array<'a>, int) => option<'a> = "at" From 47532401d2fe9432145dd2a7fb8ddd020f51bed8 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 7 Apr 2024 18:44:03 -0300 Subject: [PATCH 02/22] update --- scripts/DocTests.mjs | 232 +++++++++++++++++++++++++++++-------------- scripts/DocTests.res | 195 +++++++++++++++++++++++------------- src/Core__Test.mjs | 2 - src/Core__Test.res | 14 --- 4 files changed, 281 insertions(+), 162 deletions(-) delete mode 100644 src/Core__Test.mjs delete mode 100644 src/Core__Test.res diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index 2ed30af5..cb2295b6 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -7,6 +7,7 @@ import * as Path from "path"; import * as Belt_List from "rescript/lib/es6/belt_List.js"; import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; import * as Core__List from "../src/Core__List.mjs"; +import * as Caml_option from "rescript/lib/es6/caml_option.js"; import * as Core__Array from "../src/Core__Array.mjs"; import * as RescriptCore from "../src/RescriptCore.mjs"; import * as Tools_Docgen from "@rescript/tools/npm/Tools_Docgen.mjs"; @@ -72,7 +73,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 128, + 129, 9 ], Error: new Error() @@ -85,7 +86,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 126, + 127, 11 ], Error: new Error() @@ -98,7 +99,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 126, + 127, 11 ], Error: new Error() @@ -109,7 +110,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 128, + 129, 9 ], Error: new Error() @@ -131,6 +132,31 @@ function prepareCompiler() { prepareCompiler(); +async function run(command, args, options) { + return await new Promise((function (resolve, _reject) { + var spawn = Child_process.spawn(command, args, options !== undefined ? Caml_option.valFromOption(options) : undefined); + var stdout = []; + var stderr = []; + spawn.stdout.on("data", (function (data) { + stdout.push(data); + })); + spawn.stderr.on("data", (function (data) { + stderr.push(data); + })); + spawn.once("close", (function (code, _signal) { + resolve({ + stdout: stdout, + stderr: stderr, + code: code + }); + })); + })); +} + +var SpawnAsync = { + run: run +}; + function createFileInTempDir(id) { return Path.join(Os.tmpdir(), id); } @@ -148,24 +174,8 @@ async function compileTest(id, code) { "-open", "RescriptCore" ]; - var promise = await new Promise((function (resolve, _reject) { - var spawn = Child_process.spawn(bscBin, args); - var stdout = []; - var stderr = []; - spawn.stdout.on("data", (function (data) { - stdout.push(data); - })); - spawn.stderr.on("data", (function (data) { - stderr.push(data); - })); - spawn.once("close", (function (_code, _signal) { - resolve([ - stdout, - stderr - ]); - })); - })); - var stderr = promise[1]; + var match = await run(bscBin, args, undefined); + var stderr = match.stderr; if (stderr.length > 0) { return { TAG: "Error", @@ -176,38 +186,13 @@ async function compileTest(id, code) { } else { return { TAG: "Ok", - _0: promise[0].map(function (e) { + _0: match.stdout.map(function (e) { return e.toString(); }).join("") }; } } -async function run(command, args) { - return await new Promise((function (resolve, _reject) { - var spawn = Child_process.spawn(command, args); - var stdout = []; - var stderr = []; - spawn.stdout.on("data", (function (data) { - stdout.push(data); - })); - spawn.stderr.on("data", (function (data) { - stderr.push(data); - })); - spawn.once("close", (function (code, _signal) { - resolve({ - stdout: stdout, - stderr: stderr, - code: code - }); - })); - })); -} - -var SpawnAsync = { - run: run -}; - function extractDocFromFile(file) { var toolsBin = Path.join(Path.dirname(dirname), "node_modules", ".bin", "rescript-tools"); var spawn = Child_process.spawnSync(toolsBin, [ @@ -336,49 +321,142 @@ function getCodeBlocks(example) { }))), /* [] */0)); } -async function main() { - var results = await Promise.all(getExamples(extractDocFromFile("src/Core__Test.res")).map(async function (example) { +async function runtimeTests(code) { + var match = await run("node", [ + "-p", + code + ], { + cwd: compilerDir + }); + var stderr = match.stderr; + if (stderr.length > 0) { + return { + TAG: "Error", + _0: stderr.map(function (e) { + return e.toString(); + }).join("") + }; + } else { + return { + TAG: "Ok", + _0: match.stdout.map(function (e) { + return e.toString(); + }).join("") + }; + } +} + +function indentOutputCode(code) { + var indent = " ".repeat(2); + return code.split("\n").map(function (s) { + return indent + s; + }).join("\n"); +} + +async function compilerResults() { + var results = await Promise.all(getExamples(extractDocFromFile("src/RescriptCore.res")).map(async function (example) { var id = example.id.replaceAll(".", "_"); var codes = getCodeBlocks(example); var results = await Promise.all(codes.map(async function (code, $$int) { var id$1 = id + "_" + $$int.toString(); - return await compileTest(id$1, code); + return [ + code, + await compileTest(id$1, code) + ]; })); return [ example, results ]; })); - var errors = Belt_Array.keepMap(results, (function (param) { - var errors = Belt_Array.keepMap(param[1], (function (result) { - if (result.TAG === "Ok") { - return ; - } else { - return result._0; - } - })); - if (errors.length > 0) { + var examples = results.map(function (param) { + var match = Core__Array.reduce(param[1], [ + [], + [] + ], (function (acc, param) { + var errors = acc[1]; + var oks = acc[0]; + var result = param[1]; + if (result.TAG === "Ok") { + return [ + Belt_Array.concatMany([ + oks, + [[ + param[0], + result._0 + ]] + ]), + errors + ]; + } else { + return [ + oks, + Belt_Array.concatMany([ + errors, + [{ + TAG: "ReScript", + error: result._0 + }] + ]) + ]; + } + })); + return [ + param[0], + [ + match[0], + match[1] + ] + ]; + }); + var errors = await Promise.all(examples.map(async function (param) { + var match = param[1]; + var nodeTests = await Promise.all(match[0].map(async function (param) { + var js = param[1]; + return [ + param[0], + js, + await runtimeTests(js) + ]; + })); + var runtimeErrors = Belt_Array.keepMap(nodeTests, (function (param) { + var output = param[2]; + if (output.TAG === "Ok") { + return ; + } else { + return { + TAG: "Runtime", + rescript: param[0], + js: param[1], + error: output._0 + }; + } + })); return [ param[0], - errors + runtimeErrors.concat(match[1]) ]; - } - - })); + })); errors.forEach(function (param) { - var test = param[0]; + var example = param[0]; var cyan = function (s) { return "\x1b[36m" + s + "\x1b[0m"; }; - var other = test.kind; + var other = example.kind; var kind = other === "moduleAlias" ? "module alias" : other; - var errorMessage = param[1].map(function (e) { - return e.split("\n").filter(function (param, i) { - return i !== 2; - }).join("\n"); - }).join("\n"); - var message = "\x1B[1;31merror\x1B[0m: failed to compile examples from " + kind + " " + cyan(test.id) + "\n" + errorMessage; - process.stderr.write(message); + var errorMessage = param[1].map(function (err) { + if (err.TAG === "ReScript") { + var err$1 = err.error.split("\n").filter(function (param, i) { + return i !== 2; + }).join("\n"); + return "\x1B[1;31merror\x1B[0m: failed to compile examples from " + kind + " " + cyan(example.id) + "\n" + err$1; + } + var indent = " ".repeat(2); + return "\x1B[1;31mruntime error\x1B[0m: failed to run examples from " + kind + " " + cyan(example.id) + "\n\n" + indent + "\x1b[36mReScript\x1b[0m\n\n" + indentOutputCode(err.rescript) + "\n\n" + indent + "\x1b[36mCompiled Js\x1b[0m\n\n" + indentOutputCode(err.js) + "\n\n" + indent + "\x1B[1;31mstacktrace\x1B[0m\n\n" + indentOutputCode(err.error) + "\n"; + }); + errorMessage.forEach(function (e) { + process.stderr.write(e); + }); }); if (errors.length === 0) { return 0; @@ -387,7 +465,7 @@ async function main() { } } -var exitCode = await main(); +var exitCode = await compilerResults(); process.exit(exitCode); @@ -404,13 +482,15 @@ export { makePackageJson , rescriptJson , prepareCompiler , + SpawnAsync , createFileInTempDir , compileTest , - SpawnAsync , extractDocFromFile , getExamples , getCodeBlocks , - main , + runtimeTests , + indentOutputCode , + compilerResults , exitCode , } /* dirname Not a pure module */ diff --git a/scripts/DocTests.res b/scripts/DocTests.res index 7a87bbd4..dafd2012 100644 --- a/scripts/DocTests.res +++ b/scripts/DocTests.res @@ -41,8 +41,9 @@ module Node = { type readable type spawnReturns = {stderr: readable, stdout: readable} + type options = {cwd?: string} @module("child_process") - external spawn: (string, array) => spawnReturns = "spawn" + external spawn: (string, array, ~options: options=?) => spawnReturns = "spawn" @send external on: (readable, string, Buffer.t => unit) => unit = "on" @send @@ -151,6 +152,30 @@ type example = { docstrings: array, } +module SpawnAsync = { + type t = { + stdout: array, + stderr: array, + code: Null.t, + } + let run = async (~command, ~args, ~options=?) => { + await Promise.make((resolve, _reject) => { + let spawn = ChildProcess.spawn(command, args, ~options?) + let stdout = [] + let stderr = [] + spawn.stdout->ChildProcess.on("data", data => { + Array.push(stdout, data) + }) + spawn.stderr->ChildProcess.on("data", data => { + Array.push(stderr, data) + }) + spawn->ChildProcess.once("close", (code, _signal) => { + resolve({stdout, stderr, code}) + }) + }) + } +} + let createFileInTempDir = id => Path.join2(OS.tmpdir(), id) let compileTest = async (~id, ~code) => { @@ -169,22 +194,7 @@ let compileTest = async (~id, ~code) => { "RescriptCore", ] - let promise = await Promise.make((resolve, _reject) => { - let spawn = ChildProcess.spawn(bscBin, args) - let stdout = [] - let stderr = [] - spawn.stdout->ChildProcess.on("data", data => { - Array.push(stdout, data) - }) - spawn.stderr->ChildProcess.on("data", data => { - Array.push(stderr, data) - }) - spawn->ChildProcess.once("close", (_code, _signal) => { - resolve((stdout, stderr)) - }) - }) - - let (stdout, stderr) = promise + let {stderr, stdout} = await SpawnAsync.run(~command=bscBin, ~args) switch Array.length(stderr) > 0 { | true => @@ -195,35 +205,11 @@ let compileTest = async (~id, ~code) => { | false => stdout ->Array.map(e => e->Buffer.toString) - ->Array.joinWith("") + ->Array.join("") ->Ok } } -module SpawnAsync = { - type t = { - stdout: array, - stderr: array, - code: Null.t, - } - let run = async (~command, ~args) => { - await Promise.make((resolve, _reject) => { - let spawn = ChildProcess.spawn(command, args) - let stdout = [] - let stderr = [] - spawn.stdout->ChildProcess.on("data", data => { - Array.push(stdout, data) - }) - spawn.stderr->ChildProcess.on("data", data => { - Array.push(stderr, data) - }) - spawn->ChildProcess.once("close", (code, _signal) => { - resolve({stdout, stderr, code}) - }) - }) - } -} - let extractDocFromFile = file => { let toolsBin = Path.join([Path.dirname(dirname), "node_modules", ".bin", "rescript-tools"]) let spawn = ChildProcess.spawnSync(toolsBin, ["doc", file]) @@ -310,9 +296,43 @@ let getCodeBlocks = example => { ->List.toArray } -let main = async () => { +let runtimeTests = async code => { + let {stdout, stderr} = await SpawnAsync.run( + ~command="node", + ~args=["-p", code], + ~options={cwd: compilerDir}, + ) + + switch Array.length(stderr) > 0 { + | true => + stderr + ->Array.map(e => e->Buffer.toString) + ->Array.join("") + ->Error + | false => + stdout + ->Array.map(e => e->Buffer.toString) + ->Array.join("") + ->Ok + } +} + +let indentOutputCode = code => { + let indent = String.repeat(" ", 2) + + code + ->String.split("\n") + ->Array.map(s => `${indent}${s}`) + ->Array.join("\n") +} + +type error = + | ReScript({error: string}) + | Runtime({rescript: string, js: string, error: string}) + +let compilerResults = async () => { let results = - await extractDocFromFile("src/Core__Test.res") + await extractDocFromFile("src/RescriptCore.res") ->getExamples ->Array.map(async example => { let id = example.id->String.replaceAll(".", "_") @@ -321,55 +341,90 @@ let main = async () => { await codes ->Array.mapWithIndex(async (code, int) => { let id = `${id}_${Int.toString(int)}` - await compileTest(~id, ~code) + (code, await compileTest(~id, ~code)) }) ->Promise.all (example, results) }) ->Promise.all - let errors = results->Belt.Array.keepMap(((example, results)) => { - let errors = results->Belt.Array.keepMap(result => + let examples = results->Array.map(((example, results)) => { + let (compiled, errors) = results->Array.reduce(([], []), (acc, (resCode, result)) => { + let (oks, errors) = acc switch result { - | Ok(_) => None - | Error(msg) => Some(msg) + | Ok(jsCode) => ([...oks, (resCode, jsCode)], errors) + | Error(output) => (oks, [...errors, ReScript({error: output})]) } - ) + }) - if Array.length(errors) > 0 { - Some((example, errors)) - } else { - None - } + (example, (compiled, errors)) }) + let errors = + await examples + ->Array.map(async ((example, (compiled, errors))) => { + let nodeTests = + await compiled + ->Array.map(async ((res, js)) => (res, js, await runtimeTests(js))) + ->Promise.all + + let runtimeErrors = nodeTests->Belt.Array.keepMap(((res, js, output)) => + switch output { + | Ok(_) => None + | Error(error) => Some(Runtime({rescript: res, js, error})) + } + ) + + (example, Array.concat(runtimeErrors, errors)) + }) + ->Promise.all + // Print Errors - let () = errors->Array.forEach(((test, errors)) => { + let () = errors->Array.forEach(((example, errors)) => { let red = s => `\x1B[1;31m${s}\x1B[0m` let cyan = s => `\x1b[36m${s}\x1b[0m` - let kind = switch test.kind { + let kind = switch example.kind { | "moduleAlias" => "module alias" | other => other } - let errorMessage = - errors - ->Array.map(e => { - // Drop line from path file - e - ->String.split("\n") - ->Array.filterWithIndex((_, i) => i !== 2) - ->Array.join("\n") - }) - ->Array.join("\n") + let errorMessage = errors->Array.map(err => + switch err { + | ReScript({error}) => + let err = + error + ->String.split("\n") + ->Array.filterWithIndex((_, i) => i !== 2) + ->Array.join("\n") - let message = `${"error"->red}: failed to compile examples from ${kind} ${test.id->cyan}\n${errorMessage}` + `${"error"->red}: failed to compile examples from ${kind} ${example.id->cyan} +${err}` + | Runtime({rescript, js, error}) => + let indent = String.repeat(" ", 2) - Process.stderrWrite(message) + `${"runtime error"->red}: failed to run examples from ${kind} ${example.id->cyan} + +${indent}${"ReScript"->cyan} + +${rescript->indentOutputCode} + +${indent}${"Compiled Js"->cyan} + +${js->indentOutputCode} + +${indent}${"stacktrace"->red} + +${error->indentOutputCode} +` + } + ) + + errorMessage->Array.forEach(e => Process.stderrWrite(e)) }) errors->Array.length == 0 ? 0 : 1 } -let exitCode = await main() + +let exitCode = await compilerResults() Process.exit(exitCode) diff --git a/src/Core__Test.mjs b/src/Core__Test.mjs deleted file mode 100644 index d856702b..00000000 --- a/src/Core__Test.mjs +++ /dev/null @@ -1,2 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/src/Core__Test.res b/src/Core__Test.res deleted file mode 100644 index 70de0930..00000000 --- a/src/Core__Test.res +++ /dev/null @@ -1,14 +0,0 @@ -/** -`last(array)` returns the last element of `array`. - -Returns `None` if the array is empty. - -## Examples -```rescript -let array = ["Hello", "Hi", "Good bye"] - -array->Array.last == Some("Good bye") // true -[]->Array.last == None // true -``` -*/ -@send external at: (array<'a>, int) => option<'a> = "at" From bf7348e86b6c5304d16a434b58c8e69173586285 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 7 Apr 2024 19:10:41 -0300 Subject: [PATCH 03/22] add timeout --- scripts/DocTests.mjs | 5 +++-- scripts/DocTests.res | 15 +++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index cb2295b6..155e5cde 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -323,10 +323,11 @@ function getCodeBlocks(example) { async function runtimeTests(code) { var match = await run("node", [ - "-p", + "-e", code ], { - cwd: compilerDir + cwd: compilerDir, + timeout: 2000 }); var stderr = match.stderr; if (stderr.length > 0) { diff --git a/scripts/DocTests.res b/scripts/DocTests.res index dafd2012..0e970bf2 100644 --- a/scripts/DocTests.res +++ b/scripts/DocTests.res @@ -1,3 +1,5 @@ +open RescriptCore + module Node = { module Path = { @module("path") external join2: (string, string) => string = "join" @@ -41,14 +43,13 @@ module Node = { type readable type spawnReturns = {stderr: readable, stdout: readable} - type options = {cwd?: string} + type options = {cwd?: string, env?: Dict.t, timeout?: int} @module("child_process") external spawn: (string, array, ~options: options=?) => spawnReturns = "spawn" @send external on: (readable, string, Buffer.t => unit) => unit = "on" @send - external once: (spawnReturns, string, (Js.Null.t, Js.Null.t) => unit) => unit = - "once" + external once: (spawnReturns, string, (Null.t, Null.t) => unit) => unit = "once" } module OS = { @@ -57,7 +58,6 @@ module Node = { } } -open RescriptCore open Node module Docgen = RescriptTools.Docgen @@ -299,8 +299,11 @@ let getCodeBlocks = example => { let runtimeTests = async code => { let {stdout, stderr} = await SpawnAsync.run( ~command="node", - ~args=["-p", code], - ~options={cwd: compilerDir}, + ~args=["-e", code], + ~options={ + cwd: compilerDir, + timeout: 2000, + }, ) switch Array.length(stderr) > 0 { From 97f5e21a50936e045a618834c6af128474b19676 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 7 Apr 2024 21:18:35 -0300 Subject: [PATCH 04/22] fix node invalid errors --- scripts/DocTests.mjs | 50 +++++++++++++++++++++++++++++++++++--------- scripts/DocTests.res | 32 ++++++++++++++++++---------- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index 155e5cde..4a8e5ac7 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -329,18 +329,45 @@ async function runtimeTests(code) { cwd: compilerDir, timeout: 2000 }); + var exitCode = match.code; var stderr = match.stderr; - if (stderr.length > 0) { + var stdout = match.stdout; + var std; + var exit = 0; + if (exitCode !== null) { + if (exitCode === 0.0 && stderr.length > 0) { + std = { + TAG: "Ok", + _0: stderr + }; + } else if (exitCode === 0.0) { + std = { + TAG: "Ok", + _0: stdout + }; + } else { + exit = 1; + } + } else { + exit = 1; + } + if (exit === 1) { + std = { + TAG: "Error", + _0: stderr.length > 0 ? stderr : stdout + }; + } + if (std.TAG === "Ok") { return { - TAG: "Error", - _0: stderr.map(function (e) { + TAG: "Ok", + _0: std._0.map(function (e) { return e.toString(); }).join("") }; } else { return { - TAG: "Ok", - _0: match.stdout.map(function (e) { + TAG: "Error", + _0: std._0.map(function (e) { return e.toString(); }).join("") }; @@ -410,7 +437,7 @@ async function compilerResults() { ] ]; }); - var errors = await Promise.all(examples.map(async function (param) { + var exampleErrors = await Promise.all(examples.map(async function (param) { var match = param[1]; var nodeTests = await Promise.all(match[0].map(async function (param) { var js = param[1]; @@ -438,7 +465,7 @@ async function compilerResults() { runtimeErrors.concat(match[1]) ]; })); - errors.forEach(function (param) { + exampleErrors.forEach(function (param) { var example = param[0]; var cyan = function (s) { return "\x1b[36m" + s + "\x1b[0m"; @@ -459,10 +486,13 @@ async function compilerResults() { process.stderr.write(e); }); }); - if (errors.length === 0) { - return 0; - } else { + var someError = exampleErrors.some(function (param) { + return param[1].length > 0; + }); + if (someError) { return 1; + } else { + return 0; } } diff --git a/scripts/DocTests.res b/scripts/DocTests.res index 0e970bf2..1479a9c2 100644 --- a/scripts/DocTests.res +++ b/scripts/DocTests.res @@ -297,7 +297,7 @@ let getCodeBlocks = example => { } let runtimeTests = async code => { - let {stdout, stderr} = await SpawnAsync.run( + let {stdout, stderr, code: exitCode} = await SpawnAsync.run( ~command="node", ~args=["-e", code], ~options={ @@ -306,17 +306,25 @@ let runtimeTests = async code => { }, ) - switch Array.length(stderr) > 0 { - | true => - stderr + // Some expressions, like, `console.error("error")` is printed to stderr but + // exit code is 0 + let std = switch exitCode->Null.toOption { + | Some(exitCode) if exitCode == 0.0 && Array.length(stderr) > 0 => stderr->Ok + | Some(exitCode) if exitCode == 0.0 => stdout->Ok + | None | Some(_) => Error(Array.length(stderr) > 0 ? stderr : stdout) + } + + switch std { + | Ok(buf) => + buf ->Array.map(e => e->Buffer.toString) ->Array.join("") - ->Error - | false => - stdout + ->Ok + | Error(buf) => + buf ->Array.map(e => e->Buffer.toString) ->Array.join("") - ->Ok + ->Error } } @@ -363,7 +371,7 @@ let compilerResults = async () => { (example, (compiled, errors)) }) - let errors = + let exampleErrors = await examples ->Array.map(async ((example, (compiled, errors))) => { let nodeTests = @@ -383,7 +391,7 @@ let compilerResults = async () => { ->Promise.all // Print Errors - let () = errors->Array.forEach(((example, errors)) => { + let () = exampleErrors->Array.forEach(((example, errors)) => { let red = s => `\x1B[1;31m${s}\x1B[0m` let cyan = s => `\x1b[36m${s}\x1b[0m` let kind = switch example.kind { @@ -425,7 +433,9 @@ ${error->indentOutputCode} errorMessage->Array.forEach(e => Process.stderrWrite(e)) }) - errors->Array.length == 0 ? 0 : 1 + let someError = exampleErrors->Array.some(((_, err)) => Array.length(err) > 0) + + someError ? 1 : 0 } let exitCode = await compilerResults() From 04c2bcfbb4f9b0786fd89595176979a58fef9f8b Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 22 Apr 2024 11:36:41 -0300 Subject: [PATCH 05/22] Checkout js compiled --- scripts/DocTests.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index 434b0f17..9365fa17 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -387,7 +387,10 @@ async function compilerResults() { var codes = getCodeBlocks(example); var results = await Promise.all(codes.map(async function (code, $$int) { var id$1 = id + "_" + $$int.toString(undefined); - return await testCode(id$1, code); + return [ + code, + await compileTest(id$1, code) + ]; })); return [ example, From 722fe3d3a0e684653247405a4565198854390a29 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 22 Apr 2024 11:59:36 -0300 Subject: [PATCH 06/22] add assert_eq --- src/RescriptCore.mjs | 9 +++++++++ src/RescriptCore.res | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/RescriptCore.mjs b/src/RescriptCore.mjs index aad5ebf3..53f9cb1e 100644 --- a/src/RescriptCore.mjs +++ b/src/RescriptCore.mjs @@ -1,7 +1,15 @@ // Generated by ReScript, PLEASE EDIT WITH CARE +import * as Caml_obj from "rescript/lib/es6/caml_obj.js"; import * as Core__Error from "./Core__Error.mjs"; +function assert_eq(a, b) { + if (Caml_obj.notequal(a, b)) { + return Core__Error.panic("Assertion Failed"); + } + +} + var $$Array; var Console; @@ -147,5 +155,6 @@ export { List , Result , panic , + assert_eq , } /* No side effect */ diff --git a/src/RescriptCore.res b/src/RescriptCore.res index 1e245c47..69acc0e1 100644 --- a/src/RescriptCore.res +++ b/src/RescriptCore.res @@ -110,3 +110,20 @@ type undefined<+'a> = Js.undefined<'a> type nullable<+'a> = Js.nullable<'a> let panic = Core__Error.panic + +/** +`assert_eq(a, b)` check if `a` is equal `b`. If not raise a panic exception + +## Examples + +```rescript +list{1, 2} +->List.tailExn +->assert_eq(list{2}) +``` +*/ +let assert_eq = (a, b) => { + if a != b { + panic("Assertion Failed") + } +} From 32a53ac22c907a178d9d74db6c928f1abdb0707c Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 22 Apr 2024 13:26:28 -0300 Subject: [PATCH 07/22] add Array unit tests --- src/Core__Array.resi | 552 ++++++++++++++++++++++++++++--------------- test/ArrayTests.mjs | 477 ------------------------------------- test/ArrayTests.res | 113 --------- test/TestSuite.mjs | 1 - test/TestSuite.res | 1 - 5 files changed, 360 insertions(+), 784 deletions(-) delete mode 100644 test/ArrayTests.mjs delete mode 100644 test/ArrayTests.res diff --git a/src/Core__Array.resi b/src/Core__Array.resi index 529aa9cd..57c1cbe7 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -1,13 +1,16 @@ /** - `fromIterator(iterator)` +`fromIterator(iterator)` - Creates an array from the provided `iterator` +Creates an array from the provided `iterator` - ```res example - let map = Map.fromArray([("foo", 1), ("bar", 2)]) +## Examples - Array.fromIterator(map->Map.values) // [1, 2] - ``` +```rescript +Map.fromArray([("foo", 1), ("bar", 2)]) +->Map.values +->Array.fromIterator +->assert_eq([1, 2]) +``` */ @val external fromIterator: Core__Iterator.t<'a> => array<'a> = "Array.from" @@ -20,24 +23,32 @@ external fromIterator: Core__Iterator.t<'a> => array<'a> = "Array.from" external fromArrayLikeWithMap: (Js.Array2.array_like<'a>, 'a => 'b) => array<'b> = "Array.from" /** - `make(~length, init)` +`make(~length, init)` - Creates an array of length `length` initialized with the value of `init`. +Creates an array of length `length` initialized with the value of `init`. + +## Examples - ```res example - Array.make(~length=3, #apple) == [#apple, #apple, #apple] - ``` +```rescript +Array.make(~length=3, #apple)->assert_eq([#apple, #apple, #apple]) +Array.make(~length=6, 7)->assert_eq([7, 7, 7, 7, 7, 7]) +``` */ let make: (~length: int, 'a) => array<'a> /** - `fromInitializer(~length, f)` +`fromInitializer(~length, f)` + +Creates an array of length `length` initialized with the value returned from `f ` for each index. + +## Examples - Creates an array of length `length` initialized with the value returned from `f ` for each index. +```rescript +Array.fromInitializer(~length=3, i => i + 3)->assert_eq([3, 4, 5]) + +Array.fromInitializer(~length=7, i => i + 3)->assert_eq([3, 4, 5, 6, 7, 8, 9]) - ```res example - Array.fromInitializer(~length=3, i => i + 3) == [3, 4, 5] - ``` +``` */ let fromInitializer: (~length: int, int => 'a) => array<'a> @@ -53,10 +64,13 @@ let compare: (array<'a>, array<'a>, ('a, 'a) => Core__Ordering.t) => Core__Order See [`Array.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] -Console.log(someArray->Array.length) // 2 +someArray +->Array.length +->assert_eq(2) ``` */ @get @@ -81,11 +95,12 @@ Beware this will *mutate* the array. See [`Array.fill`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill) on MDN. ## Examples + ```rescript let myArray = [1, 2, 3, 4] -myArray->Array.fillAll(9) - -Console.log(myArray) // [9, 9, 9, 9] +myArray +->Array.fillAll(9) +->assert_eq([9, 9, 9, 9]) ``` */ @send @@ -99,11 +114,13 @@ Beware this will *mutate* the array. See [`Array.fill`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill) on MDN. ## Examples + ```rescript let myArray = [1, 2, 3, 4] -myArray->Array.fillToEnd(9, ~start=1) -Console.log(myArray) // [1, 9, 9, 9] +myArray +->Array.fillToEnd(9, ~start=1) +->assert_eq([1, 9, 9, 9]) ``` */ @send @@ -117,11 +134,13 @@ Beware this will *mutate* the array. See [`Array.fill`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill) on MDN. ## Examples + ```rescript let myArray = [1, 2, 3, 4] -myArray->Array.fill(9, ~start=1, ~end=2) -Console.log(myArray) // [1, 9, 9, 4] +myArray +->Array.fill(9, ~start=1, ~end=2) +->assert_eq([1, 9, 9, 4]) ``` */ @send @@ -135,11 +154,15 @@ Beware this will *mutate* the array. See [`Array.pop`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] -let lastItem = someArray->Array.pop // "hello" -Console.log(someArray) // ["hi"]. Notice last item is gone. +someArray +->Array.pop +->assert_eq(Some("hello")) + +someArray->assert_eq(["hi"]) // Notice last item is gone. ``` */ @send @@ -153,11 +176,13 @@ Beware this will *mutate* the array. See [`Array.push`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] + someArray->Array.push("yay") -Console.log(someArray) // ["hi", "hello", "yay"] +someArray->assert_eq(["hi", "hello", "yay"]) ``` */ @send @@ -171,11 +196,12 @@ Beware this will *mutate* the array. See [`Array.push`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] -someArray->Array.pushMany(["yay", "wehoo"]) -Console.log(someArray) // ["hi", "hello", "yay", "wehoo"] +someArray->Array.pushMany(["yay", "wehoo"]) +someArray->assert_eq(["hi", "hello", "yay", "wehoo"]) ``` */ @variadic @@ -190,11 +216,12 @@ Beware this will *mutate* the array. See [`Array.reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] someArray->Array.reverse -Console.log(someArray) // ["hello", "h1"] +someArray->assert_eq(["hello", "h1"]) ``` */ @send @@ -208,11 +235,15 @@ Beware this will *mutate* the array. See [`Array.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] -let lastItem = someArray->Array.shift // "hi" -Console.log(someArray) // ["hello"]. Notice first item is gone. +someArray +->Array.shift +->assert_eq(Some("hi")) + +someArray->assert_eq(["hello"]) // Notice first item is gone. ``` */ @send @@ -224,12 +255,15 @@ external shift: array<'a> => option<'a> = "shift" See [`Array.toSorted`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSorted) on MDN. ## Examples + ```rescript let someArray = [3, 2, 1] -let sorted = someArray->Array.toSorted(Int.compare) -Console.log(sorted) // [1, 2, 3] -Console.log(someArray) // [3, 2, 1]. Original unchanged +someArray +->Array.toSorted(Int.compare) +->assert_eq([1, 2, 3]) + +someArray->assert_eq([3, 2, 1]) // Original unchanged ``` */ @send @@ -243,11 +277,11 @@ Beware this will *mutate* the array. See [`Array.sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) on MDN. ## Examples -```rescript -let someArray = [3, 2, 1] -someArray->Array.sort((a, b) => float(a - b)) -Console.log(someArray) // [1, 2, 3] +```rescript +[3, 2, 1] +->Array.sort((a, b) => float(a - b)) +->assert_eq([1, 2, 3]) ``` */ @send @@ -270,11 +304,11 @@ Beware this will *mutate* the array. See [`Array.unshift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] someArray->Array.unshift("yay") - -Console.log(someArray) // ["yay", "hi", "hello"] +someArray->assert_eq(["yay", "hi", "hello"]) ``` */ @send @@ -288,11 +322,11 @@ Beware this will *mutate* the array. See [`Array.push`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] someArray->Array.unshiftMany(["yay", "wehoo"]) - -Console.log(someArray) // ["yay", "wehoo", "hi", "hello"] +someArray->assert_eq(["yay", "wehoo", "hi", "hello"]) ``` */ @variadic @@ -305,13 +339,14 @@ external unshiftMany: (array<'a>, array<'a>) => unit = "unshift" See [`Array.concat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) on MDN. ## Examples + ```rescript let array1 = ["hi", "hello"] let array2 = ["yay", "wehoo"] let someArray = array1->Array.concat(array2) -Console.log(someArray) // ["hi", "hello", "yay", "wehoo"] +someArray->assert_eq(["hi", "hello", "yay", "wehoo"]) ``` */ @send @@ -323,6 +358,7 @@ external concat: (array<'a>, array<'a>) => array<'a> = "concat" See [`Array.concat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) on MDN. ## Examples + ```rescript let array1 = ["hi", "hello"] let array2 = ["yay"] @@ -330,7 +366,7 @@ let array3 = ["wehoo"] let someArray = array1->Array.concatMany([array2, array3]) -Console.log(someArray) // ["hi", "hello", "yay", "wehoo"] +someArray->assert_eq(["hi", "hello", "yay", "wehoo"]) ``` */ @variadic @@ -343,8 +379,11 @@ external concatMany: (array<'a>, array>) => array<'a> = "concat" See [`Array.flat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) on MDN. ## Examples + ```rescript -Console.log([[1], [2], [3, 4]]->Array.flat) // [1, 2, 3, 4] +[[1], [2], [3, 4]] +->Array.flat +->assert_eq([1, 2, 3, 4]) ``` */ @send @@ -356,10 +395,14 @@ external flat: array> => array<'a> = "flat" See [`Array.includes`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) on MDN. ## Examples + ```rescript -Console.log([1, 2]->Array.includes(1)) // true -Console.log([1, 2]->Array.includes(3)) // false -Console.log([{"language": "ReScript"}]->Array.includes({"language": "ReScript"})) // false, because of strict equality +[1, 2]->Array.includes(1)->assert_eq(true) +[1, 2]->Array.includes(3)->assert_eq(false) + +[{"language": "ReScript"}] +->Array.includes({"language": "ReScript"}) +->assert_eq(false) // false, because of strict equality ``` */ @send @@ -373,10 +416,14 @@ Returns `-1` if the item doesn not exist. Check out `Array.indexOfOpt` for a ver See [`Array.indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) on MDN. ## Examples + ```rescript -Console.log([1, 2]->Array.indexOf(2)) // 1 -Console.log([1, 2]->Array.indexOf(3)) // -1 -Console.log([{"language": "ReScript"}]->Array.indexOf({"language": "ReScript"})) // -1, because of strict equality +[1, 2]->Array.indexOf(2)->assert_eq(1) +[1, 2]->Array.indexOf(3)->assert_eq(-1) + +[{"language": "ReScript"}] +->Array.indexOf({"language": "ReScript"}) +->assert_eq(-1) // -1, because of strict equality ``` */ @send @@ -388,10 +435,13 @@ external indexOf: (array<'a>, 'a) => int = "indexOf" See [`Array.indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) on MDN. ## Examples + ```rescript -Console.log([1, 2]->Array.indexOfOpt(2)) // Some(1) -Console.log([1, 2]->Array.indexOfOpt(3)) // None -Console.log([{"language": "ReScript"}]->Array.indexOfOpt({"language": "ReScript"})) // None, because of strict equality +[1, 2]->Array.indexOfOpt(2)->assert_eq(Some(1)) +[1, 2]->Array.indexOfOpt(3)->assert_eq(None) +[{"language": "ReScript"}] +->Array.indexOfOpt({"language": "ReScript"}) +->assert_eq(None) // None, because of strict equality ``` */ let indexOfOpt: (array<'a>, 'a) => option @@ -403,10 +453,11 @@ let indexOfOpt: (array<'a>, 'a) => option See [Array.join](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join) ## Examples -```rescript -let array = ["One", "Two", "Three"] -Console.log(array->Array.join(" -- ")) // One -- Two -- Three +```rescript +["One", "Two", "Three"] +->Array.join(" -- ") +->assert_eq("One -- Two -- Three") ``` */ @send @@ -417,9 +468,9 @@ external join: (array, string) => string = "join" ## Examples ```rescript -let array = ["One", "Two", "Three"] - -Console.log(array->Array.joinWith(" -- ")) // One -- Two -- Three +["One", "Two", "Three"] +->Array.joinWith(" -- ") +->assert_eq("One -- Two -- Three") ``` */ @deprecated("Use `join` instead") @@ -432,10 +483,11 @@ external joinWith: (array, string) => string = "join" See [Array.join](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join) ## Examples -```rescript -let array = [1, 2, 3] -Console.log(array->Array.joinUnsafe(" -- ")) // 1 -- 2 -- 3 +```rescript +[1, 2, 3] +->Array.joinUnsafe(" -- ") +->assert_eq("1 -- 2 -- 3") ``` */ @send @@ -445,10 +497,11 @@ external joinUnsafe: (array<'a>, string) => string = "join" `joinWithUnsafe(array, separator)` produces a string where all items of `array` are printed, separated by `separator`. Under the hood this will run JavaScript's `toString` on all the array items. ## Examples -```rescript -let array = [1, 2, 3] -Console.log(array->Array.joinWithUnsafe(" -- ")) // 1 -- 2 -- 3 +```rescript +[1, 2, 3] +->Array.joinWithUnsafe(" -- ") +->assert_eq("1 -- 2 -- 3") ``` */ @deprecated("Use `joinUnsafe` instead") @@ -464,10 +517,11 @@ let lastIndexOfOpt: (array<'a>, 'a) => option See [`Array.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) on MDN. ## Examples -```rescript -let myArray = [1, 2, 3, 4] -Console.log(myArray->Array.slice(~start=1, ~end=3)) // [2, 3] +```rescript +[1, 2, 3, 4] +->Array.slice(~start=1, ~end=3) +->assert_eq([2, 3]) ``` */ @send @@ -479,10 +533,11 @@ external slice: (array<'a>, ~start: int, ~end: int) => array<'a> = "slice" See [`Array.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) on MDN. ## Examples -```rescript -let myArray = [1, 2, 3, 4] -Console.log(myArray->Array.sliceToEnd(~start=1)) // [2, 3, 4] +```rescript +[1, 2, 3, 4] +->Array.sliceToEnd(~start=1) +->assert_eq([2, 3, 4]) ``` */ @send @@ -491,12 +546,13 @@ external sliceToEnd: (array<'a>, ~start: int) => array<'a> = "slice" `copy(array)` makes a copy of the array with the items in it, but does not make copies of the items themselves. ## Examples + ```rescript let myArray = [1, 2, 3] let copyOfMyArray = myArray->Array.copy -Console.log(copyOfMyArray) // [1, 2, 3] -Console.log(myArray === copyOfMyArray) // false +copyOfMyArray->assert_eq([1, 2, 3]) +assert_eq(myArray === copyOfMyArray, false) ``` */ @send @@ -508,10 +564,11 @@ external copy: array<'a> => array<'a> = "slice" See [`Array.toString`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString) on MDN. ## Examples -```rescript -let array = [1, 2, 3, 4] -Console.log(array->Array.toString) // "1,2,3,4" +```rescript +[1, 2, 3, 4] +->Array.toString +->assert_eq("1,2,3,4") ``` */ @send @@ -525,11 +582,17 @@ external toString: array<'a> => string = "toString" See [`Array.every`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every) on MDN. ## Examples + ```rescript let array = [1, 2, 3, 4] -Console.log(array->Array.every(num => num > 4)) // true -Console.log(array->Array.every(num => num === 1)) // false +array +->Array.every(num => num > 4) +->assert_eq(true) + +array +->Array.every(num => num === 1) +->assert_eq(false) ``` */ @send @@ -541,11 +604,17 @@ external every: (array<'a>, 'a => bool) => bool = "every" See [`Array.every`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every) on MDN. ## Examples + ```rescript let array = [1, 2, 3, 4] -Console.log(array->Array.everyWithIndex((num, index) => index < 2 && num <= 2)) // true -Console.log(array->Array.everyWithIndex((num, index) => index < 2 && num >= 2)) // false +array +->Array.everyWithIndex((num, index) => index < 2 && num <= 2) +->assert_eq(true) + +array +->Array.everyWithIndex((num, index) => index < 2 && num >= 2) +->assert_eq(false) ``` */ @send @@ -557,10 +626,11 @@ external everyWithIndex: (array<'a>, ('a, int) => bool) => bool = "every" See [`Array.filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) on MDN. ## Examples -```rescript -let array = [1, 2, 3, 4] -Console.log(array->Array.filter(num => num > 2)) // [3, 4] +```rescript +[1, 2, 3, 4] +->Array.filter(num => num > 2) +->assert_eq([3, 4]) ``` */ @send @@ -572,10 +642,11 @@ external filter: (array<'a>, 'a => bool) => array<'a> = "filter" See [`Array.filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) on MDN. ## Examples -```rescript -let array = [1, 2, 3, 4] -Console.log(array->Array.filterWithIndex((num, index) => index === 0 || num === 2)) // [1, 2] +```rescript +[1, 2, 3, 4] +->Array.filterWithIndex((num, index) => index === 0 || num === 2) +->assert_eq([1, 2]) ``` */ @send @@ -587,15 +658,15 @@ external filterWithIndex: (array<'a>, ('a, int) => bool) => array<'a> = "filter" See [`Array.find`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) on MDN. ## Examples + ```rescript type languages = ReScript | TypeScript | JavaScript let array = [ReScript, TypeScript, JavaScript] -switch array->Array.find(item => item == ReScript) { -| None => Console.log("No item...") -| Some(_) => Console.log("Yay, ReScript!") -} +array +->Array.find(item => item == ReScript) +->assert_eq(Some(ReScript)) ``` */ @send @@ -607,15 +678,15 @@ external find: (array<'a>, 'a => bool) => option<'a> = "find" See [`Array.find`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) on MDN. ## Examples + ```rescript type languages = ReScript | TypeScript | JavaScript let array = [TypeScript, JavaScript, ReScript] -switch array->Array.findWithIndex((item, index) => index > 1 && item == ReScript) { -| None => Console.log("No item...") -| Some(_) => Console.log("Yay, ReScript exists in a later position!") -} +array +->Array.findWithIndex((item, index) => index > 1 && item == ReScript) +->assert_eq(Some(ReScript)) ``` */ @send @@ -629,13 +700,18 @@ Returns `-1` if the item does not exist. Consider using `Array.findIndexOpt` if See [`Array.findIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) on MDN. ## Examples + ```rescript type languages = ReScript | TypeScript | JavaScript let array = [ReScript, JavaScript] -Console.log(array->Array.findIndex(item => item == ReScript)) // 0 -Console.log(array->Array.findIndex(item => item == TypeScript)) // -1 +array +->Array.findIndex(item => item == ReScript) +->assert_eq(0) + +array->Array.findIndex(item => item == TypeScript) +->assert_eq(-1) ``` */ @send @@ -649,6 +725,7 @@ Returns `-1` if the item does not exist. Consider using `Array.findIndexOpt` if See [`Array.findIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) on MDN. ## Examples + ```rescript type languages = ReScript | TypeScript | JavaScript @@ -657,8 +734,8 @@ let array = [ReScript, JavaScript] let isReScriptFirst = array->Array.findIndexWithIndex((item, index) => index === 0 && item == ReScript) let isTypeScriptFirst = array->Array.findIndexWithIndex((item, index) => index === 0 && item == TypeScript) -Console.log(isReScriptFirst) // 0 -Console.log(isTypeScriptFirst) // -1 +assert_eq(isReScriptFirst, 0) +assert_eq(isTypeScriptFirst, -1) ``` */ @send @@ -670,6 +747,7 @@ external findIndexWithIndex: (array<'a>, ('a, int) => bool) => int = "findIndex" See [`Array.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) on MDN. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] @@ -687,6 +765,7 @@ external forEach: (array<'a>, 'a => unit) => unit = "forEach" See [`Array.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) on MDN. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] @@ -704,11 +783,12 @@ external forEachWithIndex: (array<'a>, ('a, int) => unit) => unit = "forEach" See [`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) on MDN. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] let mappedArray = array->Array.map(greeting => greeting ++ " to you") -Console.log(mappedArray) // ["Hello to you", "Hi to you", "Good bye to you"] +assert_eq(mappedArray, ["Hello to you", "Hi to you", "Good bye to you"]) ``` */ @send @@ -720,6 +800,7 @@ external map: (array<'a>, 'a => 'b) => array<'b> = "map" See [`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) on MDN. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] let mappedArray = @@ -727,55 +808,80 @@ let mappedArray = greeting ++ " at position " ++ Int.toString(index) ) -Console.log(mappedArray) // ["Hello at position 0", "Hi at position 1", "Good bye at position 2"] +assert_eq(mappedArray, ["Hello at position 0", "Hi at position 1", "Good bye at position 2"]) ``` */ @send external mapWithIndex: (array<'a>, ('a, int) => 'b) => array<'b> = "map" /** - `reduce(xs, init, fn)` +`reduce(xs, init, fn)` + +Applies `fn` to each element of `xs` from beginning to end. Function `fn` has two parameters: the item from the list and an “accumulator”; which starts with a value of `init`. `reduce` returns the final value of the accumulator. + +## Examples + +```rescript +Array.reduce([2, 3, 4], 1, (a, b) => a + b)->assert_eq(10) - Applies `fn` to each element of `xs` from beginning to end. Function `fn` has two parameters: the item from the list and an “accumulator”; which starts with a value of `init`. `reduce` returns the final value of the accumulator. +Array.reduce(["a", "b", "c", "d"], "", (a, b) => a ++ b)->assert_eq("abcd") - ```res example - Array.reduce([2, 3, 4], 1, (a, b) => a + b) == 10 +[1, 2, 3] +->Array.reduce(list{}, List.add) +->assert_eq(list{3, 2, 1}) - Array.reduce(["a", "b", "c", "d"], "", (a, b) => a ++ b) == "abcd" - ``` +Array.reduce([], list{}, List.add)->assert_eq(list{}) +``` */ let reduce: (array<'a>, 'b, ('b, 'a) => 'b) => 'b /** - `reduceWithIndex(x, init, fn)` +`reduceWithIndex(x, init, fn)` + +Applies `fn` to each element of `xs` from beginning to end. Function `fn` has three parameters: the item from the array and an “accumulator”, which starts with a value of `init` and the index of each element. `reduceWithIndex` returns the final value of the accumulator. + +## Examples - Applies `fn` to each element of `xs` from beginning to end. Function `fn` has three parameters: the item from the array and an “accumulator”, which starts with a value of `init` and the index of each element. `reduceWithIndex` returns the final value of the accumulator. +```rescript +Array.reduceWithIndex([1, 2, 3, 4], 0, (acc, x, i) => acc + x + i)->assert_eq(16) + + +Array.reduceWithIndex([1, 2, 3], list{}, (acc, v, i) => list{v + i, ...acc})->assert_eq(list{5, 3, 1}) - ```res example - Array.reduceWithIndex([1, 2, 3, 4], 0, (acc, x, i) => acc + x + i) == 16 - ``` +Array.reduceWithIndex([], list{}, (acc, v, i) => list{v + i, ...acc})->assert_eq(list{}) +``` */ let reduceWithIndex: (array<'a>, 'b, ('b, 'a, int) => 'b) => 'b /** - `reduceRight(xs, init, fn)` +`reduceRight(xs, init, fn)` - Works like `Array.reduce`; except that function `fn` is applied to each item of `xs` from the last back to the first. +Works like `Array.reduce`; except that function `fn` is applied to each item of `xs` from the last back to the first. - ```res example - Array.reduceRight(["a", "b", "c", "d"], "", (a, b) => a ++ b) == "dcba" - ``` +## Examples + +```rescript +Array.reduceRight(["a", "b", "c", "d"], "", (a, b) => a ++ b)->assert_eq("dcba") + +Array.reduceRight([1, 2, 3], list{}, List.add)->assert_eq(list{1, 2, 3}) + +Array.reduceRight([], list{}, List.add)->assert_eq(list{}) +``` */ let reduceRight: (array<'a>, 'b, ('b, 'a) => 'b) => 'b /** - `reduceRightWithIndex(xs, init, fn)` +`reduceRightWithIndex(xs, init, fn)` - Like `reduceRight`, but with an additional index argument on the callback function. +Like `reduceRight`, but with an additional index argument on the callback function. - ```res example - Array.reduceRightWithIndex([1, 2, 3, 4], 0, (acc, x, i) => acc + x + i) == 16 - ``` +## Examples + +```rescript +Array.reduceRightWithIndex([1, 2, 3, 4], 0, (acc, x, i) => acc + x + i)->assert_eq(16) + +Array.reduceRightWithIndex([], list{}, (acc, v, i) => list{v + i, ...acc})->assert_eq(list{}) +``` */ let reduceRightWithIndex: (array<'a>, 'b, ('b, 'a, int) => 'b) => 'b @@ -785,10 +891,13 @@ let reduceRightWithIndex: (array<'a>, 'b, ('b, 'a, int) => 'b) => 'b See [`Array.some`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) on MDN. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] -Console.log(array->Array.some(greeting => greeting === "Hello")) // true +array +->Array.some(greeting => greeting === "Hello") +->assert_eq(true) ``` */ @send @@ -800,10 +909,13 @@ external some: (array<'a>, 'a => bool) => bool = "some" See [`Array.some`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) on MDN. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] -Console.log(array->Array.someWithIndex((greeting, index) => greeting === "Hello" && index === 0)) // true +array +->Array.someWithIndex((greeting, index) => greeting === "Hello" && index === 0) +->assert_eq(true) ``` */ @send @@ -815,11 +927,17 @@ external someWithIndex: (array<'a>, ('a, int) => bool) => bool = "some" Returns `None` if the index does not exist in the array. Equivalent to doing `array[index]` in JavaScript. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] -array->Array.get(0) == Some("Hello") // true -array->Array.get(3) == None // true +array +->Array.get(0) +->assert_eq(Some("Hello")) + +array +->Array.get(3) +->assert_eq(None) ``` */ @get_index @@ -831,11 +949,12 @@ external get: (array<'a>, int) => option<'a> = "" Beware this will *mutate* the array. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] array->Array.set(1, "Hello") -Console.log(array[1]) // "Hello" +array[1]->assert_eq("Hello") ``` */ @set_index @@ -852,12 +971,21 @@ This is _unsafe_, meaning it will return `undefined` value if `index` does not e Use `Array.getUnsafe` only when you are sure the `index` exists (i.e. when using for-loop). ## Examples + ```rescript let array = [1, 2, 3] for index in 0 to array->Array.length - 1 { let value = array->Array.getUnsafe(index) Console.log(value) } + +[0, 1, 2] +->Array.getUnsafe(1) +->assert_eq(1) + +[0, 1, 2] +->Array.getUnsafe(10) +->assert_eq(%raw(`undefined`)) ``` */ external getUnsafe: (array<'a>, int) => 'a = "%array_unsafe_get" @@ -868,11 +996,12 @@ external getUnsafe: (array<'a>, int) => 'a = "%array_unsafe_get" Beware this will *mutate* the array, and is *unsafe*. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] array->Array.setUnsafe(1, "Hello") -Console.log(array[1]) // "Hello" +assert_eq(array[1], "Hello") ``` */ external setUnsafe: (array<'a>, int, 'a) => unit = "%array_unsafe_set" @@ -885,15 +1014,15 @@ Returns `None` if no item matches. See [`Array.findIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) on MDN. ## Examples + ```rescript type languages = ReScript | TypeScript | JavaScript let array = [ReScript, TypeScript, JavaScript] -switch array->Array.findIndexOpt(item => item == ReScript) { -| None => Console.log("Ahh, no ReScript...") -| Some(index) => Console.log("Yay, ReScript at index " ++ Int.toString(index)) -} +array +->Array.findIndexOpt(item => item == ReScript) +->assert_eq(Some(0)) ``` */ let findIndexOpt: (array<'a>, 'a => bool) => option @@ -904,12 +1033,13 @@ let findIndexOpt: (array<'a>, 'a => bool) => option See [`Array.toReversed`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toReversed) on MDN. ## Examples + ```rescript let someArray = ["hi", "hello"] let reversed = someArray->Array.toReversed -Console.log(reversed) // ["hello", "h1"] -Console.log(someArray) // ["h1", "hello"]. Original unchanged +reversed->assert_eq(["hello", "h1"]) +someArray->assert_eq(["h1", "hello"]) // Original unchanged ``` */ @send @@ -921,30 +1051,45 @@ external toReversed: array<'a> => array<'a> = "toReversed" Calls `fn` for each element and returns a new array containing results of the `fn` calls which are not `None`. ## Examples + ```rescript -let array = ["Hello", "Hi", "Good bye"] +["Hello", "Hi", "Good bye"] +->Array.filterMap(item => + switch item { + | "Hello" => Some(item->String.length) + | _ => None + } +) +->assert_eq([5]) + +[1, 2, 3, 4, 5, 6] +->Array.filterMap(n => mod(n, 2) == 0 ? Some(n * n) : None) +->assert_eq([4, 16, 36]) + +Array.filterMap([1, 2, 3, 4, 5, 6], _ => None)->assert_eq([]) -Console.log( - array->Array.filterMap(item => - switch item { - | "Hello" => Some(item->String.length) - | _ => None - } - ), -) // [5] +Array.filterMap([], n => mod(n, 2) == 0 ? Some(n * n) : None)->assert_eq([]) ``` */ let filterMap: (array<'a>, 'a => option<'b>) => array<'b> /** - `keepSome(arr)` +`keepSome(arr)` + +Returns a new array containing `value` for all elements that are `Some(value)` +and ignoring every value that is `None` + +## Examples + +```rescript +Array.keepSome([Some(1), None, Some(3)])->assert_eq([1, 3]) - Returns a new array containing `value` for all elements that are `Some(value)` - and ignoring every value that is `None` +Array.keepSome([Some(1), Some(2), Some(3)])->assert_eq([1, 2, 3]) - ```res example - Array.keepSome([Some(1), None, Some(3)]) == [1, 3] - ``` +Array.keepSome([None, None, None])->assert_eq([]) + +Array.keepSome([])->assert_eq([]) +``` */ let keepSome: array> => array<'a> @@ -952,11 +1097,15 @@ let keepSome: array> => array<'a> `toShuffled(array)` returns a new array with all items in `array` in a random order. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] let shuffledArray = array->Array.toShuffled - Console.log(shuffledArray) + +Array.toShuffled([1, 2, 3]) +->Array.length +->assert_eq(3) ``` */ let toShuffled: array<'a> => array<'a> @@ -967,11 +1116,16 @@ let toShuffled: array<'a> => array<'a> Beware this will *mutate* the array. ## Examples + ```rescript let array = ["Hello", "Hi", "Good bye"] array->Array.shuffle - Console.log(array) + +[1, 2, 3] +->Array.shuffle +->Array.length +->assert_eq(3) ``` */ let shuffle: array<'a> => unit @@ -980,21 +1134,21 @@ let shuffle: array<'a> => unit `flatMap(array, mapper)` returns a new array concatenating the arrays returned from running `mapper` on all items in `array`. ## Examples + ```rescript type language = ReScript | TypeScript | JavaScript let array = [ReScript, TypeScript, JavaScript] -Console.log( - array->Array.flatMap(item => - switch item { - | ReScript => [1, 2, 3] - | TypeScript => [4, 5, 6] - | JavaScript => [7, 8, 9] - } - ), +array +->Array.flatMap(item => + switch item { + | ReScript => [1, 2, 3] + | TypeScript => [4, 5, 6] + | JavaScript => [7, 8, 9] + } ) -// [1, 2, 3, 4, 5, 6, 7, 8, 9] +->assert_eq([1, 2, 3, 4, 5, 6, 7, 8, 9]) ``` */ @send @@ -1004,52 +1158,62 @@ external flatMap: (array<'a>, 'a => array<'b>) => array<'b> = "flatMap" `flatMapWithIndex(array, mapper)` returns a new array concatenating the arrays returned from running `mapper` on all items in `array`. ## Examples + ```rescript type language = ReScript | TypeScript | JavaScript let array = [ReScript, TypeScript, JavaScript] -Console.log( - array->Array.flatMapWithIndex((item, index) => - switch item { - | ReScript => [index] - | TypeScript => [index, index + 1] - | JavaScript => [index, index + 1, index + 2] - } - ), + +array +->Array.flatMapWithIndex((item, index) => + switch item { + | ReScript => [index] + | TypeScript => [index, index + 1] + | JavaScript => [index, index + 1, index + 2] + } ) -// [0, 1, 2, 2, 3, 4] +->assert_eq([0, 1, 2, 2, 3, 4]) ``` */ @send external flatMapWithIndex: (array<'a>, ('a, int) => array<'b>) => array<'b> = "flatMap" /** - `findMap(arr, fn)` +`findMap(arr, fn)` + +Calls `fn` for each element and returns the first value from `fn` that is `Some(_)`. +Otherwise returns `None` + +## Examples + +```rescript +Array.findMap([1, 2, 3], n => mod(n, 2) == 0 ? Some(n - 2) : None)->assert_eq(Some(0)) + +Array.findMap([1, 2, 3, 4, 5, 6], n => mod(n, 2) == 0 ? Some(n - 8) : None)->assert_eq(Some(-6)) - Calls `fn` for each element and returns the first value from `fn` that is `Some(_)`. - Otherwise returns `None` +Array.findMap([1, 2, 3, 4, 5, 6], _ => None)->assert_eq(None) - ```res example - Array.findMap([1, 2, 3], n => mod(n, 2) == 0 ? Some(n - 2) : None) == Some(0) // true - ``` +Array.findMap([], n => mod(n, 2) == 0 ? Some(n * n) : None)->assert_eq(None) +``` */ let findMap: (array<'a>, 'a => option<'b>) => option<'b> /** - `at(array, index)` - - Get an element by its index. Negative indices count backwards from the last item. - - ## Examples - ```rescript - ["a", "b", "c"]->Array.at(0) // Some("a") - ["a", "b", "c"]->Array.at(2) // Some("c") - ["a", "b", "c"]->Array.at(3) // None - ["a", "b", "c"]->Array.at(-1) // Some("c") - ["a", "b", "c"]->Array.at(-3) // Some("a") - ["a", "b", "c"]->Array.at(-4) // None - ``` +`at(array, index)` + +Get an element by its index. Negative indices count backwards from the last item. + +## Examples + +```rescript +["a", "b", "c"]->Array.at(0)->assert_eq(Some("a")) +["a", "b", "c"]->Array.at(2)->assert_eq(Some("c")) +["a", "b", "c"]->Array.at(3)->assert_eq(None) +["a", "b", "c"]->Array.at(-1)->assert_eq(Some("c")) +["a", "b", "c"]->Array.at(-3)->assert_eq(Some("a")) +["a", "b", "c"]->Array.at(-4)->assert_eq(None) +``` */ @send external at: (array<'a>, int) => option<'a> = "at" @@ -1060,11 +1224,15 @@ external at: (array<'a>, int) => option<'a> = "at" Returns `None` if the array is empty. ## Examples + ```rescript -let array = ["Hello", "Hi", "Good bye"] +["Hello", "Hi", "Good bye"] +->Array.last +->assert_eq(Some("Good bye")) -array->Array.last == Some("Good bye") // true -[]->Array.last == None // true +[] +->Array.last +->assert_eq(None) ``` */ let last: array<'a> => option<'a> diff --git a/test/ArrayTests.mjs b/test/ArrayTests.mjs deleted file mode 100644 index fbce97e8..00000000 --- a/test/ArrayTests.mjs +++ /dev/null @@ -1,477 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Test from "./Test.mjs"; -import * as Caml_obj from "rescript/lib/es6/caml_obj.js"; -import * as Core__List from "../src/Core__List.mjs"; -import * as Core__Array from "../src/Core__Array.mjs"; - -var eq = Caml_obj.equal; - -Test.run([ - [ - "ArrayTests.res", - 5, - 20, - 26 - ], - "make" - ], Core__Array.make(6, 7), eq, [ - 7, - 7, - 7, - 7, - 7, - 7 - ]); - -Test.run([ - [ - "ArrayTests.res", - 7, - 20, - 42 - ], - "getUnsafe - existing" - ], 1, eq, 1); - -Test.run([ - [ - "ArrayTests.res", - 8, - 20, - 41 - ], - "getUnsafe - missing" - ], [ - 0, - 1, - 2 - ][10], eq, undefined); - -Test.run([ - [ - "ArrayTests.res", - 11, - 13, - 30 - ], - "fromInitializer" - ], Core__Array.fromInitializer(7, (function (i) { - return i + 3 | 0; - })), eq, [ - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ]); - -Test.run([ - [ - "ArrayTests.res", - 17, - 20, - 28 - ], - "reduce" - ], Core__Array.reduce([ - 1, - 2, - 3 - ], /* [] */0, Core__List.add), eq, { - hd: 3, - tl: { - hd: 2, - tl: { - hd: 1, - tl: /* [] */0 - } - } - }); - -Test.run([ - [ - "ArrayTests.res", - 18, - 20, - 36 - ], - "reduce - empty" - ], Core__Array.reduce([], /* [] */0, Core__List.add), eq, /* [] */0); - -Test.run([ - [ - "ArrayTests.res", - 21, - 13, - 30 - ], - "reduceWithIndex" - ], Core__Array.reduceWithIndex([ - 1, - 2, - 3 - ], /* [] */0, (function (acc, v, i) { - return { - hd: v + i | 0, - tl: acc - }; - })), eq, { - hd: 5, - tl: { - hd: 3, - tl: { - hd: 1, - tl: /* [] */0 - } - } - }); - -Test.run([ - [ - "ArrayTests.res", - 27, - 13, - 38 - ], - "reduceWithIndex - empty" - ], Core__Array.reduceWithIndex([], /* [] */0, (function (acc, v, i) { - return { - hd: v + i | 0, - tl: acc - }; - })), eq, /* [] */0); - -Test.run([ - [ - "ArrayTests.res", - 34, - 13, - 26 - ], - "reduceRight" - ], Core__Array.reduceRight([ - 1, - 2, - 3 - ], /* [] */0, Core__List.add), eq, { - hd: 1, - tl: { - hd: 2, - tl: { - hd: 3, - tl: /* [] */0 - } - } - }); - -Test.run([ - [ - "ArrayTests.res", - 39, - 20, - 41 - ], - "reduceRight - empty" - ], Core__Array.reduceRight([], /* [] */0, Core__List.add), eq, /* [] */0); - -Test.run([ - [ - "ArrayTests.res", - 42, - 13, - 35 - ], - "reduceEightWithIndex" - ], Core__Array.reduceRightWithIndex([ - 1, - 2, - 3 - ], /* [] */0, (function (acc, v, i) { - return { - hd: v + i | 0, - tl: acc - }; - })), eq, { - hd: 1, - tl: { - hd: 3, - tl: { - hd: 5, - tl: /* [] */0 - } - } - }); - -Test.run([ - [ - "ArrayTests.res", - 48, - 13, - 38 - ], - "reduceWithIndex - empty" - ], Core__Array.reduceRightWithIndex([], /* [] */0, (function (acc, v, i) { - return { - hd: v + i | 0, - tl: acc - }; - })), eq, /* [] */0); - -Test.run([ - [ - "ArrayTests.res", - 54, - 20, - 41 - ], - "toShuffled - length" - ], Core__Array.toShuffled([ - 1, - 2, - 3 - ]).length, eq, 3); - -var arr = [ - 1, - 2, - 3 -]; - -Test.run([ - [ - "ArrayTests.res", - 57, - 13, - 31 - ], - "shuffle - length" - ], (Core__Array.shuffle(arr), arr.length), eq, 3); - -Test.run([ - [ - "ArrayTests.res", - 68, - 13, - 24 - ], - "filterMap" - ], Core__Array.filterMap([ - 1, - 2, - 3, - 4, - 5, - 6 - ], (function (n) { - if (n % 2 === 0) { - return Math.imul(n, n); - } - - })), eq, [ - 4, - 16, - 36 - ]); - -Test.run([ - [ - "ArrayTests.res", - 73, - 20, - 42 - ], - "filterMap - no match" - ], Core__Array.filterMap([ - 1, - 2, - 3, - 4, - 5, - 6 - ], (function (param) { - - })), eq, []); - -Test.run([ - [ - "ArrayTests.res", - 75, - 13, - 32 - ], - "filterMap - empty" - ], Core__Array.filterMap([], (function (n) { - if (n % 2 === 0) { - return Math.imul(n, n); - } - - })), eq, []); - -Test.run([ - [ - "ArrayTests.res", - 81, - 20, - 30 - ], - "keepSome" - ], Core__Array.keepSome([ - 1, - undefined, - 3 - ]), eq, [ - 1, - 3 - ]); - -Test.run([ - [ - "ArrayTests.res", - 83, - 13, - 34 - ], - "keepSome - all Some" - ], Core__Array.keepSome([ - 1, - 2, - 3 - ]), eq, [ - 1, - 2, - 3 - ]); - -Test.run([ - [ - "ArrayTests.res", - 88, - 20, - 41 - ], - "keepSome - all None" - ], Core__Array.keepSome([ - undefined, - undefined, - undefined - ]), eq, []); - -Test.run([ - [ - "ArrayTests.res", - 89, - 20, - 38 - ], - "keepSome - empty" - ], Core__Array.keepSome([]), eq, []); - -Test.run([ - [ - "ArrayTests.res", - 92, - 13, - 22 - ], - "findMap" - ], Core__Array.findMap([ - 1, - 2, - 3, - 4, - 5, - 6 - ], (function (n) { - if (n % 2 === 0) { - return n - 8 | 0; - } - - })), eq, -6); - -Test.run([ - [ - "ArrayTests.res", - 97, - 20, - 40 - ], - "findMap - no match" - ], Core__Array.findMap([ - 1, - 2, - 3, - 4, - 5, - 6 - ], (function (param) { - - })), eq, undefined); - -Test.run([ - [ - "ArrayTests.res", - 99, - 13, - 30 - ], - "findMap - empty" - ], Core__Array.findMap([], (function (n) { - if (n % 2 === 0) { - return Math.imul(n, n); - } - - })), eq, undefined); - -Test.run([ - [ - "ArrayTests.res", - 106, - 13, - 27 - ], - "fromIterator" - ], Array.from(new Map([ - [ - 1, - 3 - ], - [ - 2, - 4 - ] - ]).values()), eq, [ - 3, - 4 - ]); - -Test.run([ - [ - "ArrayTests.res", - 112, - 20, - 39 - ], - "last - with items" - ], Core__Array.last([ - 1, - 2, - 3 - ]), eq, 3); - -Test.run([ - [ - "ArrayTests.res", - 113, - 20, - 34 - ], - "last - empty" - ], Core__Array.last([]), eq, undefined); - -export { - eq , -} -/* Not a pure module */ diff --git a/test/ArrayTests.res b/test/ArrayTests.res deleted file mode 100644 index b6fdec2b..00000000 --- a/test/ArrayTests.res +++ /dev/null @@ -1,113 +0,0 @@ -open RescriptCore - -let eq = (a, b) => a == b - -Test.run(__POS_OF__("make"), Array.make(~length=6, 7), eq, [7, 7, 7, 7, 7, 7]) - -Test.run(__POS_OF__("getUnsafe - existing"), [0, 1, 2]->Array.getUnsafe(1), eq, 1) -Test.run(__POS_OF__("getUnsafe - missing"), [0, 1, 2]->Array.getUnsafe(10), eq, %raw(`undefined`)) - -Test.run( - __POS_OF__("fromInitializer"), - Array.fromInitializer(~length=7, i => i + 3), - eq, - [3, 4, 5, 6, 7, 8, 9], -) - -Test.run(__POS_OF__("reduce"), Array.reduce([1, 2, 3], list{}, List.add), eq, list{3, 2, 1}) -Test.run(__POS_OF__("reduce - empty"), Array.reduce([], list{}, List.add), eq, list{}) - -Test.run( - __POS_OF__("reduceWithIndex"), - Array.reduceWithIndex([1, 2, 3], list{}, (acc, v, i) => list{v + i, ...acc}), - eq, - list{5, 3, 1}, -) -Test.run( - __POS_OF__("reduceWithIndex - empty"), - Array.reduceWithIndex([], list{}, (acc, v, i) => list{v + i, ...acc}), - eq, - list{}, -) - -Test.run( - __POS_OF__("reduceRight"), - Array.reduceRight([1, 2, 3], list{}, List.add), - eq, - list{1, 2, 3}, -) -Test.run(__POS_OF__("reduceRight - empty"), Array.reduceRight([], list{}, List.add), eq, list{}) - -Test.run( - __POS_OF__("reduceEightWithIndex"), - Array.reduceRightWithIndex([1, 2, 3], list{}, (acc, v, i) => list{v + i, ...acc}), - eq, - list{1, 3, 5}, -) -Test.run( - __POS_OF__("reduceWithIndex - empty"), - Array.reduceRightWithIndex([], list{}, (acc, v, i) => list{v + i, ...acc}), - eq, - list{}, -) - -Test.run(__POS_OF__("toShuffled - length"), Array.toShuffled([1, 2, 3])->Array.length, eq, 3) - -Test.run( - __POS_OF__("shuffle - length"), - { - let arr = [1, 2, 3] - Array.shuffle(arr) - arr->Array.length - }, - eq, - 3, -) - -Test.run( - __POS_OF__("filterMap"), - Array.filterMap([1, 2, 3, 4, 5, 6], n => mod(n, 2) == 0 ? Some(n * n) : None), - eq, - [4, 16, 36], -) -Test.run(__POS_OF__("filterMap - no match"), Array.filterMap([1, 2, 3, 4, 5, 6], _ => None), eq, []) -Test.run( - __POS_OF__("filterMap - empty"), - Array.filterMap([], n => mod(n, 2) == 0 ? Some(n * n) : None), - eq, - [], -) - -Test.run(__POS_OF__("keepSome"), Array.keepSome([Some(1), None, Some(3)]), eq, [1, 3]) -Test.run( - __POS_OF__("keepSome - all Some"), - Array.keepSome([Some(1), Some(2), Some(3)]), - eq, - [1, 2, 3], -) -Test.run(__POS_OF__("keepSome - all None"), Array.keepSome([None, None, None]), eq, []) -Test.run(__POS_OF__("keepSome - empty"), Array.keepSome([]), eq, []) - -Test.run( - __POS_OF__("findMap"), - Array.findMap([1, 2, 3, 4, 5, 6], n => mod(n, 2) == 0 ? Some(n - 8) : None), - eq, - Some(-6), -) -Test.run(__POS_OF__("findMap - no match"), Array.findMap([1, 2, 3, 4, 5, 6], _ => None), eq, None) -Test.run( - __POS_OF__("findMap - empty"), - Array.findMap([], n => mod(n, 2) == 0 ? Some(n * n) : None), - eq, - None, -) - -Test.run( - __POS_OF__("fromIterator"), - Array.fromIterator(Map.fromArray([(1, 3), (2, 4)])->Map.values), - eq, - [3, 4], -) - -Test.run(__POS_OF__("last - with items"), [1, 2, 3]->Array.last, eq, Some(3)) -Test.run(__POS_OF__("last - empty"), []->Array.last, eq, None) diff --git a/test/TestSuite.mjs b/test/TestSuite.mjs index e0ee5b0b..a2bac25e 100644 --- a/test/TestSuite.mjs +++ b/test/TestSuite.mjs @@ -4,7 +4,6 @@ import * as IntTests from "./IntTests.mjs"; import * as DictTests from "./DictTests.mjs"; import * as JsonTests from "./JsonTests.mjs"; import * as TestTests from "./TestTests.mjs"; -import * as ArrayTests from "./ArrayTests.mjs"; import * as ErrorTests from "./ErrorTests.mjs"; import * as FloatTests from "./FloatTests.mjs"; import * as ObjectTests from "./ObjectTests.mjs"; diff --git a/test/TestSuite.res b/test/TestSuite.res index 4b3496ea..41093f85 100644 --- a/test/TestSuite.res +++ b/test/TestSuite.res @@ -1,7 +1,6 @@ include TestTests include PromiseTest include ErrorTests -include ArrayTests include IntTests include ObjectTests include ResultTests From ae82cfc3da48e2b0d5c6009418e1bd00f346cf22 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 22 Apr 2024 13:46:57 -0300 Subject: [PATCH 08/22] fix Array tests --- src/Core__Array.resi | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Core__Array.resi b/src/Core__Array.resi index 57c1cbe7..3b807998 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -98,9 +98,8 @@ See [`Array.fill`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ```rescript let myArray = [1, 2, 3, 4] -myArray -->Array.fillAll(9) -->assert_eq([9, 9, 9, 9]) +myArray->Array.fillAll(9) +myArray->assert_eq([9, 9, 9, 9]) ``` */ @send @@ -117,10 +116,8 @@ See [`Array.fill`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ```rescript let myArray = [1, 2, 3, 4] - -myArray -->Array.fillToEnd(9, ~start=1) -->assert_eq([1, 9, 9, 9]) +myArray->Array.fillToEnd(9, ~start=1) +myArray->assert_eq([1, 9, 9, 9]) ``` */ @send @@ -140,7 +137,8 @@ let myArray = [1, 2, 3, 4] myArray ->Array.fill(9, ~start=1, ~end=2) -->assert_eq([1, 9, 9, 4]) + +myArray->assert_eq([1, 9, 9, 4]) ``` */ @send @@ -221,7 +219,7 @@ See [`Array.reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Re let someArray = ["hi", "hello"] someArray->Array.reverse -someArray->assert_eq(["hello", "h1"]) +someArray->assert_eq(["hello", "hi"]) ``` */ @send @@ -279,9 +277,9 @@ See [`Array.sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ## Examples ```rescript -[3, 2, 1] -->Array.sort((a, b) => float(a - b)) -->assert_eq([1, 2, 3]) +let array = [3, 2, 1] +array->Array.sort((a, b) => float(a - b)) +array->assert_eq([1, 2, 3]) ``` */ @send @@ -587,7 +585,7 @@ See [`Array.every`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe let array = [1, 2, 3, 4] array -->Array.every(num => num > 4) +->Array.every(num => num <= 4) ->assert_eq(true) array @@ -609,7 +607,7 @@ See [`Array.every`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe let array = [1, 2, 3, 4] array -->Array.everyWithIndex((num, index) => index < 2 && num <= 2) +->Array.everyWithIndex((num, index) => index < 5 && num <= 4) ->assert_eq(true) array @@ -954,7 +952,7 @@ Beware this will *mutate* the array. let array = ["Hello", "Hi", "Good bye"] array->Array.set(1, "Hello") -array[1]->assert_eq("Hello") +array[1]->assert_eq(Some("Hello")) ``` */ @set_index @@ -1001,7 +999,7 @@ Beware this will *mutate* the array, and is *unsafe*. let array = ["Hello", "Hi", "Good bye"] array->Array.setUnsafe(1, "Hello") -assert_eq(array[1], "Hello") +assert_eq(array[1], Some("Hello")) ``` */ external setUnsafe: (array<'a>, int, 'a) => unit = "%array_unsafe_set" @@ -1038,7 +1036,7 @@ See [`Array.toReversed`](https://developer.mozilla.org/en-US/docs/Web/JavaScript let someArray = ["hi", "hello"] let reversed = someArray->Array.toReversed -reversed->assert_eq(["hello", "h1"]) +reversed->assert_eq(["hello", "hi"]) someArray->assert_eq(["h1", "hello"]) // Original unchanged ``` */ @@ -1122,8 +1120,10 @@ let array = ["Hello", "Hi", "Good bye"] array->Array.shuffle Console.log(array) -[1, 2, 3] -->Array.shuffle +let array2 = [1, 2, 3] +array2->Array.shuffle + +array2 ->Array.length ->assert_eq(3) ``` From 7db33dff27cade11e0224c33cdfa9a4c01bcbf0f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 22 Apr 2024 14:32:01 -0300 Subject: [PATCH 09/22] fix Array.fill test --- src/Core__Array.resi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Core__Array.resi b/src/Core__Array.resi index 3b807998..9387f35b 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -135,8 +135,7 @@ See [`Array.fill`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ```rescript let myArray = [1, 2, 3, 4] -myArray -->Array.fill(9, ~start=1, ~end=2) +myArray->Array.fill(9, ~start=1, ~end=3) myArray->assert_eq([1, 9, 9, 4]) ``` From 464efbafc88b6cb7c74dae49828c63e5ab9cfe00 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 19:02:57 -0300 Subject: [PATCH 10/22] more fixes --- src/Core__AsyncIterator.resi | 49 ++++++++---- src/Core__Dict.resi | 21 ++++- src/Core__Error.resi | 6 +- src/Core__Iterator.resi | 39 +++++++--- src/Core__JSON.resi | 144 ++++++++++++++++++++--------------- src/Core__List.resi | 23 ++++-- src/Core__Map.resi | 20 ++++- src/Core__Null.resi | 5 +- src/Core__Nullable.resi | 5 +- src/Core__Object.res | 20 ++++- src/Core__Option.resi | 12 ++- src/Core__Promise.resi | 11 ++- src/Core__Set.resi | 15 +++- src/Core__String.resi | 10 +-- 14 files changed, 259 insertions(+), 121 deletions(-) diff --git a/src/Core__AsyncIterator.resi b/src/Core__AsyncIterator.resi index 5644838b..c8778a9a 100644 --- a/src/Core__AsyncIterator.resi +++ b/src/Core__AsyncIterator.resi @@ -27,17 +27,20 @@ Returns the next value of the iterator, if any. See [async iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols) on MDN. ## Examples -- A simple example, getting the next value: -```rescript -@val external asyncIterator: AsyncIterator.t = "someAsyncIterator" -let {AsyncIterator.done, value} = await asyncIterator->AsyncIterator.next -``` -- Complete example, including looping over all values: ```rescript -// Let's pretend we get an async iterator returning ints from somewhere. -@val external asyncIterator: AsyncIterator.t = "someAsyncIterator" +// A simple example, getting the next value: +let asyncIterator: AsyncIterator.t<(string, string)> = %raw(` + (() => { + var map1 = new Map(); + + map1.set('first', '1'); + map1.set('second', '2'); + var iterator1 = map1[Symbol.iterator](); + return iterator1; + })() +`) let processMyAsyncIterator = async () => { // ReScript doesn't have `for ... of` loops, but it's easy to mimic using a while loop. @@ -50,10 +53,15 @@ let processMyAsyncIterator = async () => { // Exit the while loop if the iterator says it's done break := done - // This will log the (int) value of the current async iteration, if a value was returned. - Console.log(value) + if done { + value + ->Option.isNone + ->assert_eq(true) + } } } + +processMyAsyncIterator()->ignore ``` */ @send @@ -65,16 +73,27 @@ external next: t<'a> => promise> = "next" See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN. ## Examples + ```rescript // Let's pretend we get an async iterator returning ints from somewhere. -@val external asyncIterator: AsyncIterator.t = "someAsyncIterator" +let asyncIterator: AsyncIterator.t<(string, string)> = %raw(` + (() => { + var map1 = new Map(); + + map1.set('first', '1'); + map1.set('second', '2'); + + var iterator1 = map1[Symbol.iterator](); + return iterator1; + })() +`) -await asyncIterator->AsyncIterator.forEach(value => - switch value { - | Some(value) if value > 10 => Console.log("More than 10!") +await asyncIterator->AsyncIterator.forEach(v => { + switch v { + | Some(("second", value)) => assert_eq(value, "2") | _ => () } -) +}) ``` */ let forEach: (t<'a>, option<'a> => unit) => promise diff --git a/src/Core__Dict.resi b/src/Core__Dict.resi index db26ca44..ac1032c7 100644 --- a/src/Core__Dict.resi +++ b/src/Core__Dict.resi @@ -95,11 +95,24 @@ external fromArray: array<(string, 'a)> => t<'a> = "Object.fromEntries" `fromIterator(entries)` creates a new dictionary from the provided iterator of key/value pairs. ## Examples -```rescript -// Pretend we have an iterator of the correct shape -@val external someIterator: Iterator.t<(string, int)> = "someIterator" -let dict = Dict.fromIterator(someIterator) // Dict.t +```rescript +let iterator: Iterator.t<(string, int)> = %raw(` + (() => { + var map1 = new Map(); + + map1.set('first', 1); + map1.set('second', 2); + + var iterator1 = map1[Symbol.iterator](); + return iterator1; + })() +`) + +iterator +->Dict.fromIterator +->Dict.valuesToArray +->assert_eq([1, 2]) ``` */ @val diff --git a/src/Core__Error.resi b/src/Core__Error.resi index 38b6a973..cbaeef9c 100644 --- a/src/Core__Error.resi +++ b/src/Core__Error.resi @@ -165,8 +165,12 @@ handled. Compared to a ReScript exception this will give a better stack trace an debugging experience. ## Examples + ```rescript -Error.panic("Uh oh. This was unexpected!") +switch Error.panic("Uh oh. This was unexpected!") { +| exception _ => assert(true) +| _ => assert(false) +} ``` */ let panic: string => 'a diff --git a/src/Core__Iterator.resi b/src/Core__Iterator.resi index 300d4fca..8c871b13 100644 --- a/src/Core__Iterator.resi +++ b/src/Core__Iterator.resi @@ -29,11 +29,18 @@ Returns the next value of the iterator, if any. See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN. ## Examples -```rescript -@val external someIterator: Iterator.t = "someIterator" -// Pulls out the next value of the iterator -let {Iterator.done, value} = someIterator->Iterator.next +```rescript +let iterator: Iterator.t = %raw(` + (() => { + var array1 = ['a']; + var iterator1 = array1[Symbol.iterator](); + return iterator1 + })() +`) + +(iterator->Iterator.next).done->assert_eq(false) +(iterator->Iterator.next).done->assert_eq(true) ``` */ @send @@ -87,15 +94,25 @@ external toArrayWithMapper: (t<'a>, 'a => 'b) => array<'b> = "Array.from" See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN. ## Examples -```rescript -@val external someIterator: Iterator.t = "someIterator" -someIterator->Iterator.forEach(value => - switch value { - | Some(value) if value > 10 => Console.log("More than 10!") - | _ => () +```rescript +let iterator: Iterator.t = %raw(` + (() => { + var array1 = ['a', 'b', 'c']; + var iterator1 = array1[Symbol.iterator](); + return iterator1 + })() +`) + +iterator->Iterator.forEach(v => { + switch v { + | Some("a" | "b" | "c") => assert(true) + | other => + other + ->Option.isNone + ->assert_eq(true) } -) +}) ``` */ let forEach: (t<'a>, option<'a> => unit) => unit diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 9b5f714b..db71380d 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -297,7 +297,7 @@ JSON.stringifyWithFilterAndIndent(json, ["foo", "someNumber"], 2) external stringifyWithFilterAndIndent: (t, array, int) => string = "JSON.stringify" /** -`stringifyAny(any, ~replacer=?, ~space=?)` +`stringifyAny(any, ~replacer=?, ~space=?)` Converts any type to a JSON string. The replacer describes how the value should be transformed. It is a function which receives a key and a value. @@ -306,6 +306,7 @@ If the value contains circular references or `BigInt`s, the function will throw If you want to stringify a JSON object, use `JSON.stringify` instead. ## Examples + ```rescript let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), @@ -313,18 +314,21 @@ let dict = Dict.fromArray([ ("someNumber", JSON.Encode.int(42)), ]) -JSON.stringifyAny(dict) -// {"foo":"bar","hello":"world","someNumber":42} +dict +->JSON.stringifyAny +->assert_eq(`{"foo":"bar","hello":"world","someNumber":42}`) -JSON.stringifyAny(dict, ~space=2) -// { -// "foo": "bar", -// "hello": "world", -// "someNumber": 42 -// } +dict +->JSON.stringifyAny(~space=2) +->assert_eq(`{ + "foo": "bar", + "hello": "world", + "someNumber": 42 +}`) -JSON.stringifyAny(dict, ~replacer=Keys(["foo", "someNumber"])) -// {"foo":"bar","someNumber":42} +dict +->JSON.stringifyAny(~replacer=Keys(["foo", "someNumber"])) +->assert_eq(`{"foo":"bar","someNumber":42}`) let replacer = JSON.Replacer((_, value) => { let decodedValue = value->JSON.Decode.string @@ -335,17 +339,19 @@ let replacer = JSON.Replacer((_, value) => { } }) -JSON.stringifyAny(dict, ~replacer) -// {"foo":"BAR","hello":"WORLD","someNumber":42} +dict +->JSON.stringifyAny(~replacer) +->assert_eq(`{"foo":"BAR","hello":"WORLD","someNumber":42}`) -JSON.stringifyAny(() => "hello world") -// None +JSON.stringifyAny(() => "hello world")->assert_eq(None) -BigInt.fromInt(0)->JSON.stringifyAny -// exception +switch BigInt.fromInt(0)->JSON.stringifyAny { +| exception _ => assert(true) +| _ => assert(false) +} ``` -## Exceptions +## Exceptions - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. @@ -356,7 +362,7 @@ external stringifyAny: ('a, ~replacer: replacer=?, ~space: int=?) => optionJSON.stringifyAnyWithIndent(2) +->assert_eq(`{ + "foo": "bar", + "hello": "world", + "someNumber": 42 +}`) -JSON.stringifyAny(() => "hello world") -// None +JSON.stringifyAny(() => "hello world")->assert_eq(None) -BigInt.fromInt(0)->JSON.stringifyAny -// exception +switch BigInt.fromInt(0)->JSON.stringifyAny { +| exception _ => assert(true) +| _ => assert(false) +} ``` -## Exceptions +## Exceptions - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. @@ -395,7 +404,7 @@ BigInt.fromInt(0)->JSON.stringifyAny @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" -/** +/** `stringifyAnyWithReplacer(json, replacer)` Converts any type to a JSON string. @@ -405,6 +414,7 @@ If the value contains circular references or `BigInt`s, the function will throw If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. ## Examples + ```rescript let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), @@ -421,17 +431,20 @@ let replacer = (_, value) => { } } -JSON.stringifyAnyWithReplacer(dict, replacer) -// {"foo":"BAR","hello":"WORLD","someNumber":42} +dict +->JSON.stringifyAnyWithReplacer(replacer) +->Option.getUnsafe +->assert_eq(`{"foo":"BAR","hello":"WORLD","someNumber":42}`) -JSON.stringifyAny(() => "hello world") -// None +JSON.stringifyAny(() => "hello world")->assert_eq(None) -BigInt.fromInt(0)->JSON.stringifyAny -// exception +switch BigInt.fromInt(0)->JSON.stringifyAny { +| exception _ => assert(true) +| _ => assert(false) +} ``` -## Exceptions +## Exceptions - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. @@ -441,8 +454,8 @@ BigInt.fromInt(0)->JSON.stringifyAny @val external stringifyAnyWithReplacer: ('a, (string, t) => t) => option = "JSON.stringify" -/** -`stringifyAnyWithReplacerAndIndent(json, replacer, indentation)` +/** +`stringifyAnyWithReplacerAndIndent(json, replacer, indentation)` Converts any type to a JSON string. The output will be indented. The replacer describes how the value should be transformed. It is a function which receives a key and a value. @@ -451,6 +464,7 @@ If the value contains circular references or `BigInt`s, the function will throw If you want to stringify a JSON object, use `JSON.stringifyWithReplacerAndIndent` instead. ## Examples + ```rescript let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), @@ -467,21 +481,24 @@ let replacer = (_, value) => { } } -JSON.stringifyAnyWithReplacerAndIndent(dict, replacer, 2) -// { -// "foo": "BAR", -// "hello": "WORLD", -// "someNumber": 42 -// } +dict +->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) +->Option.getUnsafe +->assert_eq(`{ + "foo": "BAR", + "hello": "WORLD", + "someNumber": 42 +}`) -JSON.stringifyAny(() => "hello world") -// None +JSON.stringifyAny(() => "hello world")->assert_eq(None) -BigInt.fromInt(0)->JSON.stringifyAny -// exception +switch BigInt.fromInt(0)->JSON.stringifyAny { +| exception _ => assert(true) +| _ => assert(false) +} ``` -## Exceptions +## Exceptions - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. @@ -530,7 +547,7 @@ BigInt.fromInt(0)->JSON.stringifyAny external stringifyAnyWithFilter: ('a, array) => string = "JSON.stringify" /** -`stringifyAnyWithFilterAndIndent(json, filter, indentation)` +`stringifyAnyWithFilterAndIndent(json, filter, indentation)` Converts any type to a JSON string. The output will be indented. The filter is an array of keys, which should be included in the output. @@ -539,6 +556,7 @@ If the value contains circular references or `BigInt`s, the function will throw If you want to stringify a JSON object, use `JSON.stringifyWithFilterAndIndent` instead. ## Examples + ```rescript let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), @@ -546,20 +564,22 @@ let dict = Dict.fromArray([ ("someNumber", JSON.Encode.int(42)), ]) -JSON.stringifyAnyWithFilterAndIndent(dict, ["foo", "someNumber"], 2) -// { -// "foo": "bar", -// "someNumber": 42 -// } +dict +->JSON.stringifyAnyWithFilterAndIndent(["foo", "someNumber"], 2) +->assert_eq(`{ + "foo": "bar", + "someNumber": 42 +}`) -JSON.stringifyAny(() => "hello world") -// None +JSON.stringifyAny(() => "hello world")->assert_eq(None) -BigInt.fromInt(0)->JSON.stringifyAny -// exception +switch BigInt.fromInt(0)->JSON.stringifyAny { +| exception _ => assert(true) +| _ => assert(false) +} ``` -## Exceptions +## Exceptions - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. diff --git a/src/Core__List.resi b/src/Core__List.resi index 610a2820..1cf88c5f 100644 --- a/src/Core__List.resi +++ b/src/Core__List.resi @@ -75,9 +75,12 @@ let head: t<'a> => option<'a> ## Examples ```rescript -List.headExn(list{1, 2, 3}) // 1 +List.headExn(list{1, 2, 3})->assert_eq(1) -List.headExn(list{}) // Raises an Error +switch List.headExn(list{}) { +| exception Not_found => assert(true) +| _ => assert(false) +} ``` ## Exceptions @@ -107,9 +110,12 @@ let tail: t<'a> => option> ## Examples ```rescript -List.tailExn(list{1, 2, 3}) // list{2, 3} +List.tailExn(list{1, 2, 3})->assert_eq(list{2, 3}) -List.tailExn(list{}) // Raises an Error +switch List.tailExn(list{}) { +| exception Not_found => assert(true) +| _ => assert(false) +} ``` ## Exceptions @@ -155,9 +161,14 @@ let get: (t<'a>, int) => option<'a> ```rescript let abc = list{"A", "B", "C"} -abc->List.getExn(1) // "B" +abc +->List.getExn(1) +->assert_eq("B") -abc->List.getExn(4) // Raises an Error +switch abc->List.getExn(4) { +| exception Not_found => assert(true) +| _ => assert(false) +} ``` ## Exceptions diff --git a/src/Core__Map.resi b/src/Core__Map.resi index 1f29caa5..4429813f 100644 --- a/src/Core__Map.resi +++ b/src/Core__Map.resi @@ -56,11 +56,25 @@ external fromArray: array<('k, 'v)> => t<'k, 'v> = "Map" Turns an iterator in the shape of `('key, 'value)` into a `Map`. ## Examples + ```rescript // Let's pretend we have an interator in the correct shape -@val external someIterator: Iterator.t<(string, int)> = "someIterator" - -let map = Map.fromIterator(someIterator) // Map.t +let iterator: Iterator.t<(string, string)> = %raw(` + (() => { + var map1 = new Map(); + + map1.set('first', '1'); + map1.set('second', '2'); + + var iterator1 = map1[Symbol.iterator](); + return iterator1; + })() +`) + +iterator +->Map.fromIterator +->Map.size +->assert_eq(2) ``` */ @new diff --git a/src/Core__Null.resi b/src/Core__Null.resi index af2cd4ee..5b779972 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -122,7 +122,10 @@ let getExn: t<'a> => 'a ```rescript Null.getUnsafe(Null.make(3)) == 3 -Null.getUnsafe(Null.null) // Raises an error +switch Null.getUnsafe(Null.null) { +| exception _ => assert(true) +| _ => assert(false) +} ``` ## Important diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index c33f7c92..cebafeaf 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -133,7 +133,10 @@ let getExn: t<'a> => 'a ```rescript Nullable.getUnsafe(Nullable.make(3)) == 3 -Nullable.getUnsafe(Nullable.null) // Raises an error +switch Nullable.getUnsafe(Nullable.null) { +| exception _ => assert(true) +| _ => assert(false) +} ``` ## Important diff --git a/src/Core__Object.res b/src/Core__Object.res index 696f6760..7dc45809 100644 --- a/src/Core__Object.res +++ b/src/Core__Object.res @@ -186,7 +186,10 @@ See [ECMAScript Language Specification](https://tc39.es/ecma262/multipage/fundam let point = {"x": 1, "y": 2} point->Object.set("x", -7) // succeeds point->Object.seal->ignore -point->Object.set("z", 9) // fails +switch point->Object.set("z", 9) { +| exception _ => assert(true) +| _ => assert(false) +} point->Object.set("x", 13) // succeeds ``` */ @@ -204,7 +207,11 @@ See [ECMAScript Language Specification](https://tc39.es/ecma262/multipage/fundam let obj = {"a": 1} obj->Object.set("b", 2) // succeeds obj->Object.preventExtensions->ignore -obj->Object.set("c", 3) // fails + +switch obj->Object.set("c", 3) { +| exception _ => assert(true) +| _ => assert(false) +} ``` */ @val @@ -219,11 +226,16 @@ See [ECMAScript Language Specification](https://tc39.es/ecma262/multipage/fundam ## Examples - ```rescript +```rescript let obj = {"a": 1} obj->Object.set("a", 2) // succeeds + obj->Object.freeze->ignore -obj->Object.set("a", 3) // fails + +switch obj->Object.set("a", 3) { +| exception _ => assert(true) +| _ => assert(false) +} ``` */ @val diff --git a/src/Core__Option.resi b/src/Core__Option.resi index 6f920896..31521345 100644 --- a/src/Core__Option.resi +++ b/src/Core__Option.resi @@ -69,9 +69,15 @@ let forEach: (option<'a>, 'a => unit) => unit `getExn(opt, ~message=?)` returns `value` if `opt` is `Some(value)`, otherwise raises an exception with the message provided, or a generic message if no message was provided. ```rescript -Option.getExn(Some(3)) // 3 -Option.getExn(None) /* Raises an Error */ -Option.getExn(None, ~message="was None!") /* Raises an Error with the message "was None!" */ +Option.getExn(Some(3))->assert_eq(3) +switch Option.getExn(None) { +| exception _ => assert(true) +| _ => assert(false) +} +switch Option.getExn(None, ~message="was None!") { +| exception _ => assert(true) // Raises an Error with the message "was None!" +| _ => assert(false) +} ``` ## Exceptions diff --git a/src/Core__Promise.resi b/src/Core__Promise.resi index 5468bf93..64e1cdb4 100644 --- a/src/Core__Promise.resi +++ b/src/Core__Promise.resi @@ -37,7 +37,16 @@ See [`Promise.reject`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R ```rescript exception TestError(string) -let p = Promise.reject(TestError("some rejected value")) +TestError("some rejected value") +->Promise.reject +->Promise.catch(v => { + switch v { + | TestError(msg) => assert_eq(msg, "some rejected value") + | _ => assert(false) + } + Promise.resolve() +}) +->ignore ``` */ @scope("Promise") diff --git a/src/Core__Set.resi b/src/Core__Set.resi index 297755d0..795f0a02 100644 --- a/src/Core__Set.resi +++ b/src/Core__Set.resi @@ -57,9 +57,18 @@ Turns an iterator into a `Set`. ## Examples ```rescript // Let's pretend we have an interator -@val external someIterator: Iterator.t = "someIterator" - -let set = Set.fromIterator(someIterator) // Set.t +let iterator: Iterator.t = %raw(` + (() => { + var array1 = ['a', 'b', 'c']; + var iterator1 = array1[Symbol.iterator](); + return iterator1 + })() +`) + +iterator +->Set.fromIterator +->Set.size +->assert_eq(3) ``` */ @new diff --git a/src/Core__String.resi b/src/Core__String.resi index 98b24971..39912ddd 100644 --- a/src/Core__String.resi +++ b/src/Core__String.resi @@ -436,13 +436,11 @@ See also [Unicode technical report #15](https://unicode.org/reports/tr15/) for d ## Examples ```rescript -let string1 = "\uFB00" -let string2 = "\u0066\u0066" -Console.log(string1 === string2) // false +let string1 = "\u00F1" +let string2 = "\u006E\u0303" -let normalizeString1 = String.normalize(string1) -let normalizeString2 = String.normalize(string2) -assert(normalizeString1 === normalizeString2) +assert(string1 != string2) // true +assert_eq(String.normalize(string1), String.normalize(string2)) ``` */ @send From 244400e15feb4f61228e393e19563aadb6a4ef0b Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 19:23:02 -0300 Subject: [PATCH 11/22] more fixes --- src/Core__AsyncIterator.resi | 15 ++++++++----- src/Core__JSON.resi | 43 ++++++++++++++++++++++++++---------- src/Core__Null.resi | 14 +++++++----- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/Core__AsyncIterator.resi b/src/Core__AsyncIterator.resi index c8778a9a..a710f8ee 100644 --- a/src/Core__AsyncIterator.resi +++ b/src/Core__AsyncIterator.resi @@ -88,12 +88,15 @@ let asyncIterator: AsyncIterator.t<(string, string)> = %raw(` })() `) -await asyncIterator->AsyncIterator.forEach(v => { - switch v { - | Some(("second", value)) => assert_eq(value, "2") - | _ => () - } -}) +let main = async () => + await asyncIterator->AsyncIterator.forEach(v => { + switch v { + | Some(("second", value)) => assert_eq(value, "2") + | _ => () + } + }) + +main()->ignore ``` */ let forEach: (t<'a>, option<'a> => unit) => promise diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index db71380d..5125606e 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -316,10 +316,12 @@ let dict = Dict.fromArray([ dict ->JSON.stringifyAny +->Option.getUnsafe ->assert_eq(`{"foo":"bar","hello":"world","someNumber":42}`) dict ->JSON.stringifyAny(~space=2) +->Option.getUnsafe ->assert_eq(`{ "foo": "bar", "hello": "world", @@ -328,6 +330,7 @@ dict dict ->JSON.stringifyAny(~replacer=Keys(["foo", "someNumber"])) +->Option.getUnsafe ->assert_eq(`{"foo":"bar","someNumber":42}`) let replacer = JSON.Replacer((_, value) => { @@ -341,9 +344,12 @@ let replacer = JSON.Replacer((_, value) => { dict ->JSON.stringifyAny(~replacer) +->Option.getUnsafe ->assert_eq(`{"foo":"BAR","hello":"WORLD","someNumber":42}`) -JSON.stringifyAny(() => "hello world")->assert_eq(None) +JSON.stringifyAny(() => "hello world") +->Option.isNone +->assert_eq(true) switch BigInt.fromInt(0)->JSON.stringifyAny { | exception _ => assert(true) @@ -380,13 +386,16 @@ let dict = Dict.fromArray([ dict ->JSON.stringifyAnyWithIndent(2) +->Option.getUnsafe ->assert_eq(`{ "foo": "bar", "hello": "world", "someNumber": 42 }`) -JSON.stringifyAny(() => "hello world")->assert_eq(None) +JSON.stringifyAny(() => "hello world") +->Option.isNone +->assert_eq(true) switch BigInt.fromInt(0)->JSON.stringifyAny { | exception _ => assert(true) @@ -436,7 +445,9 @@ dict ->Option.getUnsafe ->assert_eq(`{"foo":"BAR","hello":"WORLD","someNumber":42}`) -JSON.stringifyAny(() => "hello world")->assert_eq(None) +JSON.stringifyAny(() => "hello world") +->Option.isNone +->assert_eq(true) switch BigInt.fromInt(0)->JSON.stringifyAny { | exception _ => assert(true) @@ -490,7 +501,9 @@ dict "someNumber": 42 }`) -JSON.stringifyAny(() => "hello world")->assert_eq(None) +JSON.stringifyAny(() => "hello world") +->Option.isNone +->assert_eq(true) switch BigInt.fromInt(0)->JSON.stringifyAny { | exception _ => assert(true) @@ -509,8 +522,8 @@ switch BigInt.fromInt(0)->JSON.stringifyAny { external stringifyAnyWithReplacerAndIndent: ('a, (string, t) => t, int) => option = "JSON.stringify" -/** -`stringifyAnyWithFilter(json, filter)` +/** +`stringifyAnyWithFilter(json, filter)` Converts any type to a JSON string. The filter is an array of keys, which should be included in the output. @@ -526,14 +539,18 @@ let dict = Dict.fromArray([ ("someNumber", JSON.Encode.int(42)), ]) -JSON.stringifyAnyWithFilter(dict, ["foo", "someNumber"]) -// {"foo": "bar","someNumber": 42} +dict +->JSON.stringifyAnyWithFilter(["foo", "someNumber"]) +->assert_eq(`{"foo": "bar","someNumber": 42}`) JSON.stringifyAny(() => "hello world") -// None +->Option.isNone +->assert_eq(true) -BigInt.fromInt(0)->JSON.stringifyAny -// exception +switch BigInt.fromInt(0)->JSON.stringifyAny { +| exception _ => assert(true) +| _ => assert(false) +} ``` ## Exceptions @@ -571,7 +588,9 @@ dict "someNumber": 42 }`) -JSON.stringifyAny(() => "hello world")->assert_eq(None) +JSON.stringifyAny(() => "hello world") +->Option.isNone +->assert_eq(true) switch BigInt.fromInt(0)->JSON.stringifyAny { | exception _ => assert(true) diff --git a/src/Core__Null.resi b/src/Core__Null.resi index 5b779972..f9e4261a 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -106,7 +106,11 @@ let getWithDefault: (t<'a>, 'a) => 'a ```rescript Null.getExn(Null.make(3)) // 3 -Null.getExn(Null.null) /* Raises an Error */ + +switch Null.getExn(Null.null) { +| exception _ => assert(true) +| _ => assert(false) +} ``` ## Exceptions @@ -122,10 +126,10 @@ let getExn: t<'a> => 'a ```rescript Null.getUnsafe(Null.make(3)) == 3 -switch Null.getUnsafe(Null.null) { -| exception _ => assert(true) -| _ => assert(false) -} + +Null.getUnsafe(Null.null) +->Type.Classify.classify +->assert_eq(Null) ``` ## Important From eb7cc30d9379e6180594a721687f9b6ddafdd154 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 19:27:20 -0300 Subject: [PATCH 12/22] more fixes --- src/Core__JSON.resi | 3 ++- src/Core__Nullable.resi | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 5125606e..d7c6d849 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -532,6 +532,7 @@ If the value contains circular references or `BigInt`s, the function will throw If you want to stringify a JSON object, use `JSON.stringifyWithFilter` instead. ## Examples + ```rescript let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), @@ -541,7 +542,7 @@ let dict = Dict.fromArray([ dict ->JSON.stringifyAnyWithFilter(["foo", "someNumber"]) -->assert_eq(`{"foo": "bar","someNumber": 42}`) +->assert_eq(`{"foo":"bar","someNumber":42}`) JSON.stringifyAny(() => "hello world") ->Option.isNone diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index cebafeaf..8e4e26f3 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -117,7 +117,10 @@ let getWithDefault: (t<'a>, 'a) => 'a ```rescript Nullable.getExn(Nullable.make(3)) // 3 -Nullable.getExn(Nullable.null) /* Raises an Error */ +switch Nullable.getExn(Nullable.null) { +| exception _ => assert(true) +| _ => assert(false) +} ``` ## Exceptions @@ -133,10 +136,10 @@ let getExn: t<'a> => 'a ```rescript Nullable.getUnsafe(Nullable.make(3)) == 3 -switch Nullable.getUnsafe(Nullable.null) { -| exception _ => assert(true) -| _ => assert(false) -} + +Nullable.getUnsafe(Nullable.null) +->Type.Classify.classify +->assert_eq(Null) ``` ## Important From 4f13047e4b62d3615388b58df82498e126a42a5f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 19:34:27 -0300 Subject: [PATCH 13/22] fix timeouts --- src/Core__Global.resi | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Core__Global.resi b/src/Core__Global.resi index 03e05993..0818ae2e 100644 --- a/src/Core__Global.resi +++ b/src/Core__Global.resi @@ -16,10 +16,10 @@ See [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) ## Examples ```rescript -// Log to the console after 2 seconds (2000 milliseconds). +// Log to the console after 200 milliseconds. let timeoutId = setTimeout(() => { - Console.log("This prints in 2 seconds.") -}, 2000) + Console.log("This prints in 200 ms.") +}, 200) ``` */ @val @@ -34,10 +34,10 @@ See [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) ## Examples ```rescript -// Log to the console after 2 seconds (2000 milliseconds). +// Log to the console after 200 milliseconds. let timeoutId = setTimeoutFloat(() => { - Console.log("This prints in 2 seconds.") -}, 2000.) + Console.log("This prints in 200 ms.") +}, 200.) ``` */ @val @@ -75,10 +75,14 @@ See [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval ## Examples ```rescript -// Log to the console ever 2 seconds (2000 milliseconds). +// Log to the console ever 200 ms (200 milliseconds). let intervalId = setInterval(() => { - Console.log("This prints every 2 seconds.") -}, 2000) + Console.log("This prints every 200 ms.") +}, 200) + +let timeoutId = setTimeout(() => { + clearInterval(intervalId) +}, 500) ``` */ @val @@ -93,10 +97,15 @@ See [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval ## Examples ```rescript -// Log to the console ever 2 seconds (2000 milliseconds). +// Log to the console ever 2 seconds (200 milliseconds). let intervalId = setIntervalFloat(() => { - Console.log("This prints every 2 seconds.") -}, 2000.) + Console.log("This prints every 200 ms") +}, 200.) + +// Stop the interval after 500 ms +let timeoutId = setTimeoutFloat(() => { + clearInterval(intervalId) +}, 500.0) ``` */ @val @@ -110,13 +119,13 @@ See [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInte ## Examples ```rescript let intervalId = setInterval(() => { - Console.log("This prints in 2 seconds.") -}, 2000) + Console.log("This prints in 100 ms") +}, 100) -// Stop the interval after 10 seconds +// Stop the interval after 500 ms let timeoutId = setTimeout(() => { clearInterval(intervalId) -}, 10000) +}, 500) ``` */ @val From f54ee80ecf137a09a15d8ce4b4fa5c813e9018e6 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 23:05:25 -0300 Subject: [PATCH 14/22] add ignore-runtime-tests --- package.json | 2 +- scripts/DocTests.mjs | 39 +++++++++++++++++++++++++++++++++------ scripts/DocTests.res | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d2500be2..9dd01973 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "build": "rescript", "watch": "rescript build -w", "test": "node test/TestSuite.mjs && node test/TempTests.mjs", - "test-doc-examples": "node scripts/DocTests.mjs" + "test-doc-examples": "node scripts/DocTests.mjs --ignore-runtime-tests 'RescriptCore.Array.toReversed, RescriptCore.Promise.withResolvers'" }, "keywords": [ "rescript" diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index 9365fa17..ab93bc32 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -5,6 +5,7 @@ import * as Os from "os"; import * as Url from "url"; import * as Path from "path"; import * as Belt_List from "rescript/lib/es6/belt_List.js"; +import * as Nodeutil from "node:util"; import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; import * as Core__List from "../src/Core__List.mjs"; import * as Caml_option from "rescript/lib/es6/caml_option.js"; @@ -28,6 +29,8 @@ var ChildProcess = {}; var OS = {}; +var Util = {}; + var $$Node = { Path: Path$1, $$URL: $$URL, @@ -35,7 +38,8 @@ var $$Node = { Fs: Fs$1, $$Buffer: $$Buffer, ChildProcess: ChildProcess, - OS: OS + OS: OS, + Util: Util }; var dirname = Path.dirname(Url.fileURLToPath(import.meta.url)); @@ -73,7 +77,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 129, + 145, 9 ], Error: new Error() @@ -86,7 +90,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 127, + 143, 11 ], Error: new Error() @@ -99,7 +103,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 127, + 143, 11 ], Error: new Error() @@ -110,7 +114,7 @@ function prepareCompiler() { RE_EXN_ID: "Assert_failure", _1: [ "DocTests.res", - 129, + 145, 9 ], Error: new Error() @@ -130,6 +134,24 @@ function prepareCompiler() { }); } +var options = Object.fromEntries([[ + "ignore-runtime-tests", + { + type: "string" + } + ]]); + +var match = Nodeutil.parseArgs({ + args: process.argv.slice(2), + options: options + }); + +var values = match.values; + +var v = values["ignore-runtime-tests"]; + +var ignoreRuntimeTests = v !== undefined ? v.split(",") : []; + prepareCompiler(); async function run(command, args, options) { @@ -437,7 +459,9 @@ async function compilerResults() { ] ]; }); - var exampleErrors = await Promise.all(examples.map(async function (param) { + var exampleErrors = await Promise.all(examples.filter(function (param) { + return !ignoreRuntimeTests.includes(param[0].id); + }).map(async function (param) { var match = param[1]; var nodeTests = await Promise.all(match[0].map(async function (param) { var js = param[1]; @@ -513,6 +537,9 @@ export { makePackageJson , rescriptJson , prepareCompiler , + options , + values , + ignoreRuntimeTests , SpawnAsync , createFileInTempDir , compileTest , diff --git a/scripts/DocTests.res b/scripts/DocTests.res index 1479a9c2..4873c792 100644 --- a/scripts/DocTests.res +++ b/scripts/DocTests.res @@ -15,6 +15,9 @@ module Node = { @scope("process") external exit: int => unit = "exit" @scope(("process", "stderr")) external stderrWrite: string => unit = "write" + + @val @scope("process") + external argv: array = "argv" } module Fs = { @@ -56,6 +59,19 @@ module Node = { @module("os") external tmpdir: unit => string = "tmpdir" } + + module Util = { + type arg = {@as("type") type_: string} + type config = { + args: array, + options: Dict.t, + } + type parsed = { + values: Dict.t, + positionals: array, + } + @module("node:util") external parseArgs: config => parsed = "parseArgs" + } } open Node @@ -143,6 +159,18 @@ let prepareCompiler = () => { ChildProcess.execFileSync(rescriptBin, ["build"], {cwd: compilerDir})->ignore } +let options = Dict.fromArray([("ignore-runtime-tests", {Util.type_: "string"})]) + +let {Util.values: values} = Util.parseArgs({ + args: Process.argv->Array.sliceToEnd(~start=2), + options, +}) + +let ignoreRuntimeTests = switch values->Dict.get("ignore-runtime-tests") { +| Some(v) => v->String.split(",") +| None => [] +} + prepareCompiler() type example = { @@ -373,6 +401,7 @@ let compilerResults = async () => { let exampleErrors = await examples + ->Array.filter((({id}, _)) => !Array.includes(ignoreRuntimeTests, id)) ->Array.map(async ((example, (compiled, errors))) => { let nodeTests = await compiled From 62286d9fa358940cde9626338ff58bc7575966cd Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 23:07:34 -0300 Subject: [PATCH 15/22] trim arg whitespace --- scripts/DocTests.mjs | 4 +++- scripts/DocTests.res | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs index ab93bc32..a79fbd36 100644 --- a/scripts/DocTests.mjs +++ b/scripts/DocTests.mjs @@ -150,7 +150,9 @@ var values = match.values; var v = values["ignore-runtime-tests"]; -var ignoreRuntimeTests = v !== undefined ? v.split(",") : []; +var ignoreRuntimeTests = v !== undefined ? v.split(",").map(function (s) { + return s.trim(); + }) : []; prepareCompiler(); diff --git a/scripts/DocTests.res b/scripts/DocTests.res index 4873c792..75a2dbaa 100644 --- a/scripts/DocTests.res +++ b/scripts/DocTests.res @@ -167,7 +167,10 @@ let {Util.values: values} = Util.parseArgs({ }) let ignoreRuntimeTests = switch values->Dict.get("ignore-runtime-tests") { -| Some(v) => v->String.split(",") +| Some(v) => + v + ->String.split(",") + ->Array.map(s => s->String.trim) | None => [] } From e71be7d4a6e73408a2d3c389a893e236664a1974 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 23 Apr 2024 23:18:00 -0300 Subject: [PATCH 16/22] update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffecdbd2..4dc0aefb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Next version +- Added `assert_eq` function. https://github.com/rescript-association/rescript-core/pull/210 + ## 1.3.0 This version requires ReScript `>=11.1.0-rc.6`. @@ -44,7 +46,6 @@ This version requires ReScript `>=11.1.0-rc.6`. ### Documentation -- Fix docstring for `Array.getUnsafe` and `Array.filterMap` https://github.com/rescript-association/rescript-core/pull/168 ## 0.6.0 From 4a1beeb8c3cb853690fdba8f27e5573d6dfc4577 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 8 May 2024 11:59:45 -0300 Subject: [PATCH 17/22] restore CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dc0aefb..2c56a38d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ This version requires ReScript `>=11.1.0-rc.6`. ### Documentation +- Fix docstring for `Array.getUnsafe` and `Array.filterMap` https://github.com/rescript-association/rescript-core/pull/168 ## 0.6.0 From 8ee24af47c8d0867b5336010a6d3447b302db542 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 4 Jun 2024 18:26:20 -0300 Subject: [PATCH 18/22] improv docstrings for Null and Nullable module --- src/Core__Null.resi | 11 +++++++++-- src/Core__Nullable.resi | 12 +++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Core__Null.resi b/src/Core__Null.resi index f9e4261a..7a7f85bc 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -104,11 +104,18 @@ let getWithDefault: (t<'a>, 'a) => 'a /** `getExn(value)` raises an exception if `null`, otherwise returns the value. +## Examples + ```rescript -Null.getExn(Null.make(3)) // 3 +Null.getExn(Null.make(3))->assert_eq(3) + +switch Null.getExn(Null.make("ReScript")) { +| exception Invalid_argument(_) => assert(false) +| value => assert_eq(value, "ReScript") +} switch Null.getExn(Null.null) { -| exception _ => assert(true) +| exception Invalid_argument(_) => assert(true) | _ => assert(false) } ``` diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index b69d3bab..cc94c844 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -137,9 +137,13 @@ let getWithDefault: (t<'a>, 'a) => 'a `getExn(value)` raises an exception if `null` or `undefined`, otherwise returns the value. ```rescript -Nullable.getExn(Nullable.make(3)) // 3 +switch Nullable.getExn(Nullable.make("Hello")) { +| exception Invalid_argument(_) => assert(false) +| value => assert_eq(value, "Hello") +} + switch Nullable.getExn(Nullable.null) { -| exception _ => assert(true) +| exception Invalid_argument(_) => assert(true) | _ => assert(false) } ``` @@ -156,7 +160,9 @@ let getExn: t<'a> => 'a ## Examples ```rescript -Nullable.getUnsafe(Nullable.make(3)) == 3 +Nullable.make(3) +->Nullable.getUnsafe +->assert_eq(3) Nullable.getUnsafe(Nullable.null) ->Type.Classify.classify From f871587fba8d3c2743aaaa47a60521704c8865a8 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 4 Jun 2024 18:41:01 -0300 Subject: [PATCH 19/22] use %raw --- src/Core__Null.resi | 4 ++-- src/Core__Nullable.resi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Core__Null.resi b/src/Core__Null.resi index 7a7f85bc..b2157b6b 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -109,12 +109,12 @@ let getWithDefault: (t<'a>, 'a) => 'a ```rescript Null.getExn(Null.make(3))->assert_eq(3) -switch Null.getExn(Null.make("ReScript")) { +switch Null.getExn(%raw("ReScript")) { | exception Invalid_argument(_) => assert(false) | value => assert_eq(value, "ReScript") } -switch Null.getExn(Null.null) { +switch Null.getExn(%raw("null")) { | exception Invalid_argument(_) => assert(true) | _ => assert(false) } diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index cc94c844..4e929c61 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -137,12 +137,12 @@ let getWithDefault: (t<'a>, 'a) => 'a `getExn(value)` raises an exception if `null` or `undefined`, otherwise returns the value. ```rescript -switch Nullable.getExn(Nullable.make("Hello")) { +switch Nullable.getExn(%raw("Hello")) { | exception Invalid_argument(_) => assert(false) | value => assert_eq(value, "Hello") } -switch Nullable.getExn(Nullable.null) { +switch Nullable.getExn(%raw("undefined")) { | exception Invalid_argument(_) => assert(true) | _ => assert(false) } From 850d92a7effc1ee41704445d28a779c28866012d Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 4 Jun 2024 18:44:17 -0300 Subject: [PATCH 20/22] fix --- src/Core__Null.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__Null.resi b/src/Core__Null.resi index b2157b6b..7b443012 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -109,7 +109,7 @@ let getWithDefault: (t<'a>, 'a) => 'a ```rescript Null.getExn(Null.make(3))->assert_eq(3) -switch Null.getExn(%raw("ReScript")) { +switch Null.getExn(%raw("'ReScript'")) { | exception Invalid_argument(_) => assert(false) | value => assert_eq(value, "ReScript") } From fbf584e24b4a7d60e6c95cc82cf230be95dfeda6 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 4 Jun 2024 18:44:51 -0300 Subject: [PATCH 21/22] fix --- src/Core__Nullable.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index 4e929c61..b65912db 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -137,7 +137,7 @@ let getWithDefault: (t<'a>, 'a) => 'a `getExn(value)` raises an exception if `null` or `undefined`, otherwise returns the value. ```rescript -switch Nullable.getExn(%raw("Hello")) { +switch Nullable.getExn(%raw("'Hello'")) { | exception Invalid_argument(_) => assert(false) | value => assert_eq(value, "Hello") } From e05b5425f05ba23aef07a054f7afee36819c181e Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 8 Jun 2024 15:21:57 -0300 Subject: [PATCH 22/22] replace `panic` with `assert(false)` --- src/RescriptCore.mjs | 14 +++++++++++--- src/RescriptCore.res | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/RescriptCore.mjs b/src/RescriptCore.mjs index 53f9cb1e..a1f78f25 100644 --- a/src/RescriptCore.mjs +++ b/src/RescriptCore.mjs @@ -4,10 +4,18 @@ import * as Caml_obj from "rescript/lib/es6/caml_obj.js"; import * as Core__Error from "./Core__Error.mjs"; function assert_eq(a, b) { - if (Caml_obj.notequal(a, b)) { - return Core__Error.panic("Assertion Failed"); + if (!Caml_obj.notequal(a, b)) { + return ; } - + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "RescriptCore.res", + 127, + 4 + ], + Error: new Error() + }; } var $$Array; diff --git a/src/RescriptCore.res b/src/RescriptCore.res index 69acc0e1..5ddad4aa 100644 --- a/src/RescriptCore.res +++ b/src/RescriptCore.res @@ -124,6 +124,6 @@ list{1, 2} */ let assert_eq = (a, b) => { if a != b { - panic("Assertion Failed") + assert(false) } }