diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..599be4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/.zed/tasks.json b/.zed/tasks.json new file mode 100644 index 0000000..ab8da73 --- /dev/null +++ b/.zed/tasks.json @@ -0,0 +1,17 @@ +[ + { + "label": "gleam run", + "command": "gleam", + "args": ["run"], + "use_new_terminal": false, + "reveal": "never", + }, + + { + "label": "gleam format", + "command": "gleam", + "args": ["format"], + "use_new_terminal": false, + "reveal": "never", + }, +] diff --git a/README.md b/README.md index 6b52c9d..0a8437c 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,4 @@ -# markdown2 +# Luma -[![Package Version](https://img.shields.io/hexpm/v/markdown2)](https://hex.pm/packages/markdown2) -[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/markdown2/) - -```sh -gleam add markdown2@1 -``` -```gleam -import markdown2 - -pub fn main() -> Nil { - // TODO: An example of the project in use -} -``` - -Further documentation can be found at . - -## Development - -```sh -gleam run # Run the project -gleam test # Run the tests -``` +A parser for a semantic note taking markup language. +The parser is written in Gleam. you can test it with gleam run. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..8e1b45d --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +gleam build --target javascript +npx esbuild build/dev/javascript/markdown2/markdown2.mjs \ + --bundle \ + --outfile=parser.js \ + --format=iife \ + --global-name=App +rm -rf ui/parser.js +mv parser.js ui/parser.js diff --git a/node_modules/.bin/esbuild b/node_modules/.bin/esbuild new file mode 120000 index 0000000..c83ac07 --- /dev/null +++ b/node_modules/.bin/esbuild @@ -0,0 +1 @@ +../esbuild/bin/esbuild \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..d9471e9 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,66 @@ +{ + "name": "markdown2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + } + } +} diff --git a/node_modules/@esbuild/linux-x64/README.md b/node_modules/@esbuild/linux-x64/README.md new file mode 100644 index 0000000..b2f1930 --- /dev/null +++ b/node_modules/@esbuild/linux-x64/README.md @@ -0,0 +1,3 @@ +# esbuild + +This is the Linux 64-bit binary for esbuild, a JavaScript bundler and minifier. See https://github.com/evanw/esbuild for details. diff --git a/node_modules/@esbuild/linux-x64/bin/esbuild b/node_modules/@esbuild/linux-x64/bin/esbuild new file mode 100755 index 0000000..71fe4f8 Binary files /dev/null and b/node_modules/@esbuild/linux-x64/bin/esbuild differ diff --git a/node_modules/@esbuild/linux-x64/package.json b/node_modules/@esbuild/linux-x64/package.json new file mode 100644 index 0000000..1ce7bc3 --- /dev/null +++ b/node_modules/@esbuild/linux-x64/package.json @@ -0,0 +1,20 @@ +{ + "name": "@esbuild/linux-x64", + "version": "0.28.1", + "description": "The Linux 64-bit binary for esbuild, a JavaScript bundler.", + "repository": { + "type": "git", + "url": "git+https://github.com/evanw/esbuild.git" + }, + "license": "MIT", + "preferUnplugged": true, + "engines": { + "node": ">=18" + }, + "os": [ + "linux" + ], + "cpu": [ + "x64" + ] +} diff --git a/node_modules/esbuild/LICENSE.md b/node_modules/esbuild/LICENSE.md new file mode 100644 index 0000000..2027e8d --- /dev/null +++ b/node_modules/esbuild/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Evan Wallace + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/esbuild/README.md b/node_modules/esbuild/README.md new file mode 100644 index 0000000..93863d1 --- /dev/null +++ b/node_modules/esbuild/README.md @@ -0,0 +1,3 @@ +# esbuild + +This is a JavaScript bundler and minifier. See https://github.com/evanw/esbuild and the [JavaScript API documentation](https://esbuild.github.io/api/) for details. diff --git a/node_modules/esbuild/bin/esbuild b/node_modules/esbuild/bin/esbuild new file mode 100755 index 0000000..71fe4f8 Binary files /dev/null and b/node_modules/esbuild/bin/esbuild differ diff --git a/node_modules/esbuild/install.js b/node_modules/esbuild/install.js new file mode 100644 index 0000000..ee09eff --- /dev/null +++ b/node_modules/esbuild/install.js @@ -0,0 +1,300 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// lib/npm/node-platform.ts +var fs = require("fs"); +var os = require("os"); +var path = require("path"); +var ESBUILD_BINARY_PATH = process.env.ESBUILD_BINARY_PATH || ESBUILD_BINARY_PATH; +var isValidBinaryPath = (x) => !!x && x !== "/usr/bin/esbuild"; +var knownWindowsPackages = { + "win32 arm64 LE": "@esbuild/win32-arm64", + "win32 ia32 LE": "@esbuild/win32-ia32", + "win32 x64 LE": "@esbuild/win32-x64" +}; +var knownUnixlikePackages = { + "aix ppc64 BE": "@esbuild/aix-ppc64", + "android arm64 LE": "@esbuild/android-arm64", + "darwin arm64 LE": "@esbuild/darwin-arm64", + "darwin x64 LE": "@esbuild/darwin-x64", + "freebsd arm64 LE": "@esbuild/freebsd-arm64", + "freebsd x64 LE": "@esbuild/freebsd-x64", + "linux arm LE": "@esbuild/linux-arm", + "linux arm64 LE": "@esbuild/linux-arm64", + "linux ia32 LE": "@esbuild/linux-ia32", + "linux mips64el LE": "@esbuild/linux-mips64el", + "linux ppc64 LE": "@esbuild/linux-ppc64", + "linux riscv64 LE": "@esbuild/linux-riscv64", + "linux s390x BE": "@esbuild/linux-s390x", + "linux x64 LE": "@esbuild/linux-x64", + "linux loong64 LE": "@esbuild/linux-loong64", + "netbsd arm64 LE": "@esbuild/netbsd-arm64", + "netbsd x64 LE": "@esbuild/netbsd-x64", + "openbsd arm64 LE": "@esbuild/openbsd-arm64", + "openbsd x64 LE": "@esbuild/openbsd-x64", + "sunos x64 LE": "@esbuild/sunos-x64" +}; +var knownWebAssemblyFallbackPackages = { + "android arm LE": "@esbuild/android-arm", + "android x64 LE": "@esbuild/android-x64", + "openharmony arm64 LE": "@esbuild/openharmony-arm64" +}; +function pkgAndSubpathForCurrentPlatform() { + let pkg; + let subpath; + let isWASM = false; + let platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`; + if (platformKey in knownWindowsPackages) { + pkg = knownWindowsPackages[platformKey]; + subpath = "esbuild.exe"; + } else if (platformKey in knownUnixlikePackages) { + pkg = knownUnixlikePackages[platformKey]; + subpath = "bin/esbuild"; + } else if (platformKey in knownWebAssemblyFallbackPackages) { + pkg = knownWebAssemblyFallbackPackages[platformKey]; + subpath = "bin/esbuild"; + isWASM = true; + } else { + throw new Error(`Unsupported platform: ${platformKey}`); + } + return { pkg, subpath, isWASM }; +} +function downloadedBinPath(pkg, subpath) { + const esbuildLibDir = path.dirname(require.resolve("esbuild")); + return path.join(esbuildLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`); +} + +// lib/npm/node-install.ts +var fs2 = require("fs"); +var os2 = require("os"); +var path2 = require("path"); +var zlib = require("zlib"); +var https = require("https"); +var crypto = require("crypto"); +var child_process = require("child_process"); +var packageJSON = require(path2.join(__dirname, "package.json")); +var toPath = path2.join(__dirname, "bin", "esbuild"); +var isToPathJS = true; +function validateBinaryVersion(...command) { + command.push("--version"); + let stdout; + try { + stdout = child_process.execFileSync(command.shift(), command, { + // Without this, this install script strangely crashes with the error + // "EACCES: permission denied, write" but only on Ubuntu Linux when node is + // installed from the Snap Store. This is not a problem when you download + // the official version of node. The problem appears to be that stderr + // (i.e. file descriptor 2) isn't writable? + // + // More info: + // - https://snapcraft.io/ (what the Snap Store is) + // - https://nodejs.org/dist/ (download the official version of node) + // - https://github.com/evanw/esbuild/issues/1711#issuecomment-1027554035 + // + stdio: "pipe" + }).toString().trim(); + } catch (err) { + if (os2.platform() === "darwin" && /_SecTrustEvaluateWithError/.test(err + "")) { + let os3 = "this version of macOS"; + try { + os3 = "macOS " + child_process.execFileSync("sw_vers", ["-productVersion"]).toString().trim(); + } catch { + } + throw new Error(`The "esbuild" package cannot be installed because ${os3} is too outdated. + +The Go compiler (which esbuild relies on) no longer supports ${os3}, +which means the "esbuild" binary executable can't be run. You can either: + + * Update your version of macOS to one that the Go compiler supports + * Use the "esbuild-wasm" package instead of the "esbuild" package + * Build esbuild yourself using an older version of the Go compiler +`); + } + throw err; + } + if (stdout !== packageJSON.version) { + throw new Error(`Expected ${JSON.stringify(packageJSON.version)} but got ${JSON.stringify(stdout)}`); + } +} +function isYarn() { + const { npm_config_user_agent } = process.env; + if (npm_config_user_agent) { + return /\byarn\//.test(npm_config_user_agent); + } + return false; +} +function fetch(url) { + return new Promise((resolve, reject) => { + https.get(url, (res) => { + if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location) + return fetch(res.headers.location).then(resolve, reject); + if (res.statusCode !== 200) + return reject(new Error(`Server responded with ${res.statusCode}`)); + let chunks = []; + res.on("data", (chunk) => chunks.push(chunk)); + res.on("end", () => resolve(Buffer.concat(chunks))); + }).on("error", reject); + }); +} +function extractFileFromTarGzip(buffer, subpath) { + try { + buffer = zlib.unzipSync(buffer); + } catch (err) { + throw new Error(`Invalid gzip data in archive: ${err && err.message || err}`); + } + let str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, ""); + let offset = 0; + subpath = `package/${subpath}`; + while (offset < buffer.length) { + let name = str(offset, 100); + let size = parseInt(str(offset + 124, 12), 8); + offset += 512; + if (!isNaN(size) && size >= 0) { + if (name === subpath) return buffer.subarray(offset, offset + size); + offset += size + 511 & ~511; + } + } + throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`); +} +function installUsingNPM(pkg, subpath, binPath) { + const env = { ...process.env, npm_config_global: void 0 }; + const esbuildLibDir = path2.dirname(require.resolve("esbuild")); + const installDir = path2.join(esbuildLibDir, "npm-install"); + fs2.mkdirSync(installDir); + try { + fs2.writeFileSync(path2.join(installDir, "package.json"), "{}"); + child_process.execSync( + `npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${packageJSON.version}`, + { cwd: installDir, stdio: "pipe", env } + ); + const installedBinPath = path2.join(installDir, "node_modules", pkg, subpath); + binaryIntegrityCheck(pkg, subpath, fs2.readFileSync(installedBinPath)); + fs2.renameSync(installedBinPath, binPath); + } finally { + try { + removeRecursive(installDir); + } catch { + } + } +} +function removeRecursive(dir) { + for (const entry of fs2.readdirSync(dir)) { + const entryPath = path2.join(dir, entry); + let stats; + try { + stats = fs2.lstatSync(entryPath); + } catch { + continue; + } + if (stats.isDirectory()) removeRecursive(entryPath); + else fs2.unlinkSync(entryPath); + } + fs2.rmdirSync(dir); +} +function applyManualBinaryPathOverride(overridePath) { + const pathString = JSON.stringify(overridePath); + fs2.writeFileSync(toPath, `#!/usr/bin/env node +require('child_process').execFileSync(${pathString}, process.argv.slice(2), { stdio: 'inherit' }); +`); + const libMain = path2.join(__dirname, "lib", "main.js"); + const code = fs2.readFileSync(libMain, "utf8"); + fs2.writeFileSync(libMain, `var ESBUILD_BINARY_PATH = ${pathString}; +${code}`); +} +function maybeOptimizePackage(binPath, isWASM) { + if (os2.platform() !== "win32" && !isYarn() && !isWASM) { + const tempPath = path2.join(__dirname, "bin-esbuild"); + try { + fs2.linkSync(binPath, tempPath); + fs2.renameSync(tempPath, toPath); + isToPathJS = false; + fs2.unlinkSync(tempPath); + } catch { + } + } +} +function binaryIntegrityCheck(pkg, subpath, bytes) { + const hash = crypto.createHash("sha256").update(bytes).digest("hex"); + const key = `${pkg}/${subpath}`; + const expected = packageJSON["esbuild.binaryHashes"][key]; + if (!expected) throw new Error(`Missing hash for "${key}"`); + if (hash !== expected) throw new Error(`"${hash.slice(0, 8)}..." doesn't match "${expected.slice(0, 8)}..." for "${pkg}"`); +} +async function downloadDirectlyFromNPM(pkg, subpath, binPath) { + const url = `https://registry.npmjs.org/${pkg}/-/${pkg.replace("@esbuild/", "")}-${packageJSON.version}.tgz`; + console.error(`[esbuild] Trying to download ${JSON.stringify(url)}`); + try { + const bytes = extractFileFromTarGzip(await fetch(url), subpath); + binaryIntegrityCheck(pkg, subpath, bytes); + fs2.writeFileSync(binPath, bytes); + fs2.chmodSync(binPath, 493); + } catch (e) { + console.error(`[esbuild] Failed to download ${JSON.stringify(url)}: ${e && e.message || e}`); + throw e; + } +} +async function checkAndPreparePackage() { + if (isValidBinaryPath(ESBUILD_BINARY_PATH)) { + if (!fs2.existsSync(ESBUILD_BINARY_PATH)) { + console.warn(`[esbuild] Ignoring bad configuration: ESBUILD_BINARY_PATH=${ESBUILD_BINARY_PATH}`); + } else { + applyManualBinaryPathOverride(ESBUILD_BINARY_PATH); + return; + } + } + const { pkg, subpath, isWASM } = pkgAndSubpathForCurrentPlatform(); + let binPath; + try { + binPath = require.resolve(`${pkg}/${subpath}`); + } catch (e) { + console.error(`[esbuild] Failed to find package "${pkg}" on the file system + +This can happen if you use the "--no-optional" flag. The "optionalDependencies" +package.json feature is used by esbuild to install the correct binary executable +for your current platform. This install script will now attempt to work around +this. If that fails, you need to remove the "--no-optional" flag to use esbuild. +`); + if (isWASM) throw new Error(`Failed to install package "${pkg}"`); + binPath = downloadedBinPath(pkg, subpath); + try { + console.error(`[esbuild] Trying to install package "${pkg}" using npm`); + installUsingNPM(pkg, subpath, binPath); + } catch (e2) { + console.error(`[esbuild] Failed to install package "${pkg}" using npm: ${e2 && e2.message || e2}`); + try { + await downloadDirectlyFromNPM(pkg, subpath, binPath); + } catch (e3) { + throw new Error(`Failed to install package "${pkg}"`); + } + } + } + maybeOptimizePackage(binPath, isWASM); +} +checkAndPreparePackage().then(() => { + if (isToPathJS) { + validateBinaryVersion(process.execPath, toPath); + } else { + validateBinaryVersion(toPath); + } +}); diff --git a/node_modules/esbuild/lib/main.d.ts b/node_modules/esbuild/lib/main.d.ts new file mode 100644 index 0000000..9e69c39 --- /dev/null +++ b/node_modules/esbuild/lib/main.d.ts @@ -0,0 +1,716 @@ +export type Platform = 'browser' | 'node' | 'neutral' +export type Format = 'iife' | 'cjs' | 'esm' +export type Loader = 'base64' | 'binary' | 'copy' | 'css' | 'dataurl' | 'default' | 'empty' | 'file' | 'js' | 'json' | 'jsx' | 'local-css' | 'text' | 'ts' | 'tsx' +export type LogLevel = 'verbose' | 'debug' | 'info' | 'warning' | 'error' | 'silent' +export type Charset = 'ascii' | 'utf8' +export type Drop = 'console' | 'debugger' +export type AbsPaths = 'code' | 'log' | 'metafile' + +interface CommonOptions { + /** Documentation: https://esbuild.github.io/api/#sourcemap */ + sourcemap?: boolean | 'linked' | 'inline' | 'external' | 'both' + /** Documentation: https://esbuild.github.io/api/#legal-comments */ + legalComments?: 'none' | 'inline' | 'eof' | 'linked' | 'external' + /** Documentation: https://esbuild.github.io/api/#source-root */ + sourceRoot?: string + /** Documentation: https://esbuild.github.io/api/#sources-content */ + sourcesContent?: boolean + + /** Documentation: https://esbuild.github.io/api/#format */ + format?: Format + /** Documentation: https://esbuild.github.io/api/#global-name */ + globalName?: string + /** Documentation: https://esbuild.github.io/api/#target */ + target?: string | string[] + /** Documentation: https://esbuild.github.io/api/#supported */ + supported?: Record + /** Documentation: https://esbuild.github.io/api/#platform */ + platform?: Platform + + /** Documentation: https://esbuild.github.io/api/#mangle-props */ + mangleProps?: RegExp + /** Documentation: https://esbuild.github.io/api/#mangle-props */ + reserveProps?: RegExp + /** Documentation: https://esbuild.github.io/api/#mangle-props */ + mangleQuoted?: boolean + /** Documentation: https://esbuild.github.io/api/#mangle-props */ + mangleCache?: Record + /** Documentation: https://esbuild.github.io/api/#drop */ + drop?: Drop[] + /** Documentation: https://esbuild.github.io/api/#drop-labels */ + dropLabels?: string[] + /** Documentation: https://esbuild.github.io/api/#minify */ + minify?: boolean + /** Documentation: https://esbuild.github.io/api/#minify */ + minifyWhitespace?: boolean + /** Documentation: https://esbuild.github.io/api/#minify */ + minifyIdentifiers?: boolean + /** Documentation: https://esbuild.github.io/api/#minify */ + minifySyntax?: boolean + /** Documentation: https://esbuild.github.io/api/#line-limit */ + lineLimit?: number + /** Documentation: https://esbuild.github.io/api/#charset */ + charset?: Charset + /** Documentation: https://esbuild.github.io/api/#tree-shaking */ + treeShaking?: boolean + /** Documentation: https://esbuild.github.io/api/#ignore-annotations */ + ignoreAnnotations?: boolean + + /** Documentation: https://esbuild.github.io/api/#jsx */ + jsx?: 'transform' | 'preserve' | 'automatic' + /** Documentation: https://esbuild.github.io/api/#jsx-factory */ + jsxFactory?: string + /** Documentation: https://esbuild.github.io/api/#jsx-fragment */ + jsxFragment?: string + /** Documentation: https://esbuild.github.io/api/#jsx-import-source */ + jsxImportSource?: string + /** Documentation: https://esbuild.github.io/api/#jsx-development */ + jsxDev?: boolean + /** Documentation: https://esbuild.github.io/api/#jsx-side-effects */ + jsxSideEffects?: boolean + + /** Documentation: https://esbuild.github.io/api/#define */ + define?: { [key: string]: string } + /** Documentation: https://esbuild.github.io/api/#pure */ + pure?: string[] + /** Documentation: https://esbuild.github.io/api/#keep-names */ + keepNames?: boolean + + /** Documentation: https://esbuild.github.io/api/#abs-paths */ + absPaths?: AbsPaths[] + /** Documentation: https://esbuild.github.io/api/#color */ + color?: boolean + /** Documentation: https://esbuild.github.io/api/#log-level */ + logLevel?: LogLevel + /** Documentation: https://esbuild.github.io/api/#log-limit */ + logLimit?: number + /** Documentation: https://esbuild.github.io/api/#log-override */ + logOverride?: Record + + /** Documentation: https://esbuild.github.io/api/#tsconfig-raw */ + tsconfigRaw?: string | TsconfigRaw +} + +export interface TsconfigRaw { + compilerOptions?: { + alwaysStrict?: boolean + baseUrl?: string + experimentalDecorators?: boolean + importsNotUsedAsValues?: 'remove' | 'preserve' | 'error' + jsx?: 'preserve' | 'react-native' | 'react' | 'react-jsx' | 'react-jsxdev' + jsxFactory?: string + jsxFragmentFactory?: string + jsxImportSource?: string + paths?: Record + preserveValueImports?: boolean + strict?: boolean + target?: string + useDefineForClassFields?: boolean + verbatimModuleSyntax?: boolean + } +} + +export interface BuildOptions extends CommonOptions { + /** Documentation: https://esbuild.github.io/api/#bundle */ + bundle?: boolean + /** Documentation: https://esbuild.github.io/api/#splitting */ + splitting?: boolean + /** Documentation: https://esbuild.github.io/api/#preserve-symlinks */ + preserveSymlinks?: boolean + /** Documentation: https://esbuild.github.io/api/#outfile */ + outfile?: string + /** Documentation: https://esbuild.github.io/api/#metafile */ + metafile?: boolean + /** Documentation: https://esbuild.github.io/api/#outdir */ + outdir?: string + /** Documentation: https://esbuild.github.io/api/#outbase */ + outbase?: string + /** Documentation: https://esbuild.github.io/api/#external */ + external?: string[] + /** Documentation: https://esbuild.github.io/api/#packages */ + packages?: 'bundle' | 'external' + /** Documentation: https://esbuild.github.io/api/#alias */ + alias?: Record + /** Documentation: https://esbuild.github.io/api/#loader */ + loader?: { [ext: string]: Loader } + /** Documentation: https://esbuild.github.io/api/#resolve-extensions */ + resolveExtensions?: string[] + /** Documentation: https://esbuild.github.io/api/#main-fields */ + mainFields?: string[] + /** Documentation: https://esbuild.github.io/api/#conditions */ + conditions?: string[] + /** Documentation: https://esbuild.github.io/api/#write */ + write?: boolean + /** Documentation: https://esbuild.github.io/api/#allow-overwrite */ + allowOverwrite?: boolean + /** Documentation: https://esbuild.github.io/api/#tsconfig */ + tsconfig?: string + /** Documentation: https://esbuild.github.io/api/#out-extension */ + outExtension?: { [ext: string]: string } + /** Documentation: https://esbuild.github.io/api/#public-path */ + publicPath?: string + /** Documentation: https://esbuild.github.io/api/#entry-names */ + entryNames?: string + /** Documentation: https://esbuild.github.io/api/#chunk-names */ + chunkNames?: string + /** Documentation: https://esbuild.github.io/api/#asset-names */ + assetNames?: string + /** Documentation: https://esbuild.github.io/api/#inject */ + inject?: string[] + /** Documentation: https://esbuild.github.io/api/#banner */ + banner?: { [type: string]: string } + /** Documentation: https://esbuild.github.io/api/#footer */ + footer?: { [type: string]: string } + /** Documentation: https://esbuild.github.io/api/#entry-points */ + entryPoints?: (string | { in: string, out: string })[] | Record + /** Documentation: https://esbuild.github.io/api/#stdin */ + stdin?: StdinOptions + /** Documentation: https://esbuild.github.io/plugins/ */ + plugins?: Plugin[] + /** Documentation: https://esbuild.github.io/api/#working-directory */ + absWorkingDir?: string + /** Documentation: https://esbuild.github.io/api/#node-paths */ + nodePaths?: string[]; // The "NODE_PATH" variable from Node.js +} + +export interface StdinOptions { + contents: string | Uint8Array + resolveDir?: string + sourcefile?: string + loader?: Loader +} + +export interface Message { + id: string + pluginName: string + text: string + location: Location | null + notes: Note[] + + /** + * Optional user-specified data that is passed through unmodified. You can + * use this to stash the original error, for example. + */ + detail: any +} + +export interface Note { + text: string + location: Location | null +} + +export interface Location { + file: string + namespace: string + /** 1-based */ + line: number + /** 0-based, in bytes */ + column: number + /** in bytes */ + length: number + lineText: string + suggestion: string +} + +export interface OutputFile { + path: string + contents: Uint8Array + hash: string + /** "contents" as text (changes automatically with "contents") */ + readonly text: string +} + +export interface BuildResult { + errors: Message[] + warnings: Message[] + /** Only when "write: false" */ + outputFiles: OutputFile[] | (ProvidedOptions['write'] extends false ? never : undefined) + /** Only when "metafile: true" */ + metafile: Metafile | (ProvidedOptions['metafile'] extends true ? never : undefined) + /** Only when "mangleCache" is present */ + mangleCache: Record | (ProvidedOptions['mangleCache'] extends Object ? never : undefined) +} + +export interface BuildFailure extends Error { + errors: Message[] + warnings: Message[] +} + +/** Documentation: https://esbuild.github.io/api/#serve-arguments */ +export interface ServeOptions { + port?: number + host?: string + servedir?: string + keyfile?: string + certfile?: string + fallback?: string + cors?: CORSOptions + onRequest?: (args: ServeOnRequestArgs) => void +} + +/** Documentation: https://esbuild.github.io/api/#cors */ +export interface CORSOptions { + origin?: string | string[] +} + +export interface ServeOnRequestArgs { + remoteAddress: string + method: string + path: string + status: number + /** The time to generate the response, not to send it */ + timeInMS: number +} + +/** Documentation: https://esbuild.github.io/api/#serve-return-values */ +export interface ServeResult { + port: number + hosts: string[] +} + +export interface TransformOptions extends CommonOptions { + /** Documentation: https://esbuild.github.io/api/#sourcefile */ + sourcefile?: string + /** Documentation: https://esbuild.github.io/api/#loader */ + loader?: Loader + /** Documentation: https://esbuild.github.io/api/#banner */ + banner?: string + /** Documentation: https://esbuild.github.io/api/#footer */ + footer?: string +} + +export interface TransformResult { + code: string + map: string + warnings: Message[] + /** Only when "mangleCache" is present */ + mangleCache: Record | (ProvidedOptions['mangleCache'] extends Object ? never : undefined) + /** Only when "legalComments" is "external" */ + legalComments: string | (ProvidedOptions['legalComments'] extends 'external' ? never : undefined) +} + +export interface TransformFailure extends Error { + errors: Message[] + warnings: Message[] +} + +export interface Plugin { + name: string + setup: (build: PluginBuild) => (void | Promise) +} + +export interface PluginBuild { + /** Documentation: https://esbuild.github.io/plugins/#build-options */ + initialOptions: BuildOptions + + /** Documentation: https://esbuild.github.io/plugins/#resolve */ + resolve(path: string, options?: ResolveOptions): Promise + + /** Documentation: https://esbuild.github.io/plugins/#on-start */ + onStart(callback: () => + (OnStartResult | null | void | Promise)): void + + /** Documentation: https://esbuild.github.io/plugins/#on-end */ + onEnd(callback: (result: BuildResult) => + (OnEndResult | null | void | Promise)): void + + /** Documentation: https://esbuild.github.io/plugins/#on-resolve */ + onResolve(options: OnResolveOptions, callback: (args: OnResolveArgs) => + (OnResolveResult | null | undefined | Promise)): void + + /** Documentation: https://esbuild.github.io/plugins/#on-load */ + onLoad(options: OnLoadOptions, callback: (args: OnLoadArgs) => + (OnLoadResult | null | undefined | Promise)): void + + /** Documentation: https://esbuild.github.io/plugins/#on-dispose */ + onDispose(callback: () => void): void + + // This is a full copy of the esbuild library in case you need it + esbuild: { + context: typeof context, + build: typeof build, + buildSync: typeof buildSync, + transform: typeof transform, + transformSync: typeof transformSync, + formatMessages: typeof formatMessages, + formatMessagesSync: typeof formatMessagesSync, + analyzeMetafile: typeof analyzeMetafile, + analyzeMetafileSync: typeof analyzeMetafileSync, + initialize: typeof initialize, + version: typeof version, + } +} + +/** Documentation: https://esbuild.github.io/plugins/#resolve-options */ +export interface ResolveOptions { + pluginName?: string + importer?: string + namespace?: string + resolveDir?: string + kind?: ImportKind + pluginData?: any + with?: Record +} + +/** Documentation: https://esbuild.github.io/plugins/#resolve-results */ +export interface ResolveResult { + errors: Message[] + warnings: Message[] + + path: string + external: boolean + sideEffects: boolean + namespace: string + suffix: string + pluginData: any +} + +export interface OnStartResult { + errors?: PartialMessage[] + warnings?: PartialMessage[] +} + +export interface OnEndResult { + errors?: PartialMessage[] + warnings?: PartialMessage[] +} + +/** Documentation: https://esbuild.github.io/plugins/#on-resolve-options */ +export interface OnResolveOptions { + filter: RegExp + namespace?: string +} + +/** Documentation: https://esbuild.github.io/plugins/#on-resolve-arguments */ +export interface OnResolveArgs { + path: string + importer: string + namespace: string + resolveDir: string + kind: ImportKind + pluginData: any + with: Record +} + +export type ImportKind = + | 'entry-point' + + // JS + | 'import-statement' + | 'require-call' + | 'dynamic-import' + | 'require-resolve' + + // CSS + | 'import-rule' + | 'composes-from' + | 'url-token' + +/** Documentation: https://esbuild.github.io/plugins/#on-resolve-results */ +export interface OnResolveResult { + pluginName?: string + + errors?: PartialMessage[] + warnings?: PartialMessage[] + + path?: string + external?: boolean + sideEffects?: boolean + namespace?: string + suffix?: string + pluginData?: any + + watchFiles?: string[] + watchDirs?: string[] +} + +/** Documentation: https://esbuild.github.io/plugins/#on-load-options */ +export interface OnLoadOptions { + filter: RegExp + namespace?: string +} + +/** Documentation: https://esbuild.github.io/plugins/#on-load-arguments */ +export interface OnLoadArgs { + path: string + namespace: string + suffix: string + pluginData: any + with: Record +} + +/** Documentation: https://esbuild.github.io/plugins/#on-load-results */ +export interface OnLoadResult { + pluginName?: string + + errors?: PartialMessage[] + warnings?: PartialMessage[] + + contents?: string | Uint8Array + resolveDir?: string + loader?: Loader + pluginData?: any + + watchFiles?: string[] + watchDirs?: string[] +} + +export interface PartialMessage { + id?: string + pluginName?: string + text?: string + location?: Partial | null + notes?: PartialNote[] + detail?: any +} + +export interface PartialNote { + text?: string + location?: Partial | null +} + +/** Documentation: https://esbuild.github.io/api/#metafile */ +export interface Metafile { + inputs: { + [path: string]: { + bytes: number + imports: { + path: string + kind: ImportKind + external?: boolean + original?: string + with?: Record + }[] + format?: 'cjs' | 'esm' + with?: Record + } + } + outputs: { + [path: string]: { + bytes: number + inputs: { + [path: string]: { + bytesInOutput: number + } + } + imports: { + path: string + kind: ImportKind | 'file-loader' + external?: boolean + }[] + exports: string[] + entryPoint?: string + cssBundle?: string + } + } +} + +export interface FormatMessagesOptions { + kind: 'error' | 'warning' + color?: boolean + terminalWidth?: number +} + +export interface AnalyzeMetafileOptions { + color?: boolean + verbose?: boolean +} + +/** Documentation: https://esbuild.github.io/api/#watch-arguments */ +export interface WatchOptions { + delay?: number // In milliseconds +} + +export interface BuildContext { + /** Documentation: https://esbuild.github.io/api/#rebuild */ + rebuild(): Promise> + + /** Documentation: https://esbuild.github.io/api/#watch */ + watch(options?: WatchOptions): Promise + + /** Documentation: https://esbuild.github.io/api/#serve */ + serve(options?: ServeOptions): Promise + + cancel(): Promise + dispose(): Promise +} + +// This is a TypeScript type-level function which replaces any keys in "In" +// that aren't in "Out" with "never". We use this to reject properties with +// typos in object literals. See: https://stackoverflow.com/questions/49580725 +type SameShape = In & { [Key in Exclude]: never } + +/** + * This function invokes the "esbuild" command-line tool for you. It returns a + * promise that either resolves with a "BuildResult" object or rejects with a + * "BuildFailure" object. + * + * - Works in node: yes + * - Works in browser: yes + * + * Documentation: https://esbuild.github.io/api/#build + */ +export declare function build(options: SameShape): Promise> + +/** + * This is the advanced long-running form of "build" that supports additional + * features such as watch mode and a local development server. + * + * - Works in node: yes + * - Works in browser: no + * + * Documentation: https://esbuild.github.io/api/#build + */ +export declare function context(options: SameShape): Promise> + +/** + * This function transforms a single JavaScript file. It can be used to minify + * JavaScript, convert TypeScript/JSX to JavaScript, or convert newer JavaScript + * to older JavaScript. It returns a promise that is either resolved with a + * "TransformResult" object or rejected with a "TransformFailure" object. + * + * - Works in node: yes + * - Works in browser: yes + * + * Documentation: https://esbuild.github.io/api/#transform + */ +export declare function transform(input: string | Uint8Array, options?: SameShape): Promise> + +/** + * Converts log messages to formatted message strings suitable for printing in + * the terminal. This allows you to reuse the built-in behavior of esbuild's + * log message formatter. This is a batch-oriented API for efficiency. + * + * - Works in node: yes + * - Works in browser: yes + */ +export declare function formatMessages(messages: PartialMessage[], options: FormatMessagesOptions): Promise + +/** + * Pretty-prints an analysis of the metafile JSON to a string. This is just for + * convenience to be able to match esbuild's pretty-printing exactly. If you want + * to customize it, you can just inspect the data in the metafile yourself. + * + * - Works in node: yes + * - Works in browser: yes + * + * Documentation: https://esbuild.github.io/api/#analyze + */ +export declare function analyzeMetafile(metafile: Metafile | string, options?: AnalyzeMetafileOptions): Promise + +/** + * A synchronous version of "build". + * + * - Works in node: yes + * - Works in browser: no + * + * Documentation: https://esbuild.github.io/api/#build + */ +export declare function buildSync(options: SameShape): BuildResult + +/** + * A synchronous version of "transform". + * + * - Works in node: yes + * - Works in browser: no + * + * Documentation: https://esbuild.github.io/api/#transform + */ +export declare function transformSync(input: string | Uint8Array, options?: SameShape): TransformResult + +/** + * A synchronous version of "formatMessages". + * + * - Works in node: yes + * - Works in browser: no + */ +export declare function formatMessagesSync(messages: PartialMessage[], options: FormatMessagesOptions): string[] + +/** + * A synchronous version of "analyzeMetafile". + * + * - Works in node: yes + * - Works in browser: no + * + * Documentation: https://esbuild.github.io/api/#analyze + */ +export declare function analyzeMetafileSync(metafile: Metafile | string, options?: AnalyzeMetafileOptions): string + +/** + * This configures the browser-based version of esbuild. It is necessary to + * call this first and wait for the returned promise to be resolved before + * making other API calls when using esbuild in the browser. + * + * - Works in node: yes + * - Works in browser: yes ("options" is required) + * + * Documentation: https://esbuild.github.io/api/#browser + */ +export declare function initialize(options: InitializeOptions): Promise + +export interface InitializeOptions { + /** + * The URL of the "esbuild.wasm" file. This must be provided when running + * esbuild in the browser. + */ + wasmURL?: string | URL + + /** + * The result of calling "new WebAssembly.Module(buffer)" where "buffer" + * is a typed array or ArrayBuffer containing the binary code of the + * "esbuild.wasm" file. + * + * You can use this as an alternative to "wasmURL" for environments where it's + * not possible to download the WebAssembly module. + */ + wasmModule?: WebAssembly.Module + + /** + * By default esbuild runs the WebAssembly-based browser API in a web worker + * to avoid blocking the UI thread. This can be disabled by setting "worker" + * to false. + */ + worker?: boolean +} + +export let version: string + +// Call this function to terminate esbuild's child process. The child process +// is not terminated and re-created after each API call because it's more +// efficient to keep it around when there are multiple API calls. +// +// In node this happens automatically before the parent node process exits. So +// you only need to call this if you know you will not make any more esbuild +// API calls and you want to clean up resources. +// +// Unlike node, Deno lacks the necessary APIs to clean up child processes +// automatically. You must manually call stop() in Deno when you're done +// using esbuild or Deno will continue running forever. +// +// Another reason you might want to call this is if you are using esbuild from +// within a Deno test. Deno fails tests that create a child process without +// killing it before the test ends, so you have to call this function (and +// await the returned promise) in every Deno test that uses esbuild. +export declare function stop(): Promise + +// Note: These declarations exist to avoid type errors when you omit "dom" from +// "lib" in your "tsconfig.json" file. TypeScript confusingly declares the +// global "WebAssembly" type in "lib.dom.d.ts" even though it has nothing to do +// with the browser DOM and is present in many non-browser JavaScript runtimes +// (e.g. node and deno). Declaring it here allows esbuild's API to be used in +// these scenarios. +// +// There's an open issue about getting this problem corrected (although these +// declarations will need to remain even if this is fixed for backward +// compatibility with older TypeScript versions): +// +// https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/826 +// +declare global { + namespace WebAssembly { + interface Module { + } + } + interface URL { + } +} diff --git a/node_modules/esbuild/lib/main.js b/node_modules/esbuild/lib/main.js new file mode 100644 index 0000000..1c23302 --- /dev/null +++ b/node_modules/esbuild/lib/main.js @@ -0,0 +1,2532 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/npm/node.ts +var node_exports = {}; +__export(node_exports, { + analyzeMetafile: () => analyzeMetafile, + analyzeMetafileSync: () => analyzeMetafileSync, + build: () => build, + buildSync: () => buildSync, + context: () => context, + default: () => node_default, + formatMessages: () => formatMessages, + formatMessagesSync: () => formatMessagesSync, + initialize: () => initialize, + stop: () => stop, + transform: () => transform, + transformSync: () => transformSync, + version: () => version +}); +module.exports = __toCommonJS(node_exports); + +// lib/shared/stdio_protocol.ts +function encodePacket(packet) { + let visit = (value) => { + if (value === null) { + bb.write8(0); + } else if (typeof value === "boolean") { + bb.write8(1); + bb.write8(+value); + } else if (typeof value === "number") { + bb.write8(2); + bb.write32(value | 0); + } else if (typeof value === "string") { + bb.write8(3); + bb.write(encodeUTF8(value)); + } else if (value instanceof Uint8Array) { + bb.write8(4); + bb.write(value); + } else if (value instanceof Array) { + bb.write8(5); + bb.write32(value.length); + for (let item of value) { + visit(item); + } + } else { + let keys = Object.keys(value); + bb.write8(6); + bb.write32(keys.length); + for (let key of keys) { + bb.write(encodeUTF8(key)); + visit(value[key]); + } + } + }; + let bb = new ByteBuffer(); + bb.write32(0); + bb.write32(packet.id << 1 | +!packet.isRequest); + visit(packet.value); + writeUInt32LE(bb.buf, bb.len - 4, 0); + return bb.buf.subarray(0, bb.len); +} +function decodePacket(bytes) { + let visit = () => { + switch (bb.read8()) { + case 0: + return null; + case 1: + return !!bb.read8(); + case 2: + return bb.read32(); + case 3: + return decodeUTF8(bb.read()); + case 4: + return bb.read(); + case 5: { + let count = bb.read32(); + let value2 = []; + for (let i = 0; i < count; i++) { + value2.push(visit()); + } + return value2; + } + case 6: { + let count = bb.read32(); + let value2 = {}; + for (let i = 0; i < count; i++) { + value2[decodeUTF8(bb.read())] = visit(); + } + return value2; + } + default: + throw new Error("Invalid packet"); + } + }; + let bb = new ByteBuffer(bytes); + let id = bb.read32(); + let isRequest = (id & 1) === 0; + id >>>= 1; + let value = visit(); + if (bb.ptr !== bytes.length) { + throw new Error("Invalid packet"); + } + return { id, isRequest, value }; +} +var ByteBuffer = class { + constructor(buf = new Uint8Array(1024)) { + this.buf = buf; + this.len = 0; + this.ptr = 0; + } + _write(delta) { + if (this.len + delta > this.buf.length) { + let clone = new Uint8Array((this.len + delta) * 2); + clone.set(this.buf); + this.buf = clone; + } + this.len += delta; + return this.len - delta; + } + write8(value) { + let offset = this._write(1); + this.buf[offset] = value; + } + write32(value) { + let offset = this._write(4); + writeUInt32LE(this.buf, value, offset); + } + write(bytes) { + let offset = this._write(4 + bytes.length); + writeUInt32LE(this.buf, bytes.length, offset); + this.buf.set(bytes, offset + 4); + } + _read(delta) { + if (this.ptr + delta > this.buf.length) { + throw new Error("Invalid packet"); + } + this.ptr += delta; + return this.ptr - delta; + } + read8() { + return this.buf[this._read(1)]; + } + read32() { + return readUInt32LE(this.buf, this._read(4)); + } + read() { + let length = this.read32(); + let bytes = new Uint8Array(length); + let ptr = this._read(bytes.length); + bytes.set(this.buf.subarray(ptr, ptr + length)); + return bytes; + } +}; +var encodeUTF8; +var decodeUTF8; +var encodeInvariant; +if (typeof TextEncoder !== "undefined" && typeof TextDecoder !== "undefined") { + let encoder = new TextEncoder(); + let decoder = new TextDecoder(); + encodeUTF8 = (text) => encoder.encode(text); + decodeUTF8 = (bytes) => decoder.decode(bytes); + encodeInvariant = 'new TextEncoder().encode("")'; +} else if (typeof Buffer !== "undefined") { + encodeUTF8 = (text) => Buffer.from(text); + decodeUTF8 = (bytes) => { + let { buffer, byteOffset, byteLength } = bytes; + return Buffer.from(buffer, byteOffset, byteLength).toString(); + }; + encodeInvariant = 'Buffer.from("")'; +} else { + throw new Error("No UTF-8 codec found"); +} +if (!(encodeUTF8("") instanceof Uint8Array)) + throw new Error(`Invariant violation: "${encodeInvariant} instanceof Uint8Array" is incorrectly false + +This indicates that your JavaScript environment is broken. You cannot use +esbuild in this environment because esbuild relies on this invariant. This +is not a problem with esbuild. You need to fix your environment instead. +`); +function readUInt32LE(buffer, offset) { + return (buffer[offset++] | buffer[offset++] << 8 | buffer[offset++] << 16 | buffer[offset++] << 24) >>> 0; +} +function writeUInt32LE(buffer, value, offset) { + buffer[offset++] = value; + buffer[offset++] = value >> 8; + buffer[offset++] = value >> 16; + buffer[offset++] = value >> 24; +} + +// lib/shared/uint8array_json_parser.ts +var fromCharCode = String.fromCharCode; +function throwSyntaxError(bytes, index, message) { + const c = bytes[index]; + let line = 1; + let column = 0; + for (let i = 0; i < index; i++) { + if (bytes[i] === 10 /* Newline */) { + line++; + column = 0; + } else { + column++; + } + } + throw new SyntaxError( + message ? message : index === bytes.length ? "Unexpected end of input while parsing JSON" : c >= 32 && c <= 126 ? `Unexpected character ${fromCharCode(c)} in JSON at position ${index} (line ${line}, column ${column})` : `Unexpected byte 0x${c.toString(16)} in JSON at position ${index} (line ${line}, column ${column})` + ); +} +function JSON_parse(bytes) { + if (!(bytes instanceof Uint8Array)) { + throw new Error(`JSON input must be a Uint8Array`); + } + const propertyStack = []; + const objectStack = []; + const stateStack = []; + const length = bytes.length; + let property = null; + let state = 0 /* TopLevel */; + let object; + let i = 0; + while (i < length) { + let c = bytes[i++]; + if (c <= 32 /* Space */) { + continue; + } + let value; + if (state === 2 /* Object */ && property === null && c !== 34 /* Quote */ && c !== 125 /* CloseBrace */) { + throwSyntaxError(bytes, --i); + } + switch (c) { + // True + case 116 /* LowerT */: { + if (bytes[i++] !== 114 /* LowerR */ || bytes[i++] !== 117 /* LowerU */ || bytes[i++] !== 101 /* LowerE */) { + throwSyntaxError(bytes, --i); + } + value = true; + break; + } + // False + case 102 /* LowerF */: { + if (bytes[i++] !== 97 /* LowerA */ || bytes[i++] !== 108 /* LowerL */ || bytes[i++] !== 115 /* LowerS */ || bytes[i++] !== 101 /* LowerE */) { + throwSyntaxError(bytes, --i); + } + value = false; + break; + } + // Null + case 110 /* LowerN */: { + if (bytes[i++] !== 117 /* LowerU */ || bytes[i++] !== 108 /* LowerL */ || bytes[i++] !== 108 /* LowerL */) { + throwSyntaxError(bytes, --i); + } + value = null; + break; + } + // Number begin + case 45 /* Minus */: + case 46 /* Dot */: + case 48 /* Digit0 */: + case 49 /* Digit1 */: + case 50 /* Digit2 */: + case 51 /* Digit3 */: + case 52 /* Digit4 */: + case 53 /* Digit5 */: + case 54 /* Digit6 */: + case 55 /* Digit7 */: + case 56 /* Digit8 */: + case 57 /* Digit9 */: { + let index = i; + value = fromCharCode(c); + c = bytes[i]; + while (true) { + switch (c) { + case 43 /* Plus */: + case 45 /* Minus */: + case 46 /* Dot */: + case 48 /* Digit0 */: + case 49 /* Digit1 */: + case 50 /* Digit2 */: + case 51 /* Digit3 */: + case 52 /* Digit4 */: + case 53 /* Digit5 */: + case 54 /* Digit6 */: + case 55 /* Digit7 */: + case 56 /* Digit8 */: + case 57 /* Digit9 */: + case 101 /* LowerE */: + case 69 /* UpperE */: { + value += fromCharCode(c); + c = bytes[++i]; + continue; + } + } + break; + } + value = +value; + if (isNaN(value)) { + throwSyntaxError(bytes, --index, "Invalid number"); + } + break; + } + // String begin + case 34 /* Quote */: { + value = ""; + while (true) { + if (i >= length) { + throwSyntaxError(bytes, length); + } + c = bytes[i++]; + if (c === 34 /* Quote */) { + break; + } else if (c === 92 /* Backslash */) { + switch (bytes[i++]) { + // Normal escape sequence + case 34 /* Quote */: + value += '"'; + break; + case 47 /* Slash */: + value += "/"; + break; + case 92 /* Backslash */: + value += "\\"; + break; + case 98 /* LowerB */: + value += "\b"; + break; + case 102 /* LowerF */: + value += "\f"; + break; + case 110 /* LowerN */: + value += "\n"; + break; + case 114 /* LowerR */: + value += "\r"; + break; + case 116 /* LowerT */: + value += " "; + break; + // Unicode escape sequence + case 117 /* LowerU */: { + let code = 0; + for (let j = 0; j < 4; j++) { + c = bytes[i++]; + code <<= 4; + if (c >= 48 /* Digit0 */ && c <= 57 /* Digit9 */) code |= c - 48 /* Digit0 */; + else if (c >= 97 /* LowerA */ && c <= 102 /* LowerF */) code |= c + (10 - 97 /* LowerA */); + else if (c >= 65 /* UpperA */ && c <= 70 /* UpperF */) code |= c + (10 - 65 /* UpperA */); + else throwSyntaxError(bytes, --i); + } + value += fromCharCode(code); + break; + } + // Invalid escape sequence + default: + throwSyntaxError(bytes, --i); + break; + } + } else if (c <= 127) { + value += fromCharCode(c); + } else if ((c & 224) === 192) { + value += fromCharCode((c & 31) << 6 | bytes[i++] & 63); + } else if ((c & 240) === 224) { + value += fromCharCode((c & 15) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63); + } else if ((c & 248) == 240) { + let codePoint = (c & 7) << 18 | (bytes[i++] & 63) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63; + if (codePoint > 65535) { + codePoint -= 65536; + value += fromCharCode(codePoint >> 10 & 1023 | 55296); + codePoint = 56320 | codePoint & 1023; + } + value += fromCharCode(codePoint); + } + } + value[0]; + break; + } + // Array begin + case 91 /* OpenBracket */: { + value = []; + propertyStack.push(property); + objectStack.push(object); + stateStack.push(state); + property = null; + object = value; + state = 1 /* Array */; + continue; + } + // Object begin + case 123 /* OpenBrace */: { + value = {}; + propertyStack.push(property); + objectStack.push(object); + stateStack.push(state); + property = null; + object = value; + state = 2 /* Object */; + continue; + } + // Array end + case 93 /* CloseBracket */: { + if (state !== 1 /* Array */) { + throwSyntaxError(bytes, --i); + } + value = object; + property = propertyStack.pop(); + object = objectStack.pop(); + state = stateStack.pop(); + break; + } + // Object end + case 125 /* CloseBrace */: { + if (state !== 2 /* Object */) { + throwSyntaxError(bytes, --i); + } + value = object; + property = propertyStack.pop(); + object = objectStack.pop(); + state = stateStack.pop(); + break; + } + default: { + throwSyntaxError(bytes, --i); + } + } + c = bytes[i]; + while (c <= 32 /* Space */) { + c = bytes[++i]; + } + switch (state) { + case 0 /* TopLevel */: { + if (i === length) { + return value; + } + break; + } + case 1 /* Array */: { + object.push(value); + if (c === 44 /* Comma */) { + i++; + continue; + } + if (c === 93 /* CloseBracket */) { + continue; + } + break; + } + case 2 /* Object */: { + if (property === null) { + property = value; + if (c === 58 /* Colon */) { + i++; + continue; + } + } else { + object[property] = value; + property = null; + if (c === 44 /* Comma */) { + i++; + continue; + } + if (c === 125 /* CloseBrace */) { + continue; + } + } + break; + } + } + break; + } + throwSyntaxError(bytes, i); +} + +// lib/shared/common.ts +var quote = JSON.stringify; +var buildLogLevelDefault = "warning"; +var transformLogLevelDefault = "silent"; +function validateAndJoinStringArray(values, what) { + const toJoin = []; + for (const value of values) { + validateStringValue(value, what); + if (value.indexOf(",") >= 0) throw new Error(`Invalid ${what}: ${value}`); + toJoin.push(value); + } + return toJoin.join(","); +} +var canBeAnything = () => null; +var mustBeBoolean = (value) => typeof value === "boolean" ? null : "a boolean"; +var mustBeString = (value) => typeof value === "string" ? null : "a string"; +var mustBeRegExp = (value) => value instanceof RegExp ? null : "a RegExp object"; +var mustBeInteger = (value) => typeof value === "number" && value === (value | 0) ? null : "an integer"; +var mustBeValidPortNumber = (value) => typeof value === "number" && value === (value | 0) && value >= 0 && value <= 65535 ? null : "a valid port number"; +var mustBeFunction = (value) => typeof value === "function" ? null : "a function"; +var mustBeArray = (value) => Array.isArray(value) ? null : "an array"; +var mustBeArrayOfStrings = (value) => Array.isArray(value) && value.every((x) => typeof x === "string") ? null : "an array of strings"; +var mustBeObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? null : "an object"; +var mustBeEntryPoints = (value) => typeof value === "object" && value !== null ? null : "an array or an object"; +var mustBeWebAssemblyModule = (value) => value instanceof WebAssembly.Module ? null : "a WebAssembly.Module"; +var mustBeObjectOrNull = (value) => typeof value === "object" && !Array.isArray(value) ? null : "an object or null"; +var mustBeStringOrBoolean = (value) => typeof value === "string" || typeof value === "boolean" ? null : "a string or a boolean"; +var mustBeStringOrObject = (value) => typeof value === "string" || typeof value === "object" && value !== null && !Array.isArray(value) ? null : "a string or an object"; +var mustBeStringOrArrayOfStrings = (value) => typeof value === "string" || Array.isArray(value) && value.every((x) => typeof x === "string") ? null : "a string or an array of strings"; +var mustBeStringOrUint8Array = (value) => typeof value === "string" || value instanceof Uint8Array ? null : "a string or a Uint8Array"; +var mustBeStringOrURL = (value) => typeof value === "string" || value instanceof URL ? null : "a string or a URL"; +function getFlag(object, keys, key, mustBeFn) { + let value = object[key]; + keys[key + ""] = true; + if (value === void 0) return void 0; + let mustBe = mustBeFn(value); + if (mustBe !== null) throw new Error(`${quote(key)} must be ${mustBe}`); + return value; +} +function checkForInvalidFlags(object, keys, where) { + for (let key in object) { + if (!(key in keys)) { + throw new Error(`Invalid option ${where}: ${quote(key)}`); + } + } +} +function validateInitializeOptions(options) { + let keys = /* @__PURE__ */ Object.create(null); + let wasmURL = getFlag(options, keys, "wasmURL", mustBeStringOrURL); + let wasmModule = getFlag(options, keys, "wasmModule", mustBeWebAssemblyModule); + let worker = getFlag(options, keys, "worker", mustBeBoolean); + checkForInvalidFlags(options, keys, "in initialize() call"); + return { + wasmURL, + wasmModule, + worker + }; +} +function validateMangleCache(mangleCache) { + let validated; + if (mangleCache !== void 0) { + validated = /* @__PURE__ */ Object.create(null); + for (let key in mangleCache) { + let value = mangleCache[key]; + if (typeof value === "string" || value === false) { + validated[key] = value; + } else { + throw new Error(`Expected ${quote(key)} in mangle cache to map to either a string or false`); + } + } + } + return validated; +} +function pushLogFlags(flags, options, keys, isTTY2, logLevelDefault) { + let color = getFlag(options, keys, "color", mustBeBoolean); + let logLevel = getFlag(options, keys, "logLevel", mustBeString); + let logLimit = getFlag(options, keys, "logLimit", mustBeInteger); + if (color !== void 0) flags.push(`--color=${color}`); + else if (isTTY2) flags.push(`--color=true`); + flags.push(`--log-level=${logLevel || logLevelDefault}`); + flags.push(`--log-limit=${logLimit || 0}`); +} +function validateStringValue(value, what, key) { + if (typeof value !== "string") { + throw new Error(`Expected value for ${what}${key !== void 0 ? " " + quote(key) : ""} to be a string, got ${typeof value} instead`); + } + return value; +} +function pushCommonFlags(flags, options, keys) { + let legalComments = getFlag(options, keys, "legalComments", mustBeString); + let sourceRoot = getFlag(options, keys, "sourceRoot", mustBeString); + let sourcesContent = getFlag(options, keys, "sourcesContent", mustBeBoolean); + let target = getFlag(options, keys, "target", mustBeStringOrArrayOfStrings); + let format = getFlag(options, keys, "format", mustBeString); + let globalName = getFlag(options, keys, "globalName", mustBeString); + let mangleProps = getFlag(options, keys, "mangleProps", mustBeRegExp); + let reserveProps = getFlag(options, keys, "reserveProps", mustBeRegExp); + let mangleQuoted = getFlag(options, keys, "mangleQuoted", mustBeBoolean); + let minify = getFlag(options, keys, "minify", mustBeBoolean); + let minifySyntax = getFlag(options, keys, "minifySyntax", mustBeBoolean); + let minifyWhitespace = getFlag(options, keys, "minifyWhitespace", mustBeBoolean); + let minifyIdentifiers = getFlag(options, keys, "minifyIdentifiers", mustBeBoolean); + let lineLimit = getFlag(options, keys, "lineLimit", mustBeInteger); + let drop = getFlag(options, keys, "drop", mustBeArrayOfStrings); + let dropLabels = getFlag(options, keys, "dropLabels", mustBeArrayOfStrings); + let charset = getFlag(options, keys, "charset", mustBeString); + let treeShaking = getFlag(options, keys, "treeShaking", mustBeBoolean); + let ignoreAnnotations = getFlag(options, keys, "ignoreAnnotations", mustBeBoolean); + let jsx = getFlag(options, keys, "jsx", mustBeString); + let jsxFactory = getFlag(options, keys, "jsxFactory", mustBeString); + let jsxFragment = getFlag(options, keys, "jsxFragment", mustBeString); + let jsxImportSource = getFlag(options, keys, "jsxImportSource", mustBeString); + let jsxDev = getFlag(options, keys, "jsxDev", mustBeBoolean); + let jsxSideEffects = getFlag(options, keys, "jsxSideEffects", mustBeBoolean); + let define = getFlag(options, keys, "define", mustBeObject); + let logOverride = getFlag(options, keys, "logOverride", mustBeObject); + let supported = getFlag(options, keys, "supported", mustBeObject); + let pure = getFlag(options, keys, "pure", mustBeArrayOfStrings); + let keepNames = getFlag(options, keys, "keepNames", mustBeBoolean); + let platform = getFlag(options, keys, "platform", mustBeString); + let tsconfigRaw = getFlag(options, keys, "tsconfigRaw", mustBeStringOrObject); + let absPaths = getFlag(options, keys, "absPaths", mustBeArrayOfStrings); + if (legalComments) flags.push(`--legal-comments=${legalComments}`); + if (sourceRoot !== void 0) flags.push(`--source-root=${sourceRoot}`); + if (sourcesContent !== void 0) flags.push(`--sources-content=${sourcesContent}`); + if (target) flags.push(`--target=${validateAndJoinStringArray(Array.isArray(target) ? target : [target], "target")}`); + if (format) flags.push(`--format=${format}`); + if (globalName) flags.push(`--global-name=${globalName}`); + if (platform) flags.push(`--platform=${platform}`); + if (tsconfigRaw) flags.push(`--tsconfig-raw=${typeof tsconfigRaw === "string" ? tsconfigRaw : JSON.stringify(tsconfigRaw)}`); + if (minify) flags.push("--minify"); + if (minifySyntax) flags.push("--minify-syntax"); + if (minifyWhitespace) flags.push("--minify-whitespace"); + if (minifyIdentifiers) flags.push("--minify-identifiers"); + if (lineLimit) flags.push(`--line-limit=${lineLimit}`); + if (charset) flags.push(`--charset=${charset}`); + if (treeShaking !== void 0) flags.push(`--tree-shaking=${treeShaking}`); + if (ignoreAnnotations) flags.push(`--ignore-annotations`); + if (drop) for (let what of drop) flags.push(`--drop:${validateStringValue(what, "drop")}`); + if (dropLabels) flags.push(`--drop-labels=${validateAndJoinStringArray(dropLabels, "drop label")}`); + if (absPaths) flags.push(`--abs-paths=${validateAndJoinStringArray(absPaths, "abs paths")}`); + if (mangleProps) flags.push(`--mangle-props=${jsRegExpToGoRegExp(mangleProps)}`); + if (reserveProps) flags.push(`--reserve-props=${jsRegExpToGoRegExp(reserveProps)}`); + if (mangleQuoted !== void 0) flags.push(`--mangle-quoted=${mangleQuoted}`); + if (jsx) flags.push(`--jsx=${jsx}`); + if (jsxFactory) flags.push(`--jsx-factory=${jsxFactory}`); + if (jsxFragment) flags.push(`--jsx-fragment=${jsxFragment}`); + if (jsxImportSource) flags.push(`--jsx-import-source=${jsxImportSource}`); + if (jsxDev) flags.push(`--jsx-dev`); + if (jsxSideEffects) flags.push(`--jsx-side-effects`); + if (define) { + for (let key in define) { + if (key.indexOf("=") >= 0) throw new Error(`Invalid define: ${key}`); + flags.push(`--define:${key}=${validateStringValue(define[key], "define", key)}`); + } + } + if (logOverride) { + for (let key in logOverride) { + if (key.indexOf("=") >= 0) throw new Error(`Invalid log override: ${key}`); + flags.push(`--log-override:${key}=${validateStringValue(logOverride[key], "log override", key)}`); + } + } + if (supported) { + for (let key in supported) { + if (key.indexOf("=") >= 0) throw new Error(`Invalid supported: ${key}`); + const value = supported[key]; + if (typeof value !== "boolean") throw new Error(`Expected value for supported ${quote(key)} to be a boolean, got ${typeof value} instead`); + flags.push(`--supported:${key}=${value}`); + } + } + if (pure) for (let fn of pure) flags.push(`--pure:${validateStringValue(fn, "pure")}`); + if (keepNames) flags.push(`--keep-names`); +} +function flagsForBuildOptions(callName, options, isTTY2, logLevelDefault, writeDefault) { + var _a2; + let flags = []; + let entries = []; + let keys = /* @__PURE__ */ Object.create(null); + let stdinContents = null; + let stdinResolveDir = null; + pushLogFlags(flags, options, keys, isTTY2, logLevelDefault); + pushCommonFlags(flags, options, keys); + let sourcemap = getFlag(options, keys, "sourcemap", mustBeStringOrBoolean); + let bundle = getFlag(options, keys, "bundle", mustBeBoolean); + let splitting = getFlag(options, keys, "splitting", mustBeBoolean); + let preserveSymlinks = getFlag(options, keys, "preserveSymlinks", mustBeBoolean); + let metafile = getFlag(options, keys, "metafile", mustBeBoolean); + let outfile = getFlag(options, keys, "outfile", mustBeString); + let outdir = getFlag(options, keys, "outdir", mustBeString); + let outbase = getFlag(options, keys, "outbase", mustBeString); + let tsconfig = getFlag(options, keys, "tsconfig", mustBeString); + let resolveExtensions = getFlag(options, keys, "resolveExtensions", mustBeArrayOfStrings); + let nodePathsInput = getFlag(options, keys, "nodePaths", mustBeArrayOfStrings); + let mainFields = getFlag(options, keys, "mainFields", mustBeArrayOfStrings); + let conditions = getFlag(options, keys, "conditions", mustBeArrayOfStrings); + let external = getFlag(options, keys, "external", mustBeArrayOfStrings); + let packages = getFlag(options, keys, "packages", mustBeString); + let alias = getFlag(options, keys, "alias", mustBeObject); + let loader = getFlag(options, keys, "loader", mustBeObject); + let outExtension = getFlag(options, keys, "outExtension", mustBeObject); + let publicPath = getFlag(options, keys, "publicPath", mustBeString); + let entryNames = getFlag(options, keys, "entryNames", mustBeString); + let chunkNames = getFlag(options, keys, "chunkNames", mustBeString); + let assetNames = getFlag(options, keys, "assetNames", mustBeString); + let inject = getFlag(options, keys, "inject", mustBeArrayOfStrings); + let banner = getFlag(options, keys, "banner", mustBeObject); + let footer = getFlag(options, keys, "footer", mustBeObject); + let entryPoints = getFlag(options, keys, "entryPoints", mustBeEntryPoints); + let absWorkingDir = getFlag(options, keys, "absWorkingDir", mustBeString); + let stdin = getFlag(options, keys, "stdin", mustBeObject); + let write = (_a2 = getFlag(options, keys, "write", mustBeBoolean)) != null ? _a2 : writeDefault; + let allowOverwrite = getFlag(options, keys, "allowOverwrite", mustBeBoolean); + let mangleCache = getFlag(options, keys, "mangleCache", mustBeObject); + keys.plugins = true; + checkForInvalidFlags(options, keys, `in ${callName}() call`); + if (sourcemap) flags.push(`--sourcemap${sourcemap === true ? "" : `=${sourcemap}`}`); + if (bundle) flags.push("--bundle"); + if (allowOverwrite) flags.push("--allow-overwrite"); + if (splitting) flags.push("--splitting"); + if (preserveSymlinks) flags.push("--preserve-symlinks"); + if (metafile) flags.push(`--metafile`); + if (outfile) flags.push(`--outfile=${outfile}`); + if (outdir) flags.push(`--outdir=${outdir}`); + if (outbase) flags.push(`--outbase=${outbase}`); + if (tsconfig) flags.push(`--tsconfig=${tsconfig}`); + if (packages) flags.push(`--packages=${packages}`); + if (resolveExtensions) flags.push(`--resolve-extensions=${validateAndJoinStringArray(resolveExtensions, "resolve extension")}`); + if (publicPath) flags.push(`--public-path=${publicPath}`); + if (entryNames) flags.push(`--entry-names=${entryNames}`); + if (chunkNames) flags.push(`--chunk-names=${chunkNames}`); + if (assetNames) flags.push(`--asset-names=${assetNames}`); + if (mainFields) flags.push(`--main-fields=${validateAndJoinStringArray(mainFields, "main field")}`); + if (conditions) flags.push(`--conditions=${validateAndJoinStringArray(conditions, "condition")}`); + if (external) for (let name of external) flags.push(`--external:${validateStringValue(name, "external")}`); + if (alias) { + for (let old in alias) { + if (old.indexOf("=") >= 0) throw new Error(`Invalid package name in alias: ${old}`); + flags.push(`--alias:${old}=${validateStringValue(alias[old], "alias", old)}`); + } + } + if (banner) { + for (let type in banner) { + if (type.indexOf("=") >= 0) throw new Error(`Invalid banner file type: ${type}`); + flags.push(`--banner:${type}=${validateStringValue(banner[type], "banner", type)}`); + } + } + if (footer) { + for (let type in footer) { + if (type.indexOf("=") >= 0) throw new Error(`Invalid footer file type: ${type}`); + flags.push(`--footer:${type}=${validateStringValue(footer[type], "footer", type)}`); + } + } + if (inject) for (let path3 of inject) flags.push(`--inject:${validateStringValue(path3, "inject")}`); + if (loader) { + for (let ext in loader) { + if (ext.indexOf("=") >= 0) throw new Error(`Invalid loader extension: ${ext}`); + flags.push(`--loader:${ext}=${validateStringValue(loader[ext], "loader", ext)}`); + } + } + if (outExtension) { + for (let ext in outExtension) { + if (ext.indexOf("=") >= 0) throw new Error(`Invalid out extension: ${ext}`); + flags.push(`--out-extension:${ext}=${validateStringValue(outExtension[ext], "out extension", ext)}`); + } + } + if (entryPoints) { + if (Array.isArray(entryPoints)) { + for (let i = 0, n = entryPoints.length; i < n; i++) { + let entryPoint = entryPoints[i]; + if (typeof entryPoint === "object" && entryPoint !== null) { + let entryPointKeys = /* @__PURE__ */ Object.create(null); + let input = getFlag(entryPoint, entryPointKeys, "in", mustBeString); + let output = getFlag(entryPoint, entryPointKeys, "out", mustBeString); + checkForInvalidFlags(entryPoint, entryPointKeys, "in entry point at index " + i); + if (input === void 0) throw new Error('Missing property "in" for entry point at index ' + i); + if (output === void 0) throw new Error('Missing property "out" for entry point at index ' + i); + entries.push([output, input]); + } else { + entries.push(["", validateStringValue(entryPoint, "entry point at index " + i)]); + } + } + } else { + for (let key in entryPoints) { + entries.push([key, validateStringValue(entryPoints[key], "entry point", key)]); + } + } + } + if (stdin) { + let stdinKeys = /* @__PURE__ */ Object.create(null); + let contents = getFlag(stdin, stdinKeys, "contents", mustBeStringOrUint8Array); + let resolveDir = getFlag(stdin, stdinKeys, "resolveDir", mustBeString); + let sourcefile = getFlag(stdin, stdinKeys, "sourcefile", mustBeString); + let loader2 = getFlag(stdin, stdinKeys, "loader", mustBeString); + checkForInvalidFlags(stdin, stdinKeys, 'in "stdin" object'); + if (sourcefile) flags.push(`--sourcefile=${sourcefile}`); + if (loader2) flags.push(`--loader=${loader2}`); + if (resolveDir) stdinResolveDir = resolveDir; + if (typeof contents === "string") stdinContents = encodeUTF8(contents); + else if (contents instanceof Uint8Array) stdinContents = contents; + } + let nodePaths = []; + if (nodePathsInput) { + for (let value of nodePathsInput) { + value += ""; + nodePaths.push(value); + } + } + return { + entries, + flags, + write, + stdinContents, + stdinResolveDir, + absWorkingDir, + nodePaths, + mangleCache: validateMangleCache(mangleCache) + }; +} +function flagsForTransformOptions(callName, options, isTTY2, logLevelDefault) { + let flags = []; + let keys = /* @__PURE__ */ Object.create(null); + pushLogFlags(flags, options, keys, isTTY2, logLevelDefault); + pushCommonFlags(flags, options, keys); + let sourcemap = getFlag(options, keys, "sourcemap", mustBeStringOrBoolean); + let sourcefile = getFlag(options, keys, "sourcefile", mustBeString); + let loader = getFlag(options, keys, "loader", mustBeString); + let banner = getFlag(options, keys, "banner", mustBeString); + let footer = getFlag(options, keys, "footer", mustBeString); + let mangleCache = getFlag(options, keys, "mangleCache", mustBeObject); + checkForInvalidFlags(options, keys, `in ${callName}() call`); + if (sourcemap) flags.push(`--sourcemap=${sourcemap === true ? "external" : sourcemap}`); + if (sourcefile) flags.push(`--sourcefile=${sourcefile}`); + if (loader) flags.push(`--loader=${loader}`); + if (banner) flags.push(`--banner=${banner}`); + if (footer) flags.push(`--footer=${footer}`); + return { + flags, + mangleCache: validateMangleCache(mangleCache) + }; +} +function createChannel(streamIn) { + const requestCallbacksByKey = {}; + const closeData = { didClose: false, reason: "" }; + let responseCallbacks = {}; + let nextRequestID = 0; + let nextBuildKey = 0; + let stdout = new Uint8Array(16 * 1024); + let stdoutUsed = 0; + let readFromStdout = (chunk) => { + let limit = stdoutUsed + chunk.length; + if (limit > stdout.length) { + let swap = new Uint8Array(limit * 2); + swap.set(stdout); + stdout = swap; + } + stdout.set(chunk, stdoutUsed); + stdoutUsed += chunk.length; + let offset = 0; + while (offset + 4 <= stdoutUsed) { + let length = readUInt32LE(stdout, offset); + if (offset + 4 + length > stdoutUsed) { + break; + } + offset += 4; + handleIncomingPacket(stdout.subarray(offset, offset + length)); + offset += length; + } + if (offset > 0) { + stdout.copyWithin(0, offset, stdoutUsed); + stdoutUsed -= offset; + } + }; + let afterClose = (error) => { + closeData.didClose = true; + if (error) closeData.reason = ": " + (error.message || error); + const text = "The service was stopped" + closeData.reason; + for (let id in responseCallbacks) { + responseCallbacks[id](text, null); + } + responseCallbacks = {}; + }; + let sendRequest = (refs, value, callback) => { + if (closeData.didClose) return callback("The service is no longer running" + closeData.reason, null); + let id = nextRequestID++; + responseCallbacks[id] = (error, response) => { + try { + callback(error, response); + } finally { + if (refs) refs.unref(); + } + }; + if (refs) refs.ref(); + streamIn.writeToStdin(encodePacket({ id, isRequest: true, value })); + }; + let sendResponse = (id, value) => { + if (closeData.didClose) throw new Error("The service is no longer running" + closeData.reason); + streamIn.writeToStdin(encodePacket({ id, isRequest: false, value })); + }; + let handleRequest = async (id, request) => { + try { + if (request.command === "ping") { + sendResponse(id, {}); + return; + } + if (typeof request.key === "number") { + const requestCallbacks = requestCallbacksByKey[request.key]; + if (!requestCallbacks) { + return; + } + const callback = requestCallbacks[request.command]; + if (callback) { + await callback(id, request); + return; + } + } + throw new Error(`Invalid command: ` + request.command); + } catch (e) { + const errors = [extractErrorMessageV8(e, streamIn, null, void 0, "")]; + try { + sendResponse(id, { errors }); + } catch { + } + } + }; + let isFirstPacket = true; + let handleIncomingPacket = (bytes) => { + if (isFirstPacket) { + isFirstPacket = false; + let binaryVersion = String.fromCharCode(...bytes); + if (binaryVersion !== "0.28.1") { + throw new Error(`Cannot start service: Host version "${"0.28.1"}" does not match binary version ${quote(binaryVersion)}`); + } + return; + } + let packet = decodePacket(bytes); + if (packet.isRequest) { + handleRequest(packet.id, packet.value); + } else { + let callback = responseCallbacks[packet.id]; + delete responseCallbacks[packet.id]; + if (packet.value.error) callback(packet.value.error, {}); + else callback(null, packet.value); + } + }; + let buildOrContext = ({ callName, refs, options, isTTY: isTTY2, defaultWD: defaultWD2, callback }) => { + let refCount = 0; + const buildKey = nextBuildKey++; + const requestCallbacks = {}; + const buildRefs = { + ref() { + if (++refCount === 1) { + if (refs) refs.ref(); + } + }, + unref() { + if (--refCount === 0) { + delete requestCallbacksByKey[buildKey]; + if (refs) refs.unref(); + } + } + }; + requestCallbacksByKey[buildKey] = requestCallbacks; + buildRefs.ref(); + buildOrContextImpl( + callName, + buildKey, + sendRequest, + sendResponse, + buildRefs, + streamIn, + requestCallbacks, + options, + isTTY2, + defaultWD2, + (err, res) => { + try { + callback(err, res); + } finally { + buildRefs.unref(); + } + } + ); + }; + let transform2 = ({ callName, refs, input, options, isTTY: isTTY2, fs: fs3, callback }) => { + const details = createObjectStash(); + let start = (inputPath) => { + try { + if (typeof input !== "string" && !(input instanceof Uint8Array)) + throw new Error('The input to "transform" must be a string or a Uint8Array'); + let { + flags, + mangleCache + } = flagsForTransformOptions(callName, options, isTTY2, transformLogLevelDefault); + let request = { + command: "transform", + flags, + inputFS: inputPath !== null, + input: inputPath !== null ? encodeUTF8(inputPath) : typeof input === "string" ? encodeUTF8(input) : input + }; + if (mangleCache) request.mangleCache = mangleCache; + sendRequest(refs, request, (error, response) => { + if (error) return callback(new Error(error), null); + let errors = replaceDetailsInMessages(response.errors, details); + let warnings = replaceDetailsInMessages(response.warnings, details); + let outstanding = 1; + let next = () => { + if (--outstanding === 0) { + let result = { + warnings, + code: response.code, + map: response.map, + mangleCache: void 0, + legalComments: void 0 + }; + if ("legalComments" in response) result.legalComments = response == null ? void 0 : response.legalComments; + if (response.mangleCache) result.mangleCache = response == null ? void 0 : response.mangleCache; + callback(null, result); + } + }; + if (errors.length > 0) return callback(failureErrorWithLog("Transform failed", errors, warnings), null); + if (response.codeFS) { + outstanding++; + fs3.readFile(response.code, (err, contents) => { + if (err !== null) { + callback(err, null); + } else { + response.code = contents; + next(); + } + }); + } + if (response.mapFS) { + outstanding++; + fs3.readFile(response.map, (err, contents) => { + if (err !== null) { + callback(err, null); + } else { + response.map = contents; + next(); + } + }); + } + next(); + }); + } catch (e) { + let flags = []; + try { + pushLogFlags(flags, options, {}, isTTY2, transformLogLevelDefault); + } catch { + } + const error = extractErrorMessageV8(e, streamIn, details, void 0, ""); + sendRequest(refs, { command: "error", flags, error }, () => { + error.detail = details.load(error.detail); + callback(failureErrorWithLog("Transform failed", [error], []), null); + }); + } + }; + if ((typeof input === "string" || input instanceof Uint8Array) && input.length > 1024 * 1024) { + let next = start; + start = () => fs3.writeFile(input, next); + } + start(null); + }; + let formatMessages2 = ({ callName, refs, messages, options, callback }) => { + if (!options) throw new Error(`Missing second argument in ${callName}() call`); + let keys = {}; + let kind = getFlag(options, keys, "kind", mustBeString); + let color = getFlag(options, keys, "color", mustBeBoolean); + let terminalWidth = getFlag(options, keys, "terminalWidth", mustBeInteger); + checkForInvalidFlags(options, keys, `in ${callName}() call`); + if (kind === void 0) throw new Error(`Missing "kind" in ${callName}() call`); + if (kind !== "error" && kind !== "warning") throw new Error(`Expected "kind" to be "error" or "warning" in ${callName}() call`); + let request = { + command: "format-msgs", + messages: sanitizeMessages(messages, "messages", null, "", terminalWidth), + isWarning: kind === "warning" + }; + if (color !== void 0) request.color = color; + if (terminalWidth !== void 0) request.terminalWidth = terminalWidth; + sendRequest(refs, request, (error, response) => { + if (error) return callback(new Error(error), null); + callback(null, response.messages); + }); + }; + let analyzeMetafile2 = ({ callName, refs, metafile, options, callback }) => { + if (options === void 0) options = {}; + let keys = {}; + let color = getFlag(options, keys, "color", mustBeBoolean); + let verbose = getFlag(options, keys, "verbose", mustBeBoolean); + checkForInvalidFlags(options, keys, `in ${callName}() call`); + let request = { + command: "analyze-metafile", + metafile + }; + if (color !== void 0) request.color = color; + if (verbose !== void 0) request.verbose = verbose; + sendRequest(refs, request, (error, response) => { + if (error) return callback(new Error(error), null); + callback(null, response.result); + }); + }; + return { + readFromStdout, + afterClose, + service: { + buildOrContext, + transform: transform2, + formatMessages: formatMessages2, + analyzeMetafile: analyzeMetafile2 + } + }; +} +function buildOrContextImpl(callName, buildKey, sendRequest, sendResponse, refs, streamIn, requestCallbacks, options, isTTY2, defaultWD2, callback) { + const details = createObjectStash(); + const isContext = callName === "context"; + const handleError = (e, pluginName) => { + const flags = []; + try { + pushLogFlags(flags, options, {}, isTTY2, buildLogLevelDefault); + } catch { + } + const message = extractErrorMessageV8(e, streamIn, details, void 0, pluginName); + sendRequest(refs, { command: "error", flags, error: message }, () => { + message.detail = details.load(message.detail); + callback(failureErrorWithLog(isContext ? "Context failed" : "Build failed", [message], []), null); + }); + }; + let plugins; + if (typeof options === "object") { + const value = options.plugins; + if (value !== void 0) { + if (!Array.isArray(value)) return handleError(new Error(`"plugins" must be an array`), ""); + plugins = value; + } + } + if (plugins && plugins.length > 0) { + if (streamIn.isSync) return handleError(new Error("Cannot use plugins in synchronous API calls"), ""); + handlePlugins( + buildKey, + sendRequest, + sendResponse, + refs, + streamIn, + requestCallbacks, + options, + plugins, + details + ).then( + (result) => { + if (!result.ok) return handleError(result.error, result.pluginName); + try { + buildOrContextContinue(result.requestPlugins, result.runOnEndCallbacks, result.scheduleOnDisposeCallbacks); + } catch (e) { + handleError(e, ""); + } + }, + (e) => handleError(e, "") + ); + return; + } + try { + buildOrContextContinue(null, (result, done) => done([], []), () => { + }); + } catch (e) { + handleError(e, ""); + } + function buildOrContextContinue(requestPlugins, runOnEndCallbacks, scheduleOnDisposeCallbacks) { + const writeDefault = streamIn.hasFS; + const { + entries, + flags, + write, + stdinContents, + stdinResolveDir, + absWorkingDir, + nodePaths, + mangleCache + } = flagsForBuildOptions(callName, options, isTTY2, buildLogLevelDefault, writeDefault); + if (write && !streamIn.hasFS) throw new Error(`The "write" option is unavailable in this environment`); + const request = { + command: "build", + key: buildKey, + entries, + flags, + write, + stdinContents, + stdinResolveDir, + absWorkingDir: absWorkingDir || defaultWD2, + nodePaths, + context: isContext + }; + if (requestPlugins) request.plugins = requestPlugins; + if (mangleCache) request.mangleCache = mangleCache; + const buildResponseToResult = (response, callback2) => { + const result = { + errors: replaceDetailsInMessages(response.errors, details), + warnings: replaceDetailsInMessages(response.warnings, details), + outputFiles: void 0, + metafile: void 0, + mangleCache: void 0 + }; + const originalErrors = result.errors.slice(); + const originalWarnings = result.warnings.slice(); + if (response.outputFiles) result.outputFiles = response.outputFiles.map(convertOutputFiles); + if (response.metafile && response.metafile.length) result.metafile = parseJSON(response.metafile); + if (response.mangleCache) result.mangleCache = response.mangleCache; + if (response.writeToStdout !== void 0) console.log(decodeUTF8(response.writeToStdout).replace(/\n$/, "")); + runOnEndCallbacks(result, (onEndErrors, onEndWarnings) => { + if (originalErrors.length > 0 || onEndErrors.length > 0) { + const error = failureErrorWithLog("Build failed", originalErrors.concat(onEndErrors), originalWarnings.concat(onEndWarnings)); + return callback2(error, null, onEndErrors, onEndWarnings); + } + callback2(null, result, onEndErrors, onEndWarnings); + }); + }; + let latestResultPromise; + let provideLatestResult; + if (isContext) + requestCallbacks["on-end"] = (id, request2) => new Promise((resolve) => { + buildResponseToResult(request2, (err, result, onEndErrors, onEndWarnings) => { + const response = { + errors: onEndErrors, + warnings: onEndWarnings + }; + if (provideLatestResult) provideLatestResult(err, result); + latestResultPromise = void 0; + provideLatestResult = void 0; + sendResponse(id, response); + resolve(); + }); + }); + sendRequest(refs, request, (error, response) => { + if (error) return callback(new Error(error), null); + if (!isContext) { + return buildResponseToResult(response, (err, res) => { + scheduleOnDisposeCallbacks(); + return callback(err, res); + }); + } + if (response.errors.length > 0) { + return callback(failureErrorWithLog("Context failed", response.errors, response.warnings), null); + } + let didDispose = false; + const result = { + rebuild: () => { + if (!latestResultPromise) latestResultPromise = new Promise((resolve, reject) => { + let settlePromise; + provideLatestResult = (err, result2) => { + if (!settlePromise) settlePromise = () => err ? reject(err) : resolve(result2); + }; + const triggerAnotherBuild = () => { + const request2 = { + command: "rebuild", + key: buildKey + }; + sendRequest(refs, request2, (error2, response2) => { + if (error2) { + reject(new Error(error2)); + } else if (settlePromise) { + settlePromise(); + } else { + triggerAnotherBuild(); + } + }); + }; + triggerAnotherBuild(); + }); + return latestResultPromise; + }, + watch: (options2 = {}) => new Promise((resolve, reject) => { + if (!streamIn.hasFS) throw new Error(`Cannot use the "watch" API in this environment`); + const keys = {}; + const delay = getFlag(options2, keys, "delay", mustBeInteger); + checkForInvalidFlags(options2, keys, `in watch() call`); + const request2 = { + command: "watch", + key: buildKey + }; + if (delay) request2.delay = delay; + sendRequest(refs, request2, (error2) => { + if (error2) reject(new Error(error2)); + else resolve(void 0); + }); + }), + serve: (options2 = {}) => new Promise((resolve, reject) => { + if (!streamIn.hasFS) throw new Error(`Cannot use the "serve" API in this environment`); + const keys = {}; + const port = getFlag(options2, keys, "port", mustBeValidPortNumber); + const host = getFlag(options2, keys, "host", mustBeString); + const servedir = getFlag(options2, keys, "servedir", mustBeString); + const keyfile = getFlag(options2, keys, "keyfile", mustBeString); + const certfile = getFlag(options2, keys, "certfile", mustBeString); + const fallback = getFlag(options2, keys, "fallback", mustBeString); + const cors = getFlag(options2, keys, "cors", mustBeObject); + const onRequest = getFlag(options2, keys, "onRequest", mustBeFunction); + checkForInvalidFlags(options2, keys, `in serve() call`); + const request2 = { + command: "serve", + key: buildKey, + onRequest: !!onRequest + }; + if (port !== void 0) request2.port = port; + if (host !== void 0) request2.host = host; + if (servedir !== void 0) request2.servedir = servedir; + if (keyfile !== void 0) request2.keyfile = keyfile; + if (certfile !== void 0) request2.certfile = certfile; + if (fallback !== void 0) request2.fallback = fallback; + if (cors) { + const corsKeys = {}; + const origin = getFlag(cors, corsKeys, "origin", mustBeStringOrArrayOfStrings); + checkForInvalidFlags(cors, corsKeys, `on "cors" object`); + if (Array.isArray(origin)) request2.corsOrigin = origin; + else if (origin !== void 0) request2.corsOrigin = [origin]; + } + sendRequest(refs, request2, (error2, response2) => { + if (error2) return reject(new Error(error2)); + if (onRequest) { + requestCallbacks["serve-request"] = (id, request3) => { + onRequest(request3.args); + sendResponse(id, {}); + }; + } + resolve(response2); + }); + }), + cancel: () => new Promise((resolve) => { + if (didDispose) return resolve(); + const request2 = { + command: "cancel", + key: buildKey + }; + sendRequest(refs, request2, () => { + resolve(); + }); + }), + dispose: () => new Promise((resolve) => { + if (didDispose) return resolve(); + didDispose = true; + const request2 = { + command: "dispose", + key: buildKey + }; + sendRequest(refs, request2, () => { + resolve(); + scheduleOnDisposeCallbacks(); + refs.unref(); + }); + }) + }; + refs.ref(); + callback(null, result); + }); + } +} +var handlePlugins = async (buildKey, sendRequest, sendResponse, refs, streamIn, requestCallbacks, initialOptions, plugins, details) => { + let onStartCallbacks = []; + let onEndCallbacks = []; + let onResolveCallbacks = {}; + let onLoadCallbacks = {}; + let onDisposeCallbacks = []; + let nextCallbackID = 0; + let i = 0; + let requestPlugins = []; + let isSetupDone = false; + plugins = [...plugins]; + for (let item of plugins) { + let keys = {}; + if (typeof item !== "object") throw new Error(`Plugin at index ${i} must be an object`); + const name = getFlag(item, keys, "name", mustBeString); + if (typeof name !== "string" || name === "") throw new Error(`Plugin at index ${i} is missing a name`); + try { + let setup = getFlag(item, keys, "setup", mustBeFunction); + if (typeof setup !== "function") throw new Error(`Plugin is missing a setup function`); + checkForInvalidFlags(item, keys, `on plugin ${quote(name)}`); + let plugin = { + name, + onStart: false, + onEnd: false, + onResolve: [], + onLoad: [] + }; + i++; + let resolve = (path3, options = {}) => { + if (!isSetupDone) throw new Error('Cannot call "resolve" before plugin setup has completed'); + if (typeof path3 !== "string") throw new Error(`The path to resolve must be a string`); + let keys2 = /* @__PURE__ */ Object.create(null); + let pluginName = getFlag(options, keys2, "pluginName", mustBeString); + let importer = getFlag(options, keys2, "importer", mustBeString); + let namespace = getFlag(options, keys2, "namespace", mustBeString); + let resolveDir = getFlag(options, keys2, "resolveDir", mustBeString); + let kind = getFlag(options, keys2, "kind", mustBeString); + let pluginData = getFlag(options, keys2, "pluginData", canBeAnything); + let importAttributes = getFlag(options, keys2, "with", mustBeObject); + checkForInvalidFlags(options, keys2, "in resolve() call"); + return new Promise((resolve2, reject) => { + const request = { + command: "resolve", + path: path3, + key: buildKey, + pluginName: name + }; + if (pluginName != null) request.pluginName = pluginName; + if (importer != null) request.importer = importer; + if (namespace != null) request.namespace = namespace; + if (resolveDir != null) request.resolveDir = resolveDir; + if (kind != null) request.kind = kind; + else throw new Error(`Must specify "kind" when calling "resolve"`); + if (pluginData != null) request.pluginData = details.store(pluginData); + if (importAttributes != null) request.with = sanitizeStringMap(importAttributes, "with"); + sendRequest(refs, request, (error, response) => { + if (error !== null) reject(new Error(error)); + else resolve2({ + errors: replaceDetailsInMessages(response.errors, details), + warnings: replaceDetailsInMessages(response.warnings, details), + path: response.path, + external: response.external, + sideEffects: response.sideEffects, + namespace: response.namespace, + suffix: response.suffix, + pluginData: details.load(response.pluginData) + }); + }); + }); + }; + let promise = setup({ + initialOptions, + resolve, + onStart(callback) { + let registeredText = `This error came from the "onStart" callback registered here:`; + let registeredNote = extractCallerV8(new Error(registeredText), streamIn, "onStart"); + onStartCallbacks.push({ name, callback, note: registeredNote }); + plugin.onStart = true; + }, + onEnd(callback) { + let registeredText = `This error came from the "onEnd" callback registered here:`; + let registeredNote = extractCallerV8(new Error(registeredText), streamIn, "onEnd"); + onEndCallbacks.push({ name, callback, note: registeredNote }); + plugin.onEnd = true; + }, + onResolve(options, callback) { + let registeredText = `This error came from the "onResolve" callback registered here:`; + let registeredNote = extractCallerV8(new Error(registeredText), streamIn, "onResolve"); + let keys2 = {}; + let filter = getFlag(options, keys2, "filter", mustBeRegExp); + let namespace = getFlag(options, keys2, "namespace", mustBeString); + checkForInvalidFlags(options, keys2, `in onResolve() call for plugin ${quote(name)}`); + if (filter == null) throw new Error(`onResolve() call is missing a filter`); + let id = nextCallbackID++; + onResolveCallbacks[id] = { name, callback, note: registeredNote }; + plugin.onResolve.push({ id, filter: jsRegExpToGoRegExp(filter), namespace: namespace || "" }); + }, + onLoad(options, callback) { + let registeredText = `This error came from the "onLoad" callback registered here:`; + let registeredNote = extractCallerV8(new Error(registeredText), streamIn, "onLoad"); + let keys2 = {}; + let filter = getFlag(options, keys2, "filter", mustBeRegExp); + let namespace = getFlag(options, keys2, "namespace", mustBeString); + checkForInvalidFlags(options, keys2, `in onLoad() call for plugin ${quote(name)}`); + if (filter == null) throw new Error(`onLoad() call is missing a filter`); + let id = nextCallbackID++; + onLoadCallbacks[id] = { name, callback, note: registeredNote }; + plugin.onLoad.push({ id, filter: jsRegExpToGoRegExp(filter), namespace: namespace || "" }); + }, + onDispose(callback) { + onDisposeCallbacks.push(callback); + }, + esbuild: streamIn.esbuild + }); + if (promise) await promise; + requestPlugins.push(plugin); + } catch (e) { + return { ok: false, error: e, pluginName: name }; + } + } + requestCallbacks["on-start"] = async (id, request) => { + details.clear(); + let response = { errors: [], warnings: [] }; + await Promise.all(onStartCallbacks.map(async ({ name, callback, note }) => { + try { + let result = await callback(); + if (result != null) { + if (typeof result !== "object") throw new Error(`Expected onStart() callback in plugin ${quote(name)} to return an object`); + let keys = {}; + let errors = getFlag(result, keys, "errors", mustBeArray); + let warnings = getFlag(result, keys, "warnings", mustBeArray); + checkForInvalidFlags(result, keys, `from onStart() callback in plugin ${quote(name)}`); + if (errors != null) response.errors.push(...sanitizeMessages(errors, "errors", details, name, void 0)); + if (warnings != null) response.warnings.push(...sanitizeMessages(warnings, "warnings", details, name, void 0)); + } + } catch (e) { + response.errors.push(extractErrorMessageV8(e, streamIn, details, note && note(), name)); + } + })); + sendResponse(id, response); + }; + requestCallbacks["on-resolve"] = async (id, request) => { + let response = {}, name = "", callback, note; + for (let id2 of request.ids) { + try { + ({ name, callback, note } = onResolveCallbacks[id2]); + let result = await callback({ + path: request.path, + importer: request.importer, + namespace: request.namespace, + resolveDir: request.resolveDir, + kind: request.kind, + pluginData: details.load(request.pluginData), + with: request.with + }); + if (result != null) { + if (typeof result !== "object") throw new Error(`Expected onResolve() callback in plugin ${quote(name)} to return an object`); + let keys = {}; + let pluginName = getFlag(result, keys, "pluginName", mustBeString); + let path3 = getFlag(result, keys, "path", mustBeString); + let namespace = getFlag(result, keys, "namespace", mustBeString); + let suffix = getFlag(result, keys, "suffix", mustBeString); + let external = getFlag(result, keys, "external", mustBeBoolean); + let sideEffects = getFlag(result, keys, "sideEffects", mustBeBoolean); + let pluginData = getFlag(result, keys, "pluginData", canBeAnything); + let errors = getFlag(result, keys, "errors", mustBeArray); + let warnings = getFlag(result, keys, "warnings", mustBeArray); + let watchFiles = getFlag(result, keys, "watchFiles", mustBeArrayOfStrings); + let watchDirs = getFlag(result, keys, "watchDirs", mustBeArrayOfStrings); + checkForInvalidFlags(result, keys, `from onResolve() callback in plugin ${quote(name)}`); + response.id = id2; + if (pluginName != null) response.pluginName = pluginName; + if (path3 != null) response.path = path3; + if (namespace != null) response.namespace = namespace; + if (suffix != null) response.suffix = suffix; + if (external != null) response.external = external; + if (sideEffects != null) response.sideEffects = sideEffects; + if (pluginData != null) response.pluginData = details.store(pluginData); + if (errors != null) response.errors = sanitizeMessages(errors, "errors", details, name, void 0); + if (warnings != null) response.warnings = sanitizeMessages(warnings, "warnings", details, name, void 0); + if (watchFiles != null) response.watchFiles = sanitizeStringArray(watchFiles, "watchFiles"); + if (watchDirs != null) response.watchDirs = sanitizeStringArray(watchDirs, "watchDirs"); + break; + } + } catch (e) { + response = { id: id2, errors: [extractErrorMessageV8(e, streamIn, details, note && note(), name)] }; + break; + } + } + sendResponse(id, response); + }; + requestCallbacks["on-load"] = async (id, request) => { + let response = {}, name = "", callback, note; + for (let id2 of request.ids) { + try { + ({ name, callback, note } = onLoadCallbacks[id2]); + let result = await callback({ + path: request.path, + namespace: request.namespace, + suffix: request.suffix, + pluginData: details.load(request.pluginData), + with: request.with + }); + if (result != null) { + if (typeof result !== "object") throw new Error(`Expected onLoad() callback in plugin ${quote(name)} to return an object`); + let keys = {}; + let pluginName = getFlag(result, keys, "pluginName", mustBeString); + let contents = getFlag(result, keys, "contents", mustBeStringOrUint8Array); + let resolveDir = getFlag(result, keys, "resolveDir", mustBeString); + let pluginData = getFlag(result, keys, "pluginData", canBeAnything); + let loader = getFlag(result, keys, "loader", mustBeString); + let errors = getFlag(result, keys, "errors", mustBeArray); + let warnings = getFlag(result, keys, "warnings", mustBeArray); + let watchFiles = getFlag(result, keys, "watchFiles", mustBeArrayOfStrings); + let watchDirs = getFlag(result, keys, "watchDirs", mustBeArrayOfStrings); + checkForInvalidFlags(result, keys, `from onLoad() callback in plugin ${quote(name)}`); + response.id = id2; + if (pluginName != null) response.pluginName = pluginName; + if (contents instanceof Uint8Array) response.contents = contents; + else if (contents != null) response.contents = encodeUTF8(contents); + if (resolveDir != null) response.resolveDir = resolveDir; + if (pluginData != null) response.pluginData = details.store(pluginData); + if (loader != null) response.loader = loader; + if (errors != null) response.errors = sanitizeMessages(errors, "errors", details, name, void 0); + if (warnings != null) response.warnings = sanitizeMessages(warnings, "warnings", details, name, void 0); + if (watchFiles != null) response.watchFiles = sanitizeStringArray(watchFiles, "watchFiles"); + if (watchDirs != null) response.watchDirs = sanitizeStringArray(watchDirs, "watchDirs"); + break; + } + } catch (e) { + response = { id: id2, errors: [extractErrorMessageV8(e, streamIn, details, note && note(), name)] }; + break; + } + } + sendResponse(id, response); + }; + let runOnEndCallbacks = (result, done) => done([], []); + if (onEndCallbacks.length > 0) { + runOnEndCallbacks = (result, done) => { + (async () => { + const onEndErrors = []; + const onEndWarnings = []; + for (const { name, callback, note } of onEndCallbacks) { + let newErrors; + let newWarnings; + try { + const value = await callback(result); + if (value != null) { + if (typeof value !== "object") throw new Error(`Expected onEnd() callback in plugin ${quote(name)} to return an object`); + let keys = {}; + let errors = getFlag(value, keys, "errors", mustBeArray); + let warnings = getFlag(value, keys, "warnings", mustBeArray); + checkForInvalidFlags(value, keys, `from onEnd() callback in plugin ${quote(name)}`); + if (errors != null) newErrors = sanitizeMessages(errors, "errors", details, name, void 0); + if (warnings != null) newWarnings = sanitizeMessages(warnings, "warnings", details, name, void 0); + } + } catch (e) { + newErrors = [extractErrorMessageV8(e, streamIn, details, note && note(), name)]; + } + if (newErrors) { + onEndErrors.push(...newErrors); + try { + result.errors.push(...newErrors); + } catch { + } + } + if (newWarnings) { + onEndWarnings.push(...newWarnings); + try { + result.warnings.push(...newWarnings); + } catch { + } + } + } + done(onEndErrors, onEndWarnings); + })(); + }; + } + let scheduleOnDisposeCallbacks = () => { + for (const cb of onDisposeCallbacks) { + setTimeout(() => cb(), 0); + } + }; + isSetupDone = true; + return { + ok: true, + requestPlugins, + runOnEndCallbacks, + scheduleOnDisposeCallbacks + }; +}; +function createObjectStash() { + const map = /* @__PURE__ */ new Map(); + let nextID = 0; + return { + clear() { + map.clear(); + }, + load(id) { + return map.get(id); + }, + store(value) { + if (value === void 0) return -1; + const id = nextID++; + map.set(id, value); + return id; + } + }; +} +function extractCallerV8(e, streamIn, ident) { + let note; + let tried = false; + return () => { + if (tried) return note; + tried = true; + try { + let lines = (e.stack + "").split("\n"); + lines.splice(1, 1); + let location = parseStackLinesV8(streamIn, lines, ident); + if (location) { + note = { text: e.message, location }; + return note; + } + } catch { + } + }; +} +function extractErrorMessageV8(e, streamIn, stash, note, pluginName) { + let text = "Internal error"; + let location = null; + try { + text = (e && e.message || e) + ""; + } catch { + } + try { + location = parseStackLinesV8(streamIn, (e.stack + "").split("\n"), ""); + } catch { + } + return { id: "", pluginName, text, location, notes: note ? [note] : [], detail: stash ? stash.store(e) : -1 }; +} +function parseStackLinesV8(streamIn, lines, ident) { + let at = " at "; + if (streamIn.readFileSync && !lines[0].startsWith(at) && lines[1].startsWith(at)) { + for (let i = 1; i < lines.length; i++) { + let line = lines[i]; + if (!line.startsWith(at)) continue; + line = line.slice(at.length); + while (true) { + let match = /^(?:new |async )?\S+ \((.*)\)$/.exec(line); + if (match) { + line = match[1]; + continue; + } + match = /^eval at \S+ \((.*)\)(?:, \S+:\d+:\d+)?$/.exec(line); + if (match) { + line = match[1]; + continue; + } + match = /^(\S+):(\d+):(\d+)$/.exec(line); + if (match) { + let contents; + try { + contents = streamIn.readFileSync(match[1], "utf8"); + } catch { + break; + } + let lineText = contents.split(/\r\n|\r|\n|\u2028|\u2029/)[+match[2] - 1] || ""; + let column = +match[3] - 1; + let length = lineText.slice(column, column + ident.length) === ident ? ident.length : 0; + return { + file: match[1], + namespace: "file", + line: +match[2], + column: encodeUTF8(lineText.slice(0, column)).length, + length: encodeUTF8(lineText.slice(column, column + length)).length, + lineText: lineText + "\n" + lines.slice(1).join("\n"), + suggestion: "" + }; + } + break; + } + } + } + return null; +} +function failureErrorWithLog(text, errors, warnings) { + let limit = 5; + text += errors.length < 1 ? "" : ` with ${errors.length} error${errors.length < 2 ? "" : "s"}:` + errors.slice(0, limit + 1).map((e, i) => { + if (i === limit) return "\n..."; + if (!e.location) return ` +error: ${e.text}`; + let { file, line, column } = e.location; + let pluginText = e.pluginName ? `[plugin: ${e.pluginName}] ` : ""; + return ` +${file}:${line}:${column}: ERROR: ${pluginText}${e.text}`; + }).join(""); + let error = new Error(text); + for (const [key, value] of [["errors", errors], ["warnings", warnings]]) { + Object.defineProperty(error, key, { + configurable: true, + enumerable: true, + get: () => value, + set: (value2) => Object.defineProperty(error, key, { + configurable: true, + enumerable: true, + value: value2 + }) + }); + } + return error; +} +function replaceDetailsInMessages(messages, stash) { + for (const message of messages) { + message.detail = stash.load(message.detail); + } + return messages; +} +function sanitizeLocation(location, where, terminalWidth) { + if (location == null) return null; + let keys = {}; + let file = getFlag(location, keys, "file", mustBeString); + let namespace = getFlag(location, keys, "namespace", mustBeString); + let line = getFlag(location, keys, "line", mustBeInteger); + let column = getFlag(location, keys, "column", mustBeInteger); + let length = getFlag(location, keys, "length", mustBeInteger); + let lineText = getFlag(location, keys, "lineText", mustBeString); + let suggestion = getFlag(location, keys, "suggestion", mustBeString); + checkForInvalidFlags(location, keys, where); + if (lineText) { + const relevantASCII = lineText.slice( + 0, + (column && column > 0 ? column : 0) + (length && length > 0 ? length : 0) + (terminalWidth && terminalWidth > 0 ? terminalWidth : 80) + ); + if (!/[\x7F-\uFFFF]/.test(relevantASCII) && !/\n/.test(lineText)) { + lineText = relevantASCII; + } + } + return { + file: file || "", + namespace: namespace || "", + line: line || 0, + column: column || 0, + length: length || 0, + lineText: lineText || "", + suggestion: suggestion || "" + }; +} +function sanitizeMessages(messages, property, stash, fallbackPluginName, terminalWidth) { + let messagesClone = []; + let index = 0; + for (const message of messages) { + let keys = {}; + let id = getFlag(message, keys, "id", mustBeString); + let pluginName = getFlag(message, keys, "pluginName", mustBeString); + let text = getFlag(message, keys, "text", mustBeString); + let location = getFlag(message, keys, "location", mustBeObjectOrNull); + let notes = getFlag(message, keys, "notes", mustBeArray); + let detail = getFlag(message, keys, "detail", canBeAnything); + let where = `in element ${index} of "${property}"`; + checkForInvalidFlags(message, keys, where); + let notesClone = []; + if (notes) { + for (const note of notes) { + let noteKeys = {}; + let noteText = getFlag(note, noteKeys, "text", mustBeString); + let noteLocation = getFlag(note, noteKeys, "location", mustBeObjectOrNull); + checkForInvalidFlags(note, noteKeys, where); + notesClone.push({ + text: noteText || "", + location: sanitizeLocation(noteLocation, where, terminalWidth) + }); + } + } + messagesClone.push({ + id: id || "", + pluginName: pluginName || fallbackPluginName, + text: text || "", + location: sanitizeLocation(location, where, terminalWidth), + notes: notesClone, + detail: stash ? stash.store(detail) : -1 + }); + index++; + } + return messagesClone; +} +function sanitizeStringArray(values, property) { + const result = []; + for (const value of values) { + if (typeof value !== "string") throw new Error(`${quote(property)} must be an array of strings`); + result.push(value); + } + return result; +} +function sanitizeStringMap(map, property) { + const result = /* @__PURE__ */ Object.create(null); + for (const key in map) { + const value = map[key]; + if (typeof value !== "string") throw new Error(`key ${quote(key)} in object ${quote(property)} must be a string`); + result[key] = value; + } + return result; +} +function convertOutputFiles({ path: path3, contents, hash }) { + let text = null; + return { + path: path3, + contents, + hash, + get text() { + const binary = this.contents; + if (text === null || binary !== contents) { + contents = binary; + text = decodeUTF8(binary); + } + return text; + } + }; +} +function jsRegExpToGoRegExp(regexp) { + let result = regexp.source; + if (regexp.flags) result = `(?${regexp.flags})${result}`; + return result; +} +function parseJSON(bytes) { + let text; + try { + text = decodeUTF8(bytes); + } catch { + return JSON_parse(bytes); + } + return JSON.parse(text); +} + +// lib/npm/node-platform.ts +var fs = require("fs"); +var os = require("os"); +var path = require("path"); +var ESBUILD_BINARY_PATH = process.env.ESBUILD_BINARY_PATH || ESBUILD_BINARY_PATH; +var isValidBinaryPath = (x) => !!x && x !== "/usr/bin/esbuild"; +var packageDarwin_arm64 = "@esbuild/darwin-arm64"; +var packageDarwin_x64 = "@esbuild/darwin-x64"; +var knownWindowsPackages = { + "win32 arm64 LE": "@esbuild/win32-arm64", + "win32 ia32 LE": "@esbuild/win32-ia32", + "win32 x64 LE": "@esbuild/win32-x64" +}; +var knownUnixlikePackages = { + "aix ppc64 BE": "@esbuild/aix-ppc64", + "android arm64 LE": "@esbuild/android-arm64", + "darwin arm64 LE": "@esbuild/darwin-arm64", + "darwin x64 LE": "@esbuild/darwin-x64", + "freebsd arm64 LE": "@esbuild/freebsd-arm64", + "freebsd x64 LE": "@esbuild/freebsd-x64", + "linux arm LE": "@esbuild/linux-arm", + "linux arm64 LE": "@esbuild/linux-arm64", + "linux ia32 LE": "@esbuild/linux-ia32", + "linux mips64el LE": "@esbuild/linux-mips64el", + "linux ppc64 LE": "@esbuild/linux-ppc64", + "linux riscv64 LE": "@esbuild/linux-riscv64", + "linux s390x BE": "@esbuild/linux-s390x", + "linux x64 LE": "@esbuild/linux-x64", + "linux loong64 LE": "@esbuild/linux-loong64", + "netbsd arm64 LE": "@esbuild/netbsd-arm64", + "netbsd x64 LE": "@esbuild/netbsd-x64", + "openbsd arm64 LE": "@esbuild/openbsd-arm64", + "openbsd x64 LE": "@esbuild/openbsd-x64", + "sunos x64 LE": "@esbuild/sunos-x64" +}; +var knownWebAssemblyFallbackPackages = { + "android arm LE": "@esbuild/android-arm", + "android x64 LE": "@esbuild/android-x64", + "openharmony arm64 LE": "@esbuild/openharmony-arm64" +}; +function pkgAndSubpathForCurrentPlatform() { + let pkg; + let subpath; + let isWASM = false; + let platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`; + if (platformKey in knownWindowsPackages) { + pkg = knownWindowsPackages[platformKey]; + subpath = "esbuild.exe"; + } else if (platformKey in knownUnixlikePackages) { + pkg = knownUnixlikePackages[platformKey]; + subpath = "bin/esbuild"; + } else if (platformKey in knownWebAssemblyFallbackPackages) { + pkg = knownWebAssemblyFallbackPackages[platformKey]; + subpath = "bin/esbuild"; + isWASM = true; + } else { + throw new Error(`Unsupported platform: ${platformKey}`); + } + return { pkg, subpath, isWASM }; +} +function pkgForSomeOtherPlatform() { + const libMainJS = require.resolve("esbuild"); + const nodeModulesDirectory = path.dirname(path.dirname(path.dirname(libMainJS))); + if (path.basename(nodeModulesDirectory) === "node_modules") { + for (const unixKey in knownUnixlikePackages) { + try { + const pkg = knownUnixlikePackages[unixKey]; + if (fs.existsSync(path.join(nodeModulesDirectory, pkg))) return pkg; + } catch { + } + } + for (const windowsKey in knownWindowsPackages) { + try { + const pkg = knownWindowsPackages[windowsKey]; + if (fs.existsSync(path.join(nodeModulesDirectory, pkg))) return pkg; + } catch { + } + } + } + return null; +} +function downloadedBinPath(pkg, subpath) { + const esbuildLibDir = path.dirname(require.resolve("esbuild")); + return path.join(esbuildLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`); +} +function generateBinPath() { + if (isValidBinaryPath(ESBUILD_BINARY_PATH)) { + if (!fs.existsSync(ESBUILD_BINARY_PATH)) { + console.warn(`[esbuild] Ignoring bad configuration: ESBUILD_BINARY_PATH=${ESBUILD_BINARY_PATH}`); + } else { + return { binPath: ESBUILD_BINARY_PATH, isWASM: false }; + } + } + const { pkg, subpath, isWASM } = pkgAndSubpathForCurrentPlatform(); + let binPath; + try { + binPath = require.resolve(`${pkg}/${subpath}`); + } catch (e) { + binPath = downloadedBinPath(pkg, subpath); + if (!fs.existsSync(binPath)) { + try { + require.resolve(pkg); + } catch { + const otherPkg = pkgForSomeOtherPlatform(); + if (otherPkg) { + let suggestions = ` +Specifically the "${otherPkg}" package is present but this platform +needs the "${pkg}" package instead. People often get into this +situation by installing esbuild on Windows or macOS and copying "node_modules" +into a Docker image that runs Linux, or by copying "node_modules" between +Windows and WSL environments. + +If you are installing with npm, you can try not copying the "node_modules" +directory when you copy the files over, and running "npm ci" or "npm install" +on the destination platform after the copy. Or you could consider using yarn +instead of npm which has built-in support for installing a package on multiple +platforms simultaneously. + +If you are installing with yarn, you can try listing both this platform and the +other platform in your ".yarnrc.yml" file using the "supportedArchitectures" +feature: https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures +Keep in mind that this means multiple copies of esbuild will be present. +`; + if (pkg === packageDarwin_x64 && otherPkg === packageDarwin_arm64 || pkg === packageDarwin_arm64 && otherPkg === packageDarwin_x64) { + suggestions = ` +Specifically the "${otherPkg}" package is present but this platform +needs the "${pkg}" package instead. People often get into this +situation by installing esbuild with npm running inside of Rosetta 2 and then +trying to use it with node running outside of Rosetta 2, or vice versa (Rosetta +2 is Apple's on-the-fly x86_64-to-arm64 translation service). + +If you are installing with npm, you can try ensuring that both npm and node are +not running under Rosetta 2 and then reinstalling esbuild. This likely involves +changing how you installed npm and/or node. For example, installing node with +the universal installer here should work: https://nodejs.org/en/download/. Or +you could consider using yarn instead of npm which has built-in support for +installing a package on multiple platforms simultaneously. + +If you are installing with yarn, you can try listing both "arm64" and "x64" +in your ".yarnrc.yml" file using the "supportedArchitectures" feature: +https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures +Keep in mind that this means multiple copies of esbuild will be present. +`; + } + throw new Error(` +You installed esbuild for another platform than the one you're currently using. +This won't work because esbuild is written with native code and needs to +install a platform-specific binary executable. +${suggestions} +Another alternative is to use the "esbuild-wasm" package instead, which works +the same way on all platforms. But it comes with a heavy performance cost and +can sometimes be 10x slower than the "esbuild" package, so you may also not +want to do that. +`); + } + throw new Error(`The package "${pkg}" could not be found, and is needed by esbuild. + +If you are installing esbuild with npm, make sure that you don't specify the +"--no-optional" or "--omit=optional" flags. The "optionalDependencies" feature +of "package.json" is used by esbuild to install the correct binary executable +for your current platform.`); + } + throw e; + } + } + if (/\.zip\//.test(binPath)) { + let pnpapi; + try { + pnpapi = require("pnpapi"); + } catch (e) { + } + if (pnpapi) { + const root = pnpapi.getPackageInformation(pnpapi.topLevel).packageLocation; + const binTargetPath = path.join( + root, + "node_modules", + ".cache", + "esbuild", + `pnpapi-${pkg.replace("/", "-")}-${"0.28.1"}-${path.basename(subpath)}` + ); + if (!fs.existsSync(binTargetPath)) { + fs.mkdirSync(path.dirname(binTargetPath), { recursive: true }); + fs.copyFileSync(binPath, binTargetPath); + fs.chmodSync(binTargetPath, 493); + } + return { binPath: binTargetPath, isWASM }; + } + } + return { binPath, isWASM }; +} + +// lib/npm/node.ts +var child_process = require("child_process"); +var crypto = require("crypto"); +var path2 = require("path"); +var fs2 = require("fs"); +var os2 = require("os"); +var tty = require("tty"); +var worker_threads; +if (process.env.ESBUILD_WORKER_THREADS !== "0") { + try { + worker_threads = require("worker_threads"); + } catch { + } + let [major, minor] = process.versions.node.split("."); + if ( + // { + if ((!ESBUILD_BINARY_PATH || false) && (path2.basename(__filename) !== "main.js" || path2.basename(__dirname) !== "lib")) { + throw new Error( + `The esbuild JavaScript API cannot be bundled. Please mark the "esbuild" package as external so it's not included in the bundle. + +More information: The file containing the code for esbuild's JavaScript API (${__filename}) does not appear to be inside the esbuild package on the file system, which usually means that the esbuild package was bundled into another file. This is problematic because the API needs to run a binary executable inside the esbuild package which is located using a relative path from the API code to the executable. If the esbuild package is bundled, the relative path will be incorrect and the executable won't be found.` + ); + } + if (false) { + return ["node", [path2.join(__dirname, "..", "bin", "esbuild")]]; + } else { + const { binPath, isWASM } = generateBinPath(); + if (isWASM) { + return ["node", [binPath]]; + } else { + return [binPath, []]; + } + } +}; +var isTTY = () => tty.isatty(2); +var fsSync = { + readFile(tempFile, callback) { + try { + let contents = fs2.readFileSync(tempFile, "utf8"); + try { + fs2.unlinkSync(tempFile); + } catch { + } + callback(null, contents); + } catch (err) { + callback(err, null); + } + }, + writeFile(contents, callback) { + try { + let tempFile = randomFileName(); + fs2.writeFileSync(tempFile, contents); + callback(tempFile); + } catch { + callback(null); + } + } +}; +var fsAsync = { + readFile(tempFile, callback) { + try { + fs2.readFile(tempFile, "utf8", (err, contents) => { + try { + fs2.unlink(tempFile, () => callback(err, contents)); + } catch { + callback(err, contents); + } + }); + } catch (err) { + callback(err, null); + } + }, + writeFile(contents, callback) { + try { + let tempFile = randomFileName(); + fs2.writeFile(tempFile, contents, (err) => err !== null ? callback(null) : callback(tempFile)); + } catch { + callback(null); + } + } +}; +var version = "0.28.1"; +var build = (options) => ensureServiceIsRunning().build(options); +var context = (buildOptions) => ensureServiceIsRunning().context(buildOptions); +var transform = (input, options) => ensureServiceIsRunning().transform(input, options); +var formatMessages = (messages, options) => ensureServiceIsRunning().formatMessages(messages, options); +var analyzeMetafile = (messages, options) => ensureServiceIsRunning().analyzeMetafile(messages, options); +var buildSync = (options) => { + if (worker_threads && !isInternalWorkerThread) { + if (!workerThreadService) workerThreadService = startWorkerThreadService(worker_threads); + return workerThreadService.buildSync(options); + } + let result; + runServiceSync((service) => service.buildOrContext({ + callName: "buildSync", + refs: null, + options, + isTTY: isTTY(), + defaultWD, + callback: (err, res) => { + if (err) throw err; + result = res; + } + })); + return result; +}; +var transformSync = (input, options) => { + if (worker_threads && !isInternalWorkerThread) { + if (!workerThreadService) workerThreadService = startWorkerThreadService(worker_threads); + return workerThreadService.transformSync(input, options); + } + let result; + runServiceSync((service) => service.transform({ + callName: "transformSync", + refs: null, + input, + options: options || {}, + isTTY: isTTY(), + fs: fsSync, + callback: (err, res) => { + if (err) throw err; + result = res; + } + })); + return result; +}; +var formatMessagesSync = (messages, options) => { + if (worker_threads && !isInternalWorkerThread) { + if (!workerThreadService) workerThreadService = startWorkerThreadService(worker_threads); + return workerThreadService.formatMessagesSync(messages, options); + } + let result; + runServiceSync((service) => service.formatMessages({ + callName: "formatMessagesSync", + refs: null, + messages, + options, + callback: (err, res) => { + if (err) throw err; + result = res; + } + })); + return result; +}; +var analyzeMetafileSync = (metafile, options) => { + if (worker_threads && !isInternalWorkerThread) { + if (!workerThreadService) workerThreadService = startWorkerThreadService(worker_threads); + return workerThreadService.analyzeMetafileSync(metafile, options); + } + let result; + runServiceSync((service) => service.analyzeMetafile({ + callName: "analyzeMetafileSync", + refs: null, + metafile: typeof metafile === "string" ? metafile : JSON.stringify(metafile), + options, + callback: (err, res) => { + if (err) throw err; + result = res; + } + })); + return result; +}; +var stop = () => { + if (stopService) stopService(); + if (workerThreadService) workerThreadService.stop(); + return Promise.resolve(); +}; +var initializeWasCalled = false; +var initialize = (options) => { + options = validateInitializeOptions(options || {}); + if (options.wasmURL) throw new Error(`The "wasmURL" option only works in the browser`); + if (options.wasmModule) throw new Error(`The "wasmModule" option only works in the browser`); + if (options.worker) throw new Error(`The "worker" option only works in the browser`); + if (initializeWasCalled) throw new Error('Cannot call "initialize" more than once'); + ensureServiceIsRunning(); + initializeWasCalled = true; + return Promise.resolve(); +}; +var defaultWD = process.cwd(); +var longLivedService; +var stopService; +var ensureServiceIsRunning = () => { + if (longLivedService) return longLivedService; + let [command, args] = esbuildCommandAndArgs(); + let child = child_process.spawn(command, args.concat(`--service=${"0.28.1"}`, "--ping"), { + windowsHide: true, + stdio: ["pipe", "pipe", "inherit"], + cwd: defaultWD + }); + let { readFromStdout, afterClose, service } = createChannel({ + writeToStdin(bytes) { + child.stdin.write(bytes, (err) => { + if (err) afterClose(err); + }); + }, + readFileSync: fs2.readFileSync, + isSync: false, + hasFS: true, + esbuild: node_exports + }); + child.stdin.on("error", afterClose); + child.on("error", afterClose); + const stdin = child.stdin; + const stdout = child.stdout; + stdout.on("data", readFromStdout); + stdout.on("end", afterClose); + stopService = () => { + stdin.destroy(); + stdout.destroy(); + child.kill(); + initializeWasCalled = false; + longLivedService = void 0; + stopService = void 0; + }; + let refCount = 0; + child.unref(); + if (stdin.unref) { + stdin.unref(); + } + if (stdout.unref) { + stdout.unref(); + } + const refs = { + ref() { + if (++refCount === 1) child.ref(); + }, + unref() { + if (--refCount === 0) child.unref(); + } + }; + longLivedService = { + build: (options) => new Promise((resolve, reject) => { + service.buildOrContext({ + callName: "build", + refs, + options, + isTTY: isTTY(), + defaultWD, + callback: (err, res) => err ? reject(err) : resolve(res) + }); + }), + context: (options) => new Promise((resolve, reject) => service.buildOrContext({ + callName: "context", + refs, + options, + isTTY: isTTY(), + defaultWD, + callback: (err, res) => err ? reject(err) : resolve(res) + })), + transform: (input, options) => new Promise((resolve, reject) => service.transform({ + callName: "transform", + refs, + input, + options: options || {}, + isTTY: isTTY(), + fs: fsAsync, + callback: (err, res) => err ? reject(err) : resolve(res) + })), + formatMessages: (messages, options) => new Promise((resolve, reject) => service.formatMessages({ + callName: "formatMessages", + refs, + messages, + options, + callback: (err, res) => err ? reject(err) : resolve(res) + })), + analyzeMetafile: (metafile, options) => new Promise((resolve, reject) => service.analyzeMetafile({ + callName: "analyzeMetafile", + refs, + metafile: typeof metafile === "string" ? metafile : JSON.stringify(metafile), + options, + callback: (err, res) => err ? reject(err) : resolve(res) + })) + }; + return longLivedService; +}; +var runServiceSync = (callback) => { + let [command, args] = esbuildCommandAndArgs(); + let stdin = new Uint8Array(); + let { readFromStdout, afterClose, service } = createChannel({ + writeToStdin(bytes) { + if (stdin.length !== 0) throw new Error("Must run at most one command"); + stdin = bytes; + }, + isSync: true, + hasFS: true, + esbuild: node_exports + }); + callback(service); + let stdout = child_process.execFileSync(command, args.concat(`--service=${"0.28.1"}`), { + cwd: defaultWD, + windowsHide: true, + input: stdin, + // We don't know how large the output could be. If it's too large, the + // command will fail with ENOBUFS. Reserve 16mb for now since that feels + // like it should be enough. Also allow overriding this with an environment + // variable. + maxBuffer: +process.env.ESBUILD_MAX_BUFFER || 16 * 1024 * 1024 + }); + readFromStdout(stdout); + afterClose(null); +}; +var randomFileName = () => { + return path2.join(os2.tmpdir(), `esbuild-${crypto.randomBytes(32).toString("hex")}`); +}; +var workerThreadService = null; +var startWorkerThreadService = (worker_threads2) => { + let { port1: mainPort, port2: workerPort } = new worker_threads2.MessageChannel(); + let worker = new worker_threads2.Worker(__filename, { + workerData: { workerPort, defaultWD, esbuildVersion: "0.28.1" }, + transferList: [workerPort], + // From node's documentation: https://nodejs.org/api/worker_threads.html + // + // Take care when launching worker threads from preload scripts (scripts loaded + // and run using the `-r` command line flag). Unless the `execArgv` option is + // explicitly set, new Worker threads automatically inherit the command line flags + // from the running process and will preload the same preload scripts as the main + // thread. If the preload script unconditionally launches a worker thread, every + // thread spawned will spawn another until the application crashes. + // + execArgv: [] + }); + let nextID = 0; + let fakeBuildError = (text) => { + let error = new Error(`Build failed with 1 error: +error: ${text}`); + let errors = [{ id: "", pluginName: "", text, location: null, notes: [], detail: void 0 }]; + error.errors = errors; + error.warnings = []; + return error; + }; + let validateBuildSyncOptions = (options) => { + if (!options) return; + let plugins = options.plugins; + if (plugins && plugins.length > 0) throw fakeBuildError(`Cannot use plugins in synchronous API calls`); + }; + let applyProperties = (object, properties) => { + for (let key in properties) { + object[key] = properties[key]; + } + }; + let runCallSync = (command, args) => { + let id = nextID++; + let sharedBuffer = new SharedArrayBuffer(8); + let sharedBufferView = new Int32Array(sharedBuffer); + let msg = { sharedBuffer, id, command, args }; + worker.postMessage(msg); + let status = Atomics.wait(sharedBufferView, 0, 0); + if (status !== "ok" && status !== "not-equal") throw new Error("Internal error: Atomics.wait() failed: " + status); + let { message: { id: id2, resolve, reject, properties } } = worker_threads2.receiveMessageOnPort(mainPort); + if (id !== id2) throw new Error(`Internal error: Expected id ${id} but got id ${id2}`); + if (reject) { + applyProperties(reject, properties); + throw reject; + } + return resolve; + }; + worker.unref(); + return { + buildSync(options) { + validateBuildSyncOptions(options); + return runCallSync("build", [options]); + }, + transformSync(input, options) { + return runCallSync("transform", [input, options]); + }, + formatMessagesSync(messages, options) { + return runCallSync("formatMessages", [messages, options]); + }, + analyzeMetafileSync(metafile, options) { + return runCallSync("analyzeMetafile", [metafile, options]); + }, + stop() { + worker.terminate(); + workerThreadService = null; + } + }; +}; +var startSyncServiceWorker = () => { + let workerPort = worker_threads.workerData.workerPort; + let parentPort = worker_threads.parentPort; + let extractProperties = (object) => { + let properties = {}; + if (object && typeof object === "object") { + for (let key in object) { + properties[key] = object[key]; + } + } + return properties; + }; + try { + let service = ensureServiceIsRunning(); + defaultWD = worker_threads.workerData.defaultWD; + parentPort.on("message", (msg) => { + (async () => { + let { sharedBuffer, id, command, args } = msg; + let sharedBufferView = new Int32Array(sharedBuffer); + try { + switch (command) { + case "build": + workerPort.postMessage({ id, resolve: await service.build(args[0]) }); + break; + case "transform": + workerPort.postMessage({ id, resolve: await service.transform(args[0], args[1]) }); + break; + case "formatMessages": + workerPort.postMessage({ id, resolve: await service.formatMessages(args[0], args[1]) }); + break; + case "analyzeMetafile": + workerPort.postMessage({ id, resolve: await service.analyzeMetafile(args[0], args[1]) }); + break; + default: + throw new Error(`Invalid command: ${command}`); + } + } catch (reject) { + workerPort.postMessage({ id, reject, properties: extractProperties(reject) }); + } + Atomics.add(sharedBufferView, 0, 1); + Atomics.notify(sharedBufferView, 0, Infinity); + })(); + }); + } catch (reject) { + parentPort.on("message", (msg) => { + let { sharedBuffer, id } = msg; + let sharedBufferView = new Int32Array(sharedBuffer); + workerPort.postMessage({ id, reject, properties: extractProperties(reject) }); + Atomics.add(sharedBufferView, 0, 1); + Atomics.notify(sharedBufferView, 0, Infinity); + }); + } +}; +if (isInternalWorkerThread) { + startSyncServiceWorker(); +} +var node_default = node_exports; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + analyzeMetafile, + analyzeMetafileSync, + build, + buildSync, + context, + formatMessages, + formatMessagesSync, + initialize, + stop, + transform, + transformSync, + version +}); diff --git a/node_modules/esbuild/package.json b/node_modules/esbuild/package.json new file mode 100644 index 0000000..6285838 --- /dev/null +++ b/node_modules/esbuild/package.json @@ -0,0 +1,74 @@ +{ + "name": "esbuild", + "version": "0.28.1", + "description": "An extremely fast JavaScript and CSS bundler and minifier.", + "repository": { + "type": "git", + "url": "git+https://github.com/evanw/esbuild.git" + }, + "scripts": { + "postinstall": "node install.js" + }, + "main": "lib/main.js", + "types": "lib/main.d.ts", + "engines": { + "node": ">=18" + }, + "bin": { + "esbuild": "bin/esbuild" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + }, + "license": "MIT", + "esbuild.binaryHashes": { + "@esbuild/aix-ppc64/bin/esbuild": "0dd860154344f94b7a9367e64ffc2bc5b89a4313b4a399e5127cdc4ff5000303", + "@esbuild/android-arm64/bin/esbuild": "087671da02d323e7915fafc13567c0929192633ed544bd8adee9bc020fddf5b4", + "@esbuild/darwin-arm64/bin/esbuild": "e2dc9a52440a2a34f09434a2f4843cb1e30f84e40dcf238976ec61ef8cd7f36a", + "@esbuild/darwin-x64/bin/esbuild": "dd53ccf32f9b5b3ab30d41388ef1fc8f81c44ca57ee7a32a7364a1753308d009", + "@esbuild/freebsd-arm64/bin/esbuild": "5fef5a5ef24d9660d7711b756be5ddeba1fb3ca8dd62d703682ebb9fab3b68b0", + "@esbuild/freebsd-x64/bin/esbuild": "4427a8cbfa0661943ccfef2606a65b35f3411ac73e447e86f7732aace61e4609", + "@esbuild/linux-arm/bin/esbuild": "a2d93f7a8b1c9f91d47beec987888b4765c890501b6274f4bdff4061a5e0d9fd", + "@esbuild/linux-arm64/bin/esbuild": "51e829ba36f36be6d9aea6e329ddc4f9350302339b16aaca96a3cb97f64a8ebb", + "@esbuild/linux-ia32/bin/esbuild": "9cd7515a75d6f96b0aa055861cf987498315428088cd6d18de5082f904ae5794", + "@esbuild/linux-loong64/bin/esbuild": "73fa76af9b13f7a27fdb20673b8c2af927fe1511d14e51edeb4b7b71f7f03d0e", + "@esbuild/linux-mips64el/bin/esbuild": "d734787abc3c99d95242805047fe32da85a5822f04bf33d766a966bf5fd85488", + "@esbuild/linux-ppc64/bin/esbuild": "90709144617c2adf8f6c14937f03b114c259de0b9309666e3a9d89a1fb266d04", + "@esbuild/linux-riscv64/bin/esbuild": "86df35a46bedde8b756edb6565a1df7b5a832ad74dd0e179608cbf6509a2582a", + "@esbuild/linux-s390x/bin/esbuild": "f8cad0db35132e5ac3065c4345c36e7ffe18fdc98417a61bcf5a95a6c694e57c", + "@esbuild/linux-x64/bin/esbuild": "0c6588b092a2c291a72bab90659f3c9e0e25e0fe59c9ac12b4dae4d945e5548c", + "@esbuild/netbsd-arm64/bin/esbuild": "490cfdac2d96d5608d91cf55bdf4052bbde7013dafe87ec7adc7784778ad4d4c", + "@esbuild/netbsd-x64/bin/esbuild": "c61e0e4c553a4986fd0e9d63a0425e93be831ff7b13bfb8a564368fb7590f85d", + "@esbuild/openbsd-arm64/bin/esbuild": "f9d814698e26c09c3f90d4c103cbdf3832c9f2c841d64a93889d63d23da9b8cf", + "@esbuild/openbsd-x64/bin/esbuild": "2e30dce11f7236aa362c1c57212cc696f51472169aa417f30e9b641f3b7dcade", + "@esbuild/sunos-x64/bin/esbuild": "770e0d2bc930b1a1d19d3f43243ff8f393efddb599e7f5843160feacd253267d", + "@esbuild/win32-arm64/esbuild.exe": "bfb8798ab678f1ce4a723739f4a3eabab3244d7a04eeb12be2eb9f58095c13ef", + "@esbuild/win32-ia32/esbuild.exe": "8fa99b6e0945830fce8d7e208fdb21763aa4aea875751f4a0eec7f6e262af1dd", + "@esbuild/win32-x64/esbuild.exe": "ec02ee9b14ab332416fedd10614dfb80eed5304d94f67745067c011934a8c3c3" + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..307fca1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,496 @@ +{ + "name": "markdown2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "esbuild": "^0.28.1" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..22509e0 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "esbuild": "^0.28.1" + } +} diff --git a/ui/index.html b/ui/index.html deleted file mode 100644 index c90d948..0000000 --- a/ui/index.html +++ /dev/null @@ -1,8 +0,0 @@ - -
- diff --git a/ui/javascript/filepath/_gleam_artefacts/filepath.cache b/ui/javascript/filepath/_gleam_artefacts/filepath.cache deleted file mode 100644 index fdb5138..0000000 Binary files a/ui/javascript/filepath/_gleam_artefacts/filepath.cache and /dev/null differ diff --git a/ui/javascript/filepath/_gleam_artefacts/filepath.cache_meta b/ui/javascript/filepath/_gleam_artefacts/filepath.cache_meta deleted file mode 100644 index 5f13db8..0000000 Binary files a/ui/javascript/filepath/_gleam_artefacts/filepath.cache_meta and /dev/null differ diff --git a/ui/javascript/filepath/filepath.erl b/ui/javascript/filepath/filepath.erl deleted file mode 100644 index e774982..0000000 --- a/ui/javascript/filepath/filepath.erl +++ /dev/null @@ -1,425 +0,0 @@ --module(filepath). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). - --export([join/2, split_unix/1, directory_name/1, is_absolute/1, split_windows/1, split/1, base_name/1, extension/1, strip_extension/1, expand/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Work with file paths in Gleam!\n" - "\n" - " This library expects paths to be valid unicode. If you need to work with\n" - " non-unicode paths you will need to convert them to unicode before using\n" - " this library.\n" -). - --file("src/filepath.gleam", 49). --spec relative(binary()) -> binary(). -relative(Path) -> - case Path of - <<"/"/utf8, Path@1/binary>> -> - relative(Path@1); - - _ -> - Path - end. - --file("src/filepath.gleam", 56). --spec remove_trailing_slash(binary()) -> binary(). -remove_trailing_slash(Path) -> - case gleam@string:ends_with(Path, <<"/"/utf8>>) of - true -> - gleam@string:drop_end(Path, 1); - - false -> - Path - end. - --file("src/filepath.gleam", 35). -?DOC( - " Join two paths together.\n" - "\n" - " This function does not expand `..` or `.` segments, use the `expand`\n" - " function to do this.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " join(\"/usr/local\", \"bin\")\n" - " // -> \"/usr/local/bin\"\n" - " ```\n" -). --spec join(binary(), binary()) -> binary(). -join(Left, Right) -> - _pipe@2 = case {Left, Right} of - {_, <<"/"/utf8>>} -> - Left; - - {<<""/utf8>>, _} -> - relative(Right); - - {<<"/"/utf8>>, <<"/"/utf8, _/binary>>} -> - Right; - - {<<"/"/utf8>>, _} -> - <>; - - {_, _} -> - _pipe = remove_trailing_slash(Left), - _pipe@1 = gleam@string:append(_pipe, <<"/"/utf8>>), - gleam@string:append(_pipe@1, relative(Right)) - end, - remove_trailing_slash(_pipe@2). - --file("src/filepath.gleam", 97). -?DOC( - " Split a path into its segments, using `/` as the path separator.\n" - "\n" - " Typically you would want to use `split` instead of this function, but if you\n" - " want non-Windows path behaviour on a Windows system then you can use this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split(\"/usr/local/bin\", \"bin\")\n" - " // -> [\"/\", \"usr\", \"local\", \"bin\"]\n" - " ```\n" -). --spec split_unix(binary()) -> list(binary()). -split_unix(Path) -> - _pipe = case gleam@string:split(Path, <<"/"/utf8>>) of - [<<""/utf8>>] -> - []; - - [<<""/utf8>> | Rest] -> - [<<"/"/utf8>> | Rest]; - - Rest@1 -> - Rest@1 - end, - gleam@list:filter(_pipe, fun(X) -> X /= <<""/utf8>> end). - --file("src/filepath.gleam", 267). --spec get_directory_name(list(binary()), binary(), binary()) -> binary(). -get_directory_name(Path, Acc, Segment) -> - case Path of - [<<"/"/utf8>> | Rest] -> - get_directory_name( - Rest, - <>, - <<"/"/utf8>> - ); - - [First | Rest@1] -> - get_directory_name(Rest@1, Acc, <>); - - [] -> - Acc - end. - --file("src/filepath.gleam", 259). -?DOC( - " Get the directory name of a path, that is the path without the file name.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " directory_name(\"/usr/local/bin\")\n" - " // -> \"/usr/local\"\n" - " ```\n" -). --spec directory_name(binary()) -> binary(). -directory_name(Path) -> - Path@1 = remove_trailing_slash(Path), - case Path@1 of - <<"/"/utf8, Rest/binary>> -> - get_directory_name( - gleam@string:to_graphemes(Rest), - <<"/"/utf8>>, - <<""/utf8>> - ); - - _ -> - get_directory_name( - gleam@string:to_graphemes(Path@1), - <<""/utf8>>, - <<""/utf8>> - ) - end. - --file("src/filepath.gleam", 294). -?DOC( - " Check if a path is absolute.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " is_absolute(\"/usr/local/bin\")\n" - " // -> True\n" - " ```\n" - "\n" - " ```gleam\n" - " is_absolute(\"usr/local/bin\")\n" - " // -> False\n" - " ```\n" -). --spec is_absolute(binary()) -> boolean(). -is_absolute(Path) -> - gleam@string:starts_with(Path, <<"/"/utf8>>). - --file("src/filepath.gleam", 339). --spec expand_segments(list(binary()), list(binary())) -> {ok, binary()} | - {error, nil}. -expand_segments(Path, Base) -> - case {Base, Path} of - {[<<""/utf8>>], [<<".."/utf8>> | _]} -> - {error, nil}; - - {[], [<<".."/utf8>> | _]} -> - {error, nil}; - - {[_ | Base@1], [<<".."/utf8>> | Path@1]} -> - expand_segments(Path@1, Base@1); - - {_, [<<"."/utf8>> | Path@2]} -> - expand_segments(Path@2, Base); - - {_, [S | Path@3]} -> - expand_segments(Path@3, [S | Base]); - - {_, []} -> - {ok, gleam@string:join(lists:reverse(Base), <<"/"/utf8>>)} - end. - --file("src/filepath.gleam", 364). --spec root_slash_to_empty(list(binary())) -> list(binary()). -root_slash_to_empty(Segments) -> - case Segments of - [<<"/"/utf8>> | Rest] -> - [<<""/utf8>> | Rest]; - - _ -> - Segments - end. - --file("src/filepath.gleam", 153). --spec pop_windows_drive_specifier(binary()) -> {gleam@option:option(binary()), - binary()}. -pop_windows_drive_specifier(Path) -> - Start = gleam@string:slice(Path, 0, 3), - Codepoints = gleam@string:to_utf_codepoints(Start), - case gleam@list:map(Codepoints, fun gleam@string:utf_codepoint_to_int/1) of - [Drive, Colon, Slash] when (((Slash =:= 47) orelse (Slash =:= 92)) andalso (Colon =:= 58)) andalso (((Drive >= 65) andalso (Drive =< 90)) orelse ((Drive >= 97) andalso (Drive =< 122))) -> - Drive_letter = gleam@string:slice(Path, 0, 1), - Drive@1 = <<(gleam@string:lowercase(Drive_letter))/binary, - ":/"/utf8>>, - Path@1 = gleam@string:drop_start(Path, 3), - {{some, Drive@1}, Path@1}; - - _ -> - {none, Path} - end. - --file("src/filepath.gleam", 120). -?DOC( - " Split a path into its segments, using `/` and `\\` as the path separators. If\n" - " there is a drive letter at the start of the path then it is lowercased.\n" - "\n" - " Typically you would want to use `split` instead of this function, but if you\n" - " want Windows path behaviour on a non-Windows system then you can use this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split(\"/usr/local/bin\", \"bin\")\n" - " // -> [\"/\", \"usr\", \"local\", \"bin\"]\n" - " ```\n" -). --spec split_windows(binary()) -> list(binary()). -split_windows(Path) -> - {Drive, Path@1} = pop_windows_drive_specifier(Path), - Segments = begin - _pipe = gleam@string:split(Path@1, <<"/"/utf8>>), - gleam@list:flat_map( - _pipe, - fun(_capture) -> gleam@string:split(_capture, <<"\\"/utf8>>) end - ) - end, - Segments@1 = case Drive of - {some, Drive@1} -> - [Drive@1 | Segments]; - - none -> - Segments - end, - case Segments@1 of - [<<""/utf8>>] -> - []; - - [<<""/utf8>> | Rest] -> - [<<"/"/utf8>> | Rest]; - - Rest@1 -> - Rest@1 - end. - --file("src/filepath.gleam", 77). -?DOC( - " Split a path into its segments.\n" - "\n" - " When running on Windows both `/` and `\\` are treated as path separators, and \n" - " if the path starts with a drive letter then the drive letter then it is\n" - " lowercased.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " split(\"/usr/local/bin\", \"bin\")\n" - " // -> [\"/\", \"usr\", \"local\", \"bin\"]\n" - " ```\n" -). --spec split(binary()) -> list(binary()). -split(Path) -> - case filepath_ffi:is_windows() of - true -> - split_windows(Path); - - false -> - split_unix(Path) - end. - --file("src/filepath.gleam", 240). -?DOC( - " Get the base name of a path, that is the name of the file without the\n" - " containing directory.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " base_name(\"/usr/local/bin\")\n" - " // -> \"bin\"\n" - " ```\n" -). --spec base_name(binary()) -> binary(). -base_name(Path) -> - gleam@bool:guard(Path =:= <<"/"/utf8>>, <<""/utf8>>, fun() -> _pipe = Path, - _pipe@1 = split(_pipe), - _pipe@2 = gleam@list:last(_pipe@1), - gleam@result:unwrap(_pipe@2, <<""/utf8>>) end). - --file("src/filepath.gleam", 190). -?DOC( - " Get the file extension of a path.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " extension(\"src/main.gleam\")\n" - " // -> Ok(\"gleam\")\n" - " ```\n" - "\n" - " ```gleam\n" - " extension(\"package.tar.gz\")\n" - " // -> Ok(\"gz\")\n" - " ```\n" -). --spec extension(binary()) -> {ok, binary()} | {error, nil}. -extension(Path) -> - File = base_name(Path), - case gleam@string:split(File, <<"."/utf8>>) of - [<<""/utf8>>, _] -> - {error, nil}; - - [_, Extension] -> - {ok, Extension}; - - [_ | Rest] -> - gleam@list:last(Rest); - - _ -> - {error, nil} - end. - --file("src/filepath.gleam", 219). -?DOC( - " Remove the extension from a file, if it has any.\n" - " \n" - " ## Examples\n" - " \n" - " ```gleam\n" - " strip_extension(\"src/main.gleam\")\n" - " // -> \"src/main\"\n" - " ```\n" - " \n" - " ```gleam\n" - " strip_extension(\"package.tar.gz\")\n" - " // -> \"package.tar\"\n" - " ```\n" - " \n" - " ```gleam\n" - " strip_extension(\"src/gleam\")\n" - " // -> \"src/gleam\"\n" - " ```\n" -). --spec strip_extension(binary()) -> binary(). -strip_extension(Path) -> - case extension(Path) of - {ok, Extension} -> - gleam@string:drop_end(Path, gleam@string:length(Extension) + 1); - - {error, nil} -> - Path - end. - --file("src/filepath.gleam", 324). -?DOC( - " Expand `..` and `.` segments in a path.\n" - "\n" - " If the path has a `..` segment that would go up past the root of the path\n" - " then an error is returned. This may be useful to example to ensure that a\n" - " path specified by a user does not go outside of a directory.\n" - "\n" - " If the path is absolute then the result will always be absolute.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " expand(\"/usr/local/../bin\")\n" - " // -> Ok(\"/usr/bin\")\n" - " ```\n" - "\n" - " ```gleam\n" - " expand(\"/tmp/../..\")\n" - " // -> Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " expand(\"src/../..\")\n" - " // -> Error(\"..\")\n" - " ```\n" -). --spec expand(binary()) -> {ok, binary()} | {error, nil}. -expand(Path) -> - Is_absolute = is_absolute(Path), - Result = begin - _pipe = Path, - _pipe@1 = split(_pipe), - _pipe@2 = root_slash_to_empty(_pipe@1), - _pipe@3 = expand_segments(_pipe@2, []), - gleam@result:map(_pipe@3, fun remove_trailing_slash/1) - end, - case Is_absolute andalso (Result =:= {ok, <<""/utf8>>}) of - true -> - {ok, <<"/"/utf8>>}; - - false -> - Result - end. diff --git a/ui/javascript/filepath/filepath.mjs b/ui/javascript/filepath/filepath.mjs deleted file mode 100644 index 40faa05..0000000 --- a/ui/javascript/filepath/filepath.mjs +++ /dev/null @@ -1,527 +0,0 @@ -import * as $bool from "../gleam_stdlib/gleam/bool.mjs"; -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $option from "../gleam_stdlib/gleam/option.mjs"; -import { None, Some } from "../gleam_stdlib/gleam/option.mjs"; -import * as $result from "../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../gleam_stdlib/gleam/string.mjs"; -import { is_windows } from "./filepath_ffi.mjs"; -import { Ok, Error, toList, Empty as $Empty, prepend as listPrepend, isEqual } from "./gleam.mjs"; - -const codepoint_z_up = 122; - -const codepoint_a_up = 97; - -const codepoint_z = 90; - -const codepoint_a = 65; - -const codepoint_colon = 58; - -const codepoint_backslash = 92; - -const codepoint_slash = 47; - -function remove_trailing_slash(path) { - let $ = $string.ends_with(path, "/"); - if ($) { - return $string.drop_end(path, 1); - } else { - return path; - } -} - -function relative(loop$path) { - while (true) { - let path = loop$path; - if (path.charCodeAt(0) === 47) { - let path$1 = path.slice(1); - loop$path = path$1; - } else { - return path; - } - } -} - -/** - * Join two paths together. - * - * This function does not expand `..` or `.` segments, use the `expand` - * function to do this. - * - * ## Examples - * - * ```gleam - * join("/usr/local", "bin") - * // -> "/usr/local/bin" - * ``` - */ -export function join(left, right) { - let _block; - if (right === "/") { - _block = left; - } else if (right.charCodeAt(0) === 47) { - if (left === "") { - _block = relative(right); - } else if (left === "/") { - _block = right; - } else { - let _pipe = remove_trailing_slash(left); - let _pipe$1 = $string.append(_pipe, "/"); - _block = $string.append(_pipe$1, relative(right)); - } - } else if (left === "") { - _block = relative(right); - } else if (left === "/") { - _block = left + right; - } else { - let _pipe = remove_trailing_slash(left); - let _pipe$1 = $string.append(_pipe, "/"); - _block = $string.append(_pipe$1, relative(right)); - } - let _pipe = _block; - return remove_trailing_slash(_pipe); -} - -/** - * Split a path into its segments, using `/` as the path separator. - * - * Typically you would want to use `split` instead of this function, but if you - * want non-Windows path behaviour on a Windows system then you can use this - * function. - * - * ## Examples - * - * ```gleam - * split("/usr/local/bin", "bin") - * // -> ["/", "usr", "local", "bin"] - * ``` - */ -export function split_unix(path) { - let _block; - let $ = $string.split(path, "/"); - if ($ instanceof $Empty) { - _block = $; - } else { - let $1 = $.tail; - if ($1 instanceof $Empty) { - let $2 = $.head; - if ($2 === "") { - _block = toList([]); - } else { - _block = $; - } - } else { - let $2 = $.head; - if ($2 === "") { - let rest = $1; - _block = listPrepend("/", rest); - } else { - _block = $; - } - } - } - let _pipe = _block; - return $list.filter(_pipe, (x) => { return x !== ""; }); -} - -function pop_windows_drive_specifier(path) { - let start = $string.slice(path, 0, 3); - let codepoints = $string.to_utf_codepoints(start); - let $ = $list.map(codepoints, $string.utf_codepoint_to_int); - if ($ instanceof $Empty) { - return [new None(), path]; - } else { - let $1 = $.tail; - if ($1 instanceof $Empty) { - return [new None(), path]; - } else { - let $2 = $1.tail; - if ($2 instanceof $Empty) { - return [new None(), path]; - } else { - let $3 = $2.tail; - if ($3 instanceof $Empty) { - let drive = $.head; - let colon = $1.head; - let slash = $2.head; - if ( - (((slash === 47) || (slash === 92)) && (colon === 58)) && (((drive >= 65) && (drive <= 90)) || ((drive >= 97) && (drive <= 122))) - ) { - let drive_letter = $string.slice(path, 0, 1); - let drive$1 = $string.lowercase(drive_letter) + ":/"; - let path$1 = $string.drop_start(path, 3); - return [new Some(drive$1), path$1]; - } else { - return [new None(), path]; - } - } else { - return [new None(), path]; - } - } - } - } -} - -/** - * Split a path into its segments, using `/` and `\` as the path separators. If - * there is a drive letter at the start of the path then it is lowercased. - * - * Typically you would want to use `split` instead of this function, but if you - * want Windows path behaviour on a non-Windows system then you can use this - * function. - * - * ## Examples - * - * ```gleam - * split("/usr/local/bin", "bin") - * // -> ["/", "usr", "local", "bin"] - * ``` - */ -export function split_windows(path) { - let $ = pop_windows_drive_specifier(path); - let drive = $[0]; - let path$1 = $[1]; - let _block; - let _pipe = $string.split(path$1, "/"); - _block = $list.flat_map( - _pipe, - (_capture) => { return $string.split(_capture, "\\"); }, - ); - let segments = _block; - let _block$1; - if (drive instanceof Some) { - let drive$1 = drive[0]; - _block$1 = listPrepend(drive$1, segments); - } else { - _block$1 = segments; - } - let segments$1 = _block$1; - if (segments$1 instanceof $Empty) { - return segments$1; - } else { - let $1 = segments$1.tail; - if ($1 instanceof $Empty) { - let $2 = segments$1.head; - if ($2 === "") { - return toList([]); - } else { - return segments$1; - } - } else { - let $2 = segments$1.head; - if ($2 === "") { - let rest = $1; - return listPrepend("/", rest); - } else { - return segments$1; - } - } - } -} - -/** - * Split a path into its segments. - * - * When running on Windows both `/` and `\` are treated as path separators, and - * if the path starts with a drive letter then the drive letter then it is - * lowercased. - * - * ## Examples - * - * ```gleam - * split("/usr/local/bin", "bin") - * // -> ["/", "usr", "local", "bin"] - * ``` - */ -export function split(path) { - let $ = is_windows(); - if ($) { - return split_windows(path); - } else { - return split_unix(path); - } -} - -/** - * Get the base name of a path, that is the name of the file without the - * containing directory. - * - * ## Examples - * - * ```gleam - * base_name("/usr/local/bin") - * // -> "bin" - * ``` - */ -export function base_name(path) { - return $bool.guard( - path === "/", - "", - () => { - let _pipe = path; - let _pipe$1 = split(_pipe); - let _pipe$2 = $list.last(_pipe$1); - return $result.unwrap(_pipe$2, ""); - }, - ); -} - -/** - * Get the file extension of a path. - * - * ## Examples - * - * ```gleam - * extension("src/main.gleam") - * // -> Ok("gleam") - * ``` - * - * ```gleam - * extension("package.tar.gz") - * // -> Ok("gz") - * ``` - */ -export function extension(path) { - let file = base_name(path); - let $ = $string.split(file, "."); - if ($ instanceof $Empty) { - return new Error(undefined); - } else { - let $1 = $.tail; - if ($1 instanceof $Empty) { - let rest = $1; - return $list.last(rest); - } else { - let $2 = $1.tail; - if ($2 instanceof $Empty) { - let $3 = $.head; - if ($3 === "") { - return new Error(undefined); - } else { - let extension$1 = $1.head; - return new Ok(extension$1); - } - } else { - let rest = $1; - return $list.last(rest); - } - } - } -} - -/** - * Remove the extension from a file, if it has any. - * - * ## Examples - * - * ```gleam - * strip_extension("src/main.gleam") - * // -> "src/main" - * ``` - * - * ```gleam - * strip_extension("package.tar.gz") - * // -> "package.tar" - * ``` - * - * ```gleam - * strip_extension("src/gleam") - * // -> "src/gleam" - * ``` - */ -export function strip_extension(path) { - let $ = extension(path); - if ($ instanceof Ok) { - let extension$1 = $[0]; - return $string.drop_end(path, $string.length(extension$1) + 1); - } else { - return path; - } -} - -function get_directory_name(loop$path, loop$acc, loop$segment) { - while (true) { - let path = loop$path; - let acc = loop$acc; - let segment = loop$segment; - if (path instanceof $Empty) { - return acc; - } else { - let $ = path.head; - if ($ === "/") { - let rest = path.tail; - loop$path = rest; - loop$acc = acc + segment; - loop$segment = "/"; - } else { - let first = $; - let rest = path.tail; - loop$path = rest; - loop$acc = acc; - loop$segment = segment + first; - } - } - } -} - -/** - * Get the directory name of a path, that is the path without the file name. - * - * ## Examples - * - * ```gleam - * directory_name("/usr/local/bin") - * // -> "/usr/local" - * ``` - */ -export function directory_name(path) { - let path$1 = remove_trailing_slash(path); - if (path$1.charCodeAt(0) === 47) { - let rest = path$1.slice(1); - return get_directory_name($string.to_graphemes(rest), "/", ""); - } else { - return get_directory_name($string.to_graphemes(path$1), "", ""); - } -} - -/** - * Check if a path is absolute. - * - * ## Examples - * - * ```gleam - * is_absolute("/usr/local/bin") - * // -> True - * ``` - * - * ```gleam - * is_absolute("usr/local/bin") - * // -> False - * ``` - */ -export function is_absolute(path) { - return $string.starts_with(path, "/"); -} - -function expand_segments(loop$path, loop$base) { - while (true) { - let path = loop$path; - let base = loop$base; - if (path instanceof $Empty) { - return new Ok($string.join($list.reverse(base), "/")); - } else if (base instanceof $Empty) { - let $ = path.head; - if ($ === "..") { - return new Error(undefined); - } else if ($ === ".") { - let path$1 = path.tail; - loop$path = path$1; - loop$base = base; - } else { - let s = $; - let path$1 = path.tail; - loop$path = path$1; - loop$base = listPrepend(s, base); - } - } else { - let $ = base.tail; - if ($ instanceof $Empty) { - let $1 = path.head; - if ($1 === "..") { - let $2 = base.head; - if ($2 === "") { - return new Error(undefined); - } else { - let path$1 = path.tail; - let base$1 = $; - loop$path = path$1; - loop$base = base$1; - } - } else if ($1 === ".") { - let path$1 = path.tail; - loop$path = path$1; - loop$base = base; - } else { - let s = $1; - let path$1 = path.tail; - loop$path = path$1; - loop$base = listPrepend(s, base); - } - } else { - let $1 = path.head; - if ($1 === "..") { - let path$1 = path.tail; - let base$1 = $; - loop$path = path$1; - loop$base = base$1; - } else if ($1 === ".") { - let path$1 = path.tail; - loop$path = path$1; - loop$base = base; - } else { - let s = $1; - let path$1 = path.tail; - loop$path = path$1; - loop$base = listPrepend(s, base); - } - } - } - } -} - -function root_slash_to_empty(segments) { - if (segments instanceof $Empty) { - return segments; - } else { - let $ = segments.head; - if ($ === "/") { - let rest = segments.tail; - return listPrepend("", rest); - } else { - return segments; - } - } -} - -/** - * Expand `..` and `.` segments in a path. - * - * If the path has a `..` segment that would go up past the root of the path - * then an error is returned. This may be useful to example to ensure that a - * path specified by a user does not go outside of a directory. - * - * If the path is absolute then the result will always be absolute. - * - * ## Examples - * - * ```gleam - * expand("/usr/local/../bin") - * // -> Ok("/usr/bin") - * ``` - * - * ```gleam - * expand("/tmp/../..") - * // -> Error(Nil) - * ``` - * - * ```gleam - * expand("src/../..") - * // -> Error("..") - * ``` - */ -export function expand(path) { - let is_absolute$1 = is_absolute(path); - let _block; - let _pipe = path; - let _pipe$1 = split(_pipe); - let _pipe$2 = root_slash_to_empty(_pipe$1); - let _pipe$3 = expand_segments(_pipe$2, toList([])); - _block = $result.map(_pipe$3, remove_trailing_slash); - let result = _block; - let $ = is_absolute$1 && (isEqual(result, new Ok(""))); - if ($) { - return new Ok("/"); - } else { - return result; - } -} diff --git a/ui/javascript/filepath/filepath_ffi.erl b/ui/javascript/filepath/filepath_ffi.erl deleted file mode 100644 index 2dde1aa..0000000 --- a/ui/javascript/filepath/filepath_ffi.erl +++ /dev/null @@ -1,9 +0,0 @@ --module(filepath_ffi). - --export([is_windows/0]). - -is_windows() -> - case os:type() of - {win32, _} -> true; - _ -> false - end. diff --git a/ui/javascript/filepath/filepath_ffi.mjs b/ui/javascript/filepath/filepath_ffi.mjs deleted file mode 100644 index 8919959..0000000 --- a/ui/javascript/filepath/filepath_ffi.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export function is_windows() { - return ( - globalThis?.process?.platform === "win32" || - globalThis?.Deno?.build?.os === "windows" - ); -} diff --git a/ui/javascript/filepath/gleam.mjs b/ui/javascript/filepath/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/ui/javascript/filepath/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/ui/javascript/fingerprint b/ui/javascript/fingerprint deleted file mode 100644 index bc085ca..0000000 --- a/ui/javascript/fingerprint +++ /dev/null @@ -1 +0,0 @@ -1.17.0 0 \ No newline at end of file diff --git a/ui/javascript/gleam_json/_gleam_artefacts/gleam@json.cache b/ui/javascript/gleam_json/_gleam_artefacts/gleam@json.cache deleted file mode 100644 index c1e4d95..0000000 Binary files a/ui/javascript/gleam_json/_gleam_artefacts/gleam@json.cache and /dev/null differ diff --git a/ui/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_meta b/ui/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_meta deleted file mode 100644 index 00dd819..0000000 Binary files a/ui/javascript/gleam_json/_gleam_artefacts/gleam@json.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_json/gleam.mjs b/ui/javascript/gleam_json/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/ui/javascript/gleam_json/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/ui/javascript/gleam_json/gleam/json.mjs b/ui/javascript/gleam_json/gleam/json.mjs deleted file mode 100644 index 3111ddc..0000000 --- a/ui/javascript/gleam_json/gleam/json.mjs +++ /dev/null @@ -1,325 +0,0 @@ -import * as $bit_array from "../../gleam_stdlib/gleam/bit_array.mjs"; -import * as $dict from "../../gleam_stdlib/gleam/dict.mjs"; -import * as $dynamic from "../../gleam_stdlib/gleam/dynamic.mjs"; -import * as $decode from "../../gleam_stdlib/gleam/dynamic/decode.mjs"; -import * as $list from "../../gleam_stdlib/gleam/list.mjs"; -import * as $option from "../../gleam_stdlib/gleam/option.mjs"; -import { None, Some } from "../../gleam_stdlib/gleam/option.mjs"; -import * as $result from "../../gleam_stdlib/gleam/result.mjs"; -import * as $string_tree from "../../gleam_stdlib/gleam/string_tree.mjs"; -import { Ok, Error, toList, prepend as listPrepend, CustomType as $CustomType } from "../gleam.mjs"; -import { - decode as decode_string, - json_to_string as do_to_string, - json_to_string as to_string_tree, - identity as do_string, - identity as do_bool, - identity as do_int, - identity as do_float, - do_null, - object as do_object, - array as do_preprocessed_array, -} from "../gleam_json_ffi.mjs"; - -export { to_string_tree }; - -export class UnexpectedEndOfInput extends $CustomType {} -export const DecodeError$UnexpectedEndOfInput = () => - new UnexpectedEndOfInput(); -export const DecodeError$isUnexpectedEndOfInput = (value) => - value instanceof UnexpectedEndOfInput; - -export class UnexpectedByte extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const DecodeError$UnexpectedByte = ($0) => new UnexpectedByte($0); -export const DecodeError$isUnexpectedByte = (value) => - value instanceof UnexpectedByte; -export const DecodeError$UnexpectedByte$0 = (value) => value[0]; - -export class UnexpectedSequence extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const DecodeError$UnexpectedSequence = ($0) => - new UnexpectedSequence($0); -export const DecodeError$isUnexpectedSequence = (value) => - value instanceof UnexpectedSequence; -export const DecodeError$UnexpectedSequence$0 = (value) => value[0]; - -export class UnableToDecode extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const DecodeError$UnableToDecode = ($0) => new UnableToDecode($0); -export const DecodeError$isUnableToDecode = (value) => - value instanceof UnableToDecode; -export const DecodeError$UnableToDecode$0 = (value) => value[0]; - -function do_parse(json, decoder) { - return $result.try$( - decode_string(json), - (dynamic_value) => { - let _pipe = $decode.run(dynamic_value, decoder); - return $result.map_error( - _pipe, - (var0) => { return new UnableToDecode(var0); }, - ); - }, - ); -} - -/** - * Decode a JSON string into dynamically typed data which can be decoded into - * typed data with the `gleam/dynamic` module. - * - * ## Examples - * - * ```gleam - * > parse("[1,2,3]", decode.list(of: decode.int)) - * Ok([1, 2, 3]) - * ``` - * - * ```gleam - * > parse("[", decode.list(of: decode.int)) - * Error(UnexpectedEndOfInput) - * ``` - * - * ```gleam - * > parse("1", decode.string) - * Error(UnableToDecode([decode.DecodeError("String", "Int", [])])) - * ``` - */ -export function parse(json, decoder) { - return do_parse(json, decoder); -} - -function decode_to_dynamic(json) { - let $ = $bit_array.to_string(json); - if ($ instanceof Ok) { - let string$1 = $[0]; - return decode_string(string$1); - } else { - return new Error(new UnexpectedByte("")); - } -} - -/** - * Decode a JSON bit string into dynamically typed data which can be decoded - * into typed data with the `gleam/dynamic` module. - * - * ## Examples - * - * ```gleam - * > parse_bits(<<"[1,2,3]">>, decode.list(of: decode.int)) - * Ok([1, 2, 3]) - * ``` - * - * ```gleam - * > parse_bits(<<"[">>, decode.list(of: decode.int)) - * Error(UnexpectedEndOfInput) - * ``` - * - * ```gleam - * > parse_bits(<<"1">>, decode.string) - * Error(UnableToDecode([decode.DecodeError("String", "Int", [])])), - * ``` - */ -export function parse_bits(json, decoder) { - return $result.try$( - decode_to_dynamic(json), - (dynamic_value) => { - let _pipe = $decode.run(dynamic_value, decoder); - return $result.map_error( - _pipe, - (var0) => { return new UnableToDecode(var0); }, - ); - }, - ); -} - -/** - * Convert a JSON value into a string. - * - * Where possible prefer the `to_string_tree` function as it is faster than - * this function, and BEAM VM IO is optimised for sending `StringTree` data. - * - * ## Examples - * - * ```gleam - * > to_string(array([1, 2, 3], of: int)) - * "[1,2,3]" - * ``` - */ -export function to_string(json) { - return do_to_string(json); -} - -/** - * Encode a string into JSON, using normal JSON escaping. - * - * ## Examples - * - * ```gleam - * > to_string(string("Hello!")) - * "\"Hello!\"" - * ``` - */ -export function string(input) { - return do_string(input); -} - -/** - * Encode a bool into JSON. - * - * ## Examples - * - * ```gleam - * > to_string(bool(False)) - * "false" - * ``` - */ -export function bool(input) { - return do_bool(input); -} - -/** - * Encode an int into JSON. - * - * ## Examples - * - * ```gleam - * > to_string(int(50)) - * "50" - * ``` - */ -export function int(input) { - return do_int(input); -} - -/** - * Encode a float into JSON. - * - * ## Examples - * - * ```gleam - * > to_string(float(4.7)) - * "4.7" - * ``` - */ -export function float(input) { - return do_float(input); -} - -/** - * The JSON value null. - * - * ## Examples - * - * ```gleam - * > to_string(null()) - * "null" - * ``` - */ -export function null$() { - return do_null(); -} - -/** - * Encode an optional value into JSON, using null if it is the `None` variant. - * - * ## Examples - * - * ```gleam - * > to_string(nullable(Some(50), of: int)) - * "50" - * ``` - * - * ```gleam - * > to_string(nullable(None, of: int)) - * "null" - * ``` - */ -export function nullable(input, inner_type) { - if (input instanceof Some) { - let value = input[0]; - return inner_type(value); - } else { - return null$(); - } -} - -/** - * Encode a list of key-value pairs into a JSON object. - * - * ## Examples - * - * ```gleam - * > to_string(object([ - * #("game", string("Pac-Man")), - * #("score", int(3333360)), - * ])) - * "{\"game\":\"Pac-Mac\",\"score\":3333360}" - * ``` - */ -export function object(entries) { - return do_object(entries); -} - -/** - * Encode a list of JSON values into a JSON array. - * - * ## Examples - * - * ```gleam - * > to_string(preprocessed_array([int(1), float(2.0), string("3")])) - * "[1, 2.0, \"3\"]" - * ``` - */ -export function preprocessed_array(from) { - return do_preprocessed_array(from); -} - -/** - * Encode a list into a JSON array. - * - * ## Examples - * - * ```gleam - * > to_string(array([1, 2, 3], of: int)) - * "[1, 2, 3]" - * ``` - */ -export function array(entries, inner_type) { - let _pipe = entries; - let _pipe$1 = $list.map(_pipe, inner_type); - return preprocessed_array(_pipe$1); -} - -/** - * Encode a Dict into a JSON object using the supplied functions to encode - * the keys and the values respectively. - * - * ## Examples - * - * ```gleam - * > to_string(dict(dict.from_list([ #(3, 3.0), #(4, 4.0)]), int.to_string, float) - * "{\"3\": 3.0, \"4\": 4.0}" - * ``` - */ -export function dict(dict, keys, values) { - return object( - $dict.fold( - dict, - toList([]), - (acc, k, v) => { return listPrepend([keys(k), values(v)], acc); }, - ), - ); -} diff --git a/ui/javascript/gleam_json/gleam@json.erl b/ui/javascript/gleam_json/gleam@json.erl deleted file mode 100644 index 8a33e49..0000000 --- a/ui/javascript/gleam_json/gleam@json.erl +++ /dev/null @@ -1,304 +0,0 @@ --module(gleam@json). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/json.gleam"). --export([parse_bits/2, parse/2, to_string/1, to_string_tree/1, string/1, bool/1, int/1, float/1, null/0, nullable/2, object/1, preprocessed_array/1, array/2, dict/3]). --export_type([json/0, decode_error/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type json() :: any(). - --type decode_error() :: unexpected_end_of_input | - {unexpected_byte, binary()} | - {unexpected_sequence, binary()} | - {unable_to_decode, list(gleam@dynamic@decode:decode_error())}. - --file("src/gleam/json.gleam", 88). -?DOC( - " Decode a JSON bit string into dynamically typed data which can be decoded\n" - " into typed data with the `gleam/dynamic` module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"[1,2,3]\">>, decode.list(of: decode.int))\n" - " Ok([1, 2, 3])\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"[\">>, decode.list(of: decode.int))\n" - " Error(UnexpectedEndOfInput)\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse_bits(<<\"1\">>, decode.string)\n" - " Error(UnableToDecode([decode.DecodeError(\"String\", \"Int\", [])])),\n" - " ```\n" -). --spec parse_bits(bitstring(), gleam@dynamic@decode:decoder(DNO)) -> {ok, DNO} | - {error, decode_error()}. -parse_bits(Json, Decoder) -> - gleam@result:'try'( - gleam_json_ffi:decode(Json), - fun(Dynamic_value) -> - _pipe = gleam@dynamic@decode:run(Dynamic_value, Decoder), - gleam@result:map_error( - _pipe, - fun(Field@0) -> {unable_to_decode, Field@0} end - ) - end - ). - --file("src/gleam/json.gleam", 47). --spec do_parse(binary(), gleam@dynamic@decode:decoder(DNI)) -> {ok, DNI} | - {error, decode_error()}. -do_parse(Json, Decoder) -> - Bits = gleam_stdlib:identity(Json), - parse_bits(Bits, Decoder). - --file("src/gleam/json.gleam", 39). -?DOC( - " Decode a JSON string into dynamically typed data which can be decoded into\n" - " typed data with the `gleam/dynamic` module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > parse(\"[1,2,3]\", decode.list(of: decode.int))\n" - " Ok([1, 2, 3])\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse(\"[\", decode.list(of: decode.int))\n" - " Error(UnexpectedEndOfInput)\n" - " ```\n" - "\n" - " ```gleam\n" - " > parse(\"1\", decode.string)\n" - " Error(UnableToDecode([decode.DecodeError(\"String\", \"Int\", [])]))\n" - " ```\n" -). --spec parse(binary(), gleam@dynamic@decode:decoder(DNE)) -> {ok, DNE} | - {error, decode_error()}. -parse(Json, Decoder) -> - do_parse(Json, Decoder). - --file("src/gleam/json.gleam", 117). -?DOC( - " Convert a JSON value into a string.\n" - "\n" - " Where possible prefer the `to_string_tree` function as it is faster than\n" - " this function, and BEAM VM IO is optimised for sending `StringTree` data.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(array([1, 2, 3], of: int))\n" - " \"[1,2,3]\"\n" - " ```\n" -). --spec to_string(json()) -> binary(). -to_string(Json) -> - gleam_json_ffi:json_to_string(Json). - --file("src/gleam/json.gleam", 140). -?DOC( - " Convert a JSON value into a string tree.\n" - "\n" - " Where possible prefer this function to the `to_string` function as it is\n" - " slower than this function, and BEAM VM IO is optimised for sending\n" - " `StringTree` data.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string_tree(array([1, 2, 3], of: int))\n" - " string_tree.from_string(\"[1,2,3]\")\n" - " ```\n" -). --spec to_string_tree(json()) -> gleam@string_tree:string_tree(). -to_string_tree(Json) -> - gleam_json_ffi:json_to_iodata(Json). - --file("src/gleam/json.gleam", 151). -?DOC( - " Encode a string into JSON, using normal JSON escaping.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(string(\"Hello!\"))\n" - " \"\\\"Hello!\\\"\"\n" - " ```\n" -). --spec string(binary()) -> json(). -string(Input) -> - gleam_json_ffi:string(Input). - --file("src/gleam/json.gleam", 168). -?DOC( - " Encode a bool into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(bool(False))\n" - " \"false\"\n" - " ```\n" -). --spec bool(boolean()) -> json(). -bool(Input) -> - gleam_json_ffi:bool(Input). - --file("src/gleam/json.gleam", 185). -?DOC( - " Encode an int into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(int(50))\n" - " \"50\"\n" - " ```\n" -). --spec int(integer()) -> json(). -int(Input) -> - gleam_json_ffi:int(Input). - --file("src/gleam/json.gleam", 202). -?DOC( - " Encode a float into JSON.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(float(4.7))\n" - " \"4.7\"\n" - " ```\n" -). --spec float(float()) -> json(). -float(Input) -> - gleam_json_ffi:float(Input). - --file("src/gleam/json.gleam", 219). -?DOC( - " The JSON value null.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(null())\n" - " \"null\"\n" - " ```\n" -). --spec null() -> json(). -null() -> - gleam_json_ffi:null(). - --file("src/gleam/json.gleam", 241). -?DOC( - " Encode an optional value into JSON, using null if it is the `None` variant.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(nullable(Some(50), of: int))\n" - " \"50\"\n" - " ```\n" - "\n" - " ```gleam\n" - " > to_string(nullable(None, of: int))\n" - " \"null\"\n" - " ```\n" -). --spec nullable(gleam@option:option(DNU), fun((DNU) -> json())) -> json(). -nullable(Input, Inner_type) -> - case Input of - {some, Value} -> - Inner_type(Value); - - none -> - null() - end. - --file("src/gleam/json.gleam", 260). -?DOC( - " Encode a list of key-value pairs into a JSON object.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(object([\n" - " #(\"game\", string(\"Pac-Man\")),\n" - " #(\"score\", int(3333360)),\n" - " ]))\n" - " \"{\\\"game\\\":\\\"Pac-Mac\\\",\\\"score\\\":3333360}\"\n" - " ```\n" -). --spec object(list({binary(), json()})) -> json(). -object(Entries) -> - gleam_json_ffi:object(Entries). - --file("src/gleam/json.gleam", 292). -?DOC( - " Encode a list of JSON values into a JSON array.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(preprocessed_array([int(1), float(2.0), string(\"3\")]))\n" - " \"[1, 2.0, \\\"3\\\"]\"\n" - " ```\n" -). --spec preprocessed_array(list(json())) -> json(). -preprocessed_array(From) -> - gleam_json_ffi:array(From). - --file("src/gleam/json.gleam", 277). -?DOC( - " Encode a list into a JSON array.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(array([1, 2, 3], of: int))\n" - " \"[1, 2, 3]\"\n" - " ```\n" -). --spec array(list(DNY), fun((DNY) -> json())) -> json(). -array(Entries, Inner_type) -> - _pipe = Entries, - _pipe@1 = gleam@list:map(_pipe, Inner_type), - preprocessed_array(_pipe@1). - --file("src/gleam/json.gleam", 310). -?DOC( - " Encode a Dict into a JSON object using the supplied functions to encode\n" - " the keys and the values respectively.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " > to_string(dict(dict.from_list([ #(3, 3.0), #(4, 4.0)]), int.to_string, float)\n" - " \"{\\\"3\\\": 3.0, \\\"4\\\": 4.0}\"\n" - " ```\n" -). --spec dict( - gleam@dict:dict(DOC, DOD), - fun((DOC) -> binary()), - fun((DOD) -> json()) -) -> json(). -dict(Dict, Keys, Values) -> - object( - gleam@dict:fold( - Dict, - [], - fun(Acc, K, V) -> [{Keys(K), Values(V)} | Acc] end - ) - ). diff --git a/ui/javascript/gleam_json/gleam_json_ffi.erl b/ui/javascript/gleam_json/gleam_json_ffi.erl deleted file mode 100644 index 06a26a0..0000000 --- a/ui/javascript/gleam_json/gleam_json_ffi.erl +++ /dev/null @@ -1,66 +0,0 @@ --module(gleam_json_ffi). - --export([ - decode/1, json_to_iodata/1, json_to_string/1, int/1, float/1, string/1, - bool/1, null/0, array/1, object/1 -]). - --if(?OTP_RELEASE < 27). --define(bad_version, - error({erlang_otp_27_required, << "Insufficient Erlang/OTP version. - -`gleam_json` uses the Erlang `json` module introduced in Erlang/OTP 27. -You are using Erlang/OTP "/utf8, (integer_to_binary(?OTP_RELEASE))/binary, " -Please upgrade your Erlang install or downgrade to `gleam_json` v1.0.1. -"/utf8>>})). - -decode(_) -> ?bad_version. -json_to_iodata(_) -> ?bad_version. -json_to_string(_) -> ?bad_version. -int(_) -> ?bad_version. -float(_) -> ?bad_version. -string(_) -> ?bad_version. -bool(_) -> ?bad_version. -array(_) -> ?bad_version. -object(_) -> ?bad_version. -null() -> ?bad_version. --else. - -decode(Json) -> - try - {ok, json:decode(Json)} - catch - error:unexpected_end -> {error, unexpected_end_of_input}; - error:{invalid_byte, Byte} -> {error, {unexpected_byte, hex(Byte)}}; - error:{unexpected_sequence, Byte} -> {error, {unexpected_sequence, Byte}} - end. - -hex(I) -> - H = list_to_binary(integer_to_list(I, 16)), - <<"0x"/utf8, H/binary>>. - -json_to_iodata(Json) -> - Json. - -json_to_string(Json) when is_binary(Json) -> - Json; -json_to_string(Json) when is_list(Json) -> - list_to_binary(Json). - -null() -> <<"null">>. -bool(true) -> <<"true">>; -bool(false) -> <<"false">>. -int(X) -> json:encode_integer(X). -float(X) -> json:encode_float(X). -string(X) -> json:encode_binary(X). - -array([]) -> <<"[]">>; -array([First | Rest]) -> [$[, First | array_loop(Rest)]. -array_loop([]) -> "]"; -array_loop([Elem | Rest]) -> [$,, Elem | array_loop(Rest)]. - -object(List) -> encode_object([[$,, string(Key), $: | Value] || {Key, Value} <- List]). -encode_object([]) -> <<"{}">>; -encode_object([[_Comma | Entry] | Rest]) -> ["{", Entry, Rest, "}"]. - --endif. diff --git a/ui/javascript/gleam_json/gleam_json_ffi.mjs b/ui/javascript/gleam_json/gleam_json_ffi.mjs deleted file mode 100644 index 1d8d3ff..0000000 --- a/ui/javascript/gleam_json/gleam_json_ffi.mjs +++ /dev/null @@ -1,201 +0,0 @@ -import { - Result$Ok, - Result$Error, - List$isNonEmpty, - List$NonEmpty$first, - List$NonEmpty$rest, -} from "./gleam.mjs"; -import { - DecodeError$UnexpectedByte, - DecodeError$UnexpectedEndOfInput, -} from "./gleam/json.mjs"; - -export function json_to_string(json) { - return JSON.stringify(json); -} - -export function object(entries) { - return Object.fromEntries(entries); -} - -export function identity(x) { - return x; -} - -export function array(list) { - const array = []; - while (List$isNonEmpty(list)) { - array.push(List$NonEmpty$first(list)); - list = List$NonEmpty$rest(list); - } - return array; -} - -export function do_null() { - return null; -} - -export function decode(string) { - try { - const result = JSON.parse(string); - return Result$Ok(result); - } catch (err) { - return Result$Error(getJsonDecodeError(err, string)); - } -} - -export function getJsonDecodeError(stdErr, json) { - if (isUnexpectedEndOfInput(stdErr)) return DecodeError$UnexpectedEndOfInput(); - return toUnexpectedByteError(stdErr, json); -} - -/** - * Matches unexpected end of input messages in: - * - Chromium (edge, chrome, node) - * - Spidermonkey (firefox) - * - JavascriptCore (safari) - * - * Note that Spidermonkey and JavascriptCore will both incorrectly report some - * UnexpectedByte errors as UnexpectedEndOfInput errors. For example: - * - * @example - * // in JavascriptCore - * JSON.parse('{"a"]: "b"}) - * // => JSON Parse error: Expected ':' before value - * - * JSON.parse('{"a"') - * // => JSON Parse error: Expected ':' before value - * - * // in Chromium (correct) - * JSON.parse('{"a"]: "b"}) - * // => Unexpected token ] in JSON at position 4 - * - * JSON.parse('{"a"') - * // => Unexpected end of JSON input - */ -function isUnexpectedEndOfInput(err) { - const unexpectedEndOfInputRegex = - /((unexpected (end|eof))|(end of data)|(unterminated string)|(json( parse error|\.parse)\: expected '(\:|\}|\])'))/i; - return unexpectedEndOfInputRegex.test(err.message); -} - -/** - * Converts a SyntaxError to an UnexpectedByte error based on the JS runtime. - * - * For Chromium, the unexpected byte and position are reported by the runtime. - * - * For JavascriptCore, only the unexpected byte is reported by the runtime, so - * there is no way to know which position that character is in unless we then - * parse the string again ourselves. So instead, the position is reported as 0. - * - * For Spidermonkey, the position is reported by the runtime as a line and column number - * and the unexpected byte is found using those coordinates. - */ -function toUnexpectedByteError(err, json) { - let converters = [ - v8UnexpectedByteError, - oldV8UnexpectedByteError, - jsCoreUnexpectedByteError, - spidermonkeyUnexpectedByteError, - ]; - - for (let converter of converters) { - let result = converter(err, json); - if (result) return result; - } - - return DecodeError$UnexpectedByte(""); -} - -/** - * Matches unexpected byte messages in: - * - V8 (edge, chrome, node) - * - * Matches the character but not the position as this is no longer reported by - * V8. Boo! - */ -function v8UnexpectedByteError(err) { - const regex = /unexpected token '(.)', ".+" is not valid JSON/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[1]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - V8 (edge, chrome, node) - * - * No longer works in current versions of V8. - * - * Matches the character and its position. - */ -function oldV8UnexpectedByteError(err) { - const regex = /unexpected token (.) in JSON at position (\d+)/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[1]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - Spidermonkey (firefox) - * - * Matches the position in a 2d grid only and not the character. - */ -function spidermonkeyUnexpectedByteError(err, json) { - const regex = - /(unexpected character|expected .*) at line (\d+) column (\d+)/i; - const match = regex.exec(err.message); - if (!match) return null; - const line = Number(match[2]); - const column = Number(match[3]); - const position = getPositionFromMultiline(line, column, json); - const byte = toHex(json[position]); - return DecodeError$UnexpectedByte(byte); -} - -/** - * Matches unexpected byte messages in: - * - JavascriptCore (safari) - * - * JavascriptCore only reports what the character is and not its position. - */ -function jsCoreUnexpectedByteError(err) { - const regex = /unexpected (identifier|token) "(.)"/i; - const match = regex.exec(err.message); - if (!match) return null; - const byte = toHex(match[2]); - return DecodeError$UnexpectedByte(byte); -} - -function toHex(char) { - return "0x" + char.charCodeAt(0).toString(16).toUpperCase(); -} - -/** - * Gets the position of a character in a flattened (i.e. single line) string - * from a line and column number. Note that the position is 0-indexed and - * the line and column numbers are 1-indexed. - * - * @param {number} line - * @param {number} column - * @param {string} string - */ -function getPositionFromMultiline(line, column, string) { - if (line === 1) return column - 1; - - let currentLn = 1; - let position = 0; - string.split("").find((char, idx) => { - if (char === "\n") currentLn += 1; - if (currentLn === line) { - position = idx + column; - return true; - } - return false; - }); - - return position; -} diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache deleted file mode 100644 index dd36389..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta deleted file mode 100644 index def47b4..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache deleted file mode 100644 index 3a4cc10..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta deleted file mode 100644 index aba21b2..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache deleted file mode 100644 index 48786b3..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta deleted file mode 100644 index 7b84352..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache deleted file mode 100644 index 02626f2..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta deleted file mode 100644 index 0670deb..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache deleted file mode 100644 index eee6716..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta deleted file mode 100644 index d7749a3..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache deleted file mode 100644 index a70d57e..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta deleted file mode 100644 index c3cd308..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache deleted file mode 100644 index 1de1e2a..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta deleted file mode 100644 index c7c8567..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache deleted file mode 100644 index 7a354be..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta deleted file mode 100644 index 5535ba4..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache deleted file mode 100644 index b71adc6..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta deleted file mode 100644 index 2a8b055..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache deleted file mode 100644 index 5ff57f4..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta deleted file mode 100644 index 42d0fc4..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache deleted file mode 100644 index aedc7af..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta deleted file mode 100644 index 39de384..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache deleted file mode 100644 index 6644548..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta deleted file mode 100644 index f73711e..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache deleted file mode 100644 index 15cf4a0..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta deleted file mode 100644 index 1777c36..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache deleted file mode 100644 index dcba3ab..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta deleted file mode 100644 index 6c3cb8b..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache deleted file mode 100644 index e4f1dc4..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta deleted file mode 100644 index e5481e5..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache deleted file mode 100644 index 2a77993..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta deleted file mode 100644 index 82dcad0..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache deleted file mode 100644 index 39da947..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta deleted file mode 100644 index d7b6a52..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache deleted file mode 100644 index 8f8e09c..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta deleted file mode 100644 index c89575a..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache deleted file mode 100644 index 04e5979..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta b/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta deleted file mode 100644 index dd57e64..0000000 Binary files a/ui/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta and /dev/null differ diff --git a/ui/javascript/gleam_stdlib/dict.mjs b/ui/javascript/gleam_stdlib/dict.mjs deleted file mode 100644 index 3db3b5f..0000000 --- a/ui/javascript/gleam_stdlib/dict.mjs +++ /dev/null @@ -1,710 +0,0 @@ -/** - * This file uses jsdoc to annotate types. - * These types can be checked using the typescript compiler with "checkjs" option. - */ - -import { isEqual, Result$Error, Result$Ok } from "./gleam.mjs"; - -// -- HASH -------------------------------------------------------------------- - -const referenceMap = /* @__PURE__ */ new WeakMap(); -const tempDataView = /* @__PURE__ */ new DataView( - /* @__PURE__ */ new ArrayBuffer(8), -); -let referenceUID = 0; -/** - * hash the object by reference using a weak map and incrementing uid - * @param {any} o - * @returns {number} - */ -function hashByReference(o) { - const known = referenceMap.get(o); - if (known !== undefined) { - return known; - } - const hash = referenceUID++; - if (referenceUID === 0x7fffffff) { - referenceUID = 0; - } - referenceMap.set(o, hash); - return hash; -} - -/** - * merge two hashes in an order sensitive way - * @param {number} a - * @param {number} b - * @returns {number} - */ -function hashMerge(a, b) { - return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; -} - -/** - * standard string hash popularised by Java - * @param {string} s - * @returns {number} - */ -function hashString(s) { - let hash = 0; - const len = s.length; - for (let i = 0; i < len; i++) { - hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0; - } - return hash; -} - -/** - * hash a number by converting to two integers and do some jumbling - * @param {number} n - * @returns {number} - */ -function hashNumber(n) { - tempDataView.setFloat64(0, n); - const i = tempDataView.getInt32(0); - const j = tempDataView.getInt32(4); - return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j; -} - -/** - * hash a BigInt by converting it to a string and hashing that - * @param {BigInt} n - * @returns {number} - */ -function hashBigInt(n) { - return hashString(n.toString()); -} - -/** - * hash any js object - * @param {any} o - * @returns {number} - */ -function hashObject(o) { - const proto = Object.getPrototypeOf(o); - if (proto !== null && typeof proto.hashCode === "function") { - try { - const code = o.hashCode(o); - if (typeof code === "number") { - return code; - } - } catch {} - } - if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { - return hashByReference(o); - } - if (o instanceof Date) { - return hashNumber(o.getTime()); - } - let h = 0; - if (o instanceof ArrayBuffer) { - o = new Uint8Array(o); - } - if (Array.isArray(o) || o instanceof Uint8Array) { - for (let i = 0; i < o.length; i++) { - h = (Math.imul(31, h) + getHash(o[i])) | 0; - } - } else if (o instanceof Set) { - o.forEach((v) => { - h = (h + getHash(v)) | 0; - }); - } else if (o instanceof Map) { - o.forEach((v, k) => { - h = (h + hashMerge(getHash(v), getHash(k))) | 0; - }); - } else { - const keys = Object.keys(o); - for (let i = 0; i < keys.length; i++) { - const k = keys[i]; - const v = o[k]; - h = (h + hashMerge(getHash(v), hashString(k))) | 0; - } - } - return h; -} - -/** - * hash any js value - * @param {any} u - * @returns {number} - */ -export function getHash(u) { - if (u === null) return 0x42108422; - if (u === undefined) return 0x42108423; - if (u === true) return 0x42108421; - if (u === false) return 0x42108420; - switch (typeof u) { - case "number": - return hashNumber(u); - case "string": - return hashString(u); - case "bigint": - return hashBigInt(u); - case "object": - return hashObject(u); - case "symbol": - return hashByReference(u); - case "function": - return hashByReference(u); - default: - return 0; // should be unreachable - } -} - -// -- DICT -------------------------------------------------------------------- - -/** - * An implementation of the CHAMP data structure, an optimised HAMT. - * - * See: M. J. Steindorfer, J.J. Vinju (2015). Optimizing Hash-Array Mapped Tries for - Fast and Lean Immutable JVM Collections. Available: https://michael.steindorfer.name/publications/oopsla15.pdf - */ -export default class Dict { - constructor(size, root) { - this.size = size; - this.root = root; - } -} - -/// The power-of-2 branching factor for the dict. For example, a value of `5` indicates a 32-ary tree. -const bits = 5; -const mask = (1 << bits) - 1; - -/// This symbol is used internally to avoid constructing results. -const noElementMarker = Symbol(); - -/// This symbol is used to store the "generation" on a node. -/// Using a symbol makes the property not enumerable, which means the generation -/// will be ignored during equality checks. -const generationKey = Symbol(); - -// Some commonly used constants throughout the code. -const emptyNode = /* @__PURE__ */ newNode(0); -const emptyDict = /* @__PURE__ */ new Dict(0, emptyNode); -const errorNil = /* @__PURE__ */ Result$Error(undefined); - -function makeNode(generation, datamap, nodemap, data) { - // The order of fields is important, as they define the order `isEqual` will - // compare our fields. Putting the bitmaps first means that equality can - // early-out if the bitmaps are not equal. - return { - // A node is a high-arity (32 in practice) hybrid tree node. - // Hybrid means that it stores data directly as well as pointers to child nodes. - // - // Each node contains 2 bitmaps: - // - The datamap has a bit set if that slot in the node contains direct data - // - The nodemap has a bit set if that slot in the node contains another node. - // - // Both are exclusive to on another, so datamap & nodemap == 0. - // - // Every key/hash value directly correlates to a specific bit by using a trie - // suffix (least significant bits first) encoding. - // For example, if the last 5 bits of the hash are 1101, the bit to check for - // that value is the 13th bit. - datamap, - nodemap, - // The slots itself are stored in a single contiguous array that contains - // both direct k/v-pairs and child nodes. - // - // The direct children come first, followed by the child nodes in _reverse order_: - // - // 7654321 - // datamap: 1000100 - // nodemap: 10011 - // data: [key3, value3, key7, value7, child5, child2, child1] - // -------------------------> <--------------------- - // datamap nodemap - // - // Every `1` bit in the datamap corresponds to a pair of [key, value] entries, - // and every `1` bit in the nodemap corresponds to a child node entry. - // - // Children are stored in reverse order to avoid having to store or calculate an - // "offset" value to skip over the direct children. - data, - // The generation is used to track which nodes need to be copied during transient updates. - // Using a symbol here makes `isEqual` ignore this field. - [generationKey]: generation, - }; -} - -function newNode(generation) { - return makeNode(generation, 0, 0, []); -} - -/** - * Copies a node and its data array if it's from another generation, making it safe - * to mutate the node. - */ -function copyNode(node, generation) { - if (node[generationKey] === generation) { - return node; - } - - const newData = node.data.slice(0); - return makeNode(generation, node.datamap, node.nodemap, newData); -} - -/** - * Copies a node if needed and sets a new value. - */ -function copyAndSet(node, generation, idx, val) { - if (node.data[idx] === val) { - return node; - } - - // Using copyNode is faster than a specialised implementation. - node = copyNode(node, generation); - node.data[idx] = val; - return node; -} - -/** - * Copies a node if needed, and then inserts a new key-value pair. - */ -function copyAndInsertPair(node, generation, bit, idx, key, val) { - const data = node.data; - const length = data.length; - - // the fastest way to insert a pair is to always copy. - const newData = new Array(length + 2); - - let readIndex = 0; - let writeIndex = 0; - - while (readIndex < idx) newData[writeIndex++] = data[readIndex++]; - newData[writeIndex++] = key; - newData[writeIndex++] = val; - while (readIndex < length) newData[writeIndex++] = data[readIndex++]; - - return makeNode(generation, node.datamap | bit, node.nodemap, newData); -} - -function copyAndRemovePair(node, generation, bit, idx) { - node = copyNode(node, generation); - - const data = node.data; - const length = data.length; - for (let w = idx, r = idx + 2; r < length; ++r, ++w) { - data[w] = data[r]; - } - data.pop(); - data.pop(); - - node.datamap ^= bit; - return node; -} - -export function make() { - return emptyDict; -} - -export function from(iterable) { - let transient = toTransient(emptyDict); - for (const [key, value] of iterable) { - transient = destructiveTransientInsert(key, value, transient); - } - return fromTransient(transient); -} - -export function size(dict) { - return dict.size; -} - -export function get(dict, key) { - const result = lookup(dict.root, key, getHash(key)); - return result !== noElementMarker ? Result$Ok(result) : errorNil; -} - -export function has(dict, key) { - return lookup(dict.root, key, getHash(key)) !== noElementMarker; -} - -function lookup(node, key, hash) { - for (let shift = 0; shift < 32; shift += bits) { - const data = node.data; - const bit = hashbit(hash, shift); - - if (node.nodemap & bit) { - // we found our hash inside the nodemap, so we can continue our search there. - node = data[data.length - 1 - index(node.nodemap, bit)]; - } else if (node.datamap & bit) { - // we store this hash directly! - // - // this also means that there are no other values with the same - // hash prefix in this dict. - // - // We still need to check if the key matches, but if it does we know for - // sure that this is the correct value, and if it doesn't that we don't - // contain the value in question. - const dataidx = Math.imul(index(node.datamap, bit), 2); - return isEqual(key, data[dataidx]) ? data[dataidx + 1] : noElementMarker; - } else { - // if the hash bit is not set in neither bitmaps, we immediately know that - // this key cannot be inside this dict. - return noElementMarker; - } - } - - // our shift has exceeded 32 bits. Everything that follows is - // implicitely an overflow node and only contains direct children. - const overflow = node.data; - for (let i = 0; i < overflow.length; i += 2) { - if (isEqual(key, overflow[i])) { - return overflow[i + 1]; - } - } - - return noElementMarker; -} - -/** - * We use "transient" values to allow for safer internal mutations of the data - * structure. This is an optimisation only. No mutable API is exposed to the user. - * - * Transients are to be treated as having a linear (single-use, think rust) type. - * A transient value becomes invalid as soon as it's passed to one of the functions. - * - * Internally, we track a "generation" value on each node. If the generation - * doesn't match the one for the current transient, we have to copy - the node - * could still be referenced by another dict instance! - * After that, no other references than the transient one exists, so it's safe - * to mutate in place. - */ -export function toTransient(dict) { - return { - generation: nextGeneration(dict), - root: dict.root, - size: dict.size, - dict: dict, - }; -} - -/** - * Consume a transient, producing a normal Dict again. - */ -export function fromTransient(transient) { - if (transient.root === transient.dict.root) { - return transient.dict; - } - - return new Dict(transient.size, transient.root); -} - -/** - * Find and allocate the next generation id. - * - * @template K,V - * @param {Dict} dict - * @returns {number} - */ -function nextGeneration(dict) { - const root = dict.root; - if (root[generationKey] < Number.MAX_SAFE_INTEGER) { - return root[generationKey] + 1; - } - - // we have reached MAX_SAFE_INTEGER generations - - // at this point, we have to walk the dictionary once to reset the counter - // on every node. This is safe since it's part of the contract for transient - // that only one of them exists at any given time. - // - const queue = [root]; - while (queue.length) { - // order doesn't matter, so we can use push/pop for faster array usage. - const node = queue.pop(); - - // reset the generation to 0 - node[generationKey] = 0; - - // queue all other referenced nodes - // We need to query the length from the nodemap, as we don't know if this - // is an overflow node or not! if it is, it will never have datamap set! - const nodeStart = data.length - popcount(node.nodemap); - for (let i = nodeStart; i < node.data.length; ++i) { - queue.push(node.data[i]); - } - } - - return 1; -} - -/// Insert is the second-most performance-sensitive operation. -/// We use a global "transient" value here to avoid doing a memory allocation. -const globalTransient = /* @__PURE__ */ toTransient(emptyDict); - -export function insert(dict, key, value) { - globalTransient.generation = nextGeneration(dict); - globalTransient.size = dict.size; - - const hash = getHash(key); - const root = insertIntoNode(globalTransient, dict.root, key, value, hash, 0); - if (root === dict.root) { - return dict; - } - - return new Dict(globalTransient.size, root); -} - -/** - * Consume a transient, writing a new key/value pair into the dictionary it - * represents. If the key already exists, it will be overwritten. - * - * Returns a new transient. - */ -export function destructiveTransientInsert(key, value, transient) { - const hash = getHash(key); - transient.root = insertIntoNode(transient, transient.root, key, value, hash, 0); - return transient; -} - -/** - * Consume a transient, writing a new key/value pair if the key doesn't exist or updating - * the existing value with a function if it does. - * - * Returns a new transient. - */ -export function destructiveTransientUpdateWith(key, fun, value, transient) { - const hash = getHash(key); - - const existing = lookup(transient.root, key, hash); - if (existing !== noElementMarker) { - value = fun(existing); - } - transient.root = insertIntoNode(transient, transient.root, key, value, hash, 0); - return transient; -} - -function insertIntoNode(transient, node, key, value, hash, shift) { - const data = node.data; - const generation = transient.generation; - - // 1. Overflow Node - // overflow nodes only contain key/value-pairs. we walk the data linearly trying to find a match. - if (shift > 32) { - for (let i = 0; i < data.length; i += 2) { - if (isEqual(key, data[i])) { - return copyAndSet(node, generation, i + 1, value); - } - } - - transient.size += 1; - return copyAndInsertPair(node, generation, 0, data.length, key, value); - } - - const bit = hashbit(hash, shift); - - // 2. Child Node - // We have to check first if there is already a child node we have to traverse to. - if (node.nodemap & bit) { - const nodeidx = data.length - 1 - index(node.nodemap, bit); - - let child = data[nodeidx]; - child = insertIntoNode(transient, child, key, value, hash, shift + bits); - return copyAndSet(node, generation, nodeidx, child); - } - - // 3. New Data Node - // No child node and no data node exists yet, so we can potentially just insert a new value. - const dataidx = Math.imul(index(node.datamap, bit), 2); - if ((node.datamap & bit) === 0) { - transient.size += 1; - return copyAndInsertPair(node, generation, bit, dataidx, key, value); - } - - // 4. Existing Data Node - // We have a match that we can update, or remove. - if (isEqual(key, data[dataidx])) { - return copyAndSet(node, generation, dataidx + 1, value); - } - - // 5. Collision - // There is no child node, but a data node with the same hash, but with a different key. - // To resolve this, we push both nodes down one level. - const childShift = shift + bits; - - let child = emptyNode; - child = insertIntoNode(transient, child, key, value, hash, childShift); - - const key2 = data[dataidx]; - const value2 = data[dataidx + 1]; - const hash2 = getHash(key2); - child = insertIntoNode(transient, child, key2, value2, hash2, childShift); - - // we inserted 2 elements, but implicitely deleted the one we pushed down from the datamap. - transient.size -= 1; - - // remove the old data pair, and insert the new child node. - const length = data.length; - const nodeidx = length - 1 - index(node.nodemap, bit); - - // writing these loops in javascript instead of a combination of splices - // turns out to be faster. Copying always turned out to be faster. - const newData = new Array(length - 1); - - let readIndex = 0; - let writeIndex = 0; - - // [0..dataidx, skip 2 elements, ..nodeidx, newChild, ..rest] - while (readIndex < dataidx) newData[writeIndex++] = data[readIndex++]; - readIndex += 2; - while (readIndex <= nodeidx) newData[writeIndex++] = data[readIndex++]; - newData[writeIndex++] = child; - while (readIndex < length) newData[writeIndex++] = data[readIndex++]; - - return makeNode(generation, node.datamap ^ bit, node.nodemap | bit, newData); -} - -/** - * Consume a transient, removing a key if it exists. - * Returns a new transient. - */ -export function destructiveTransientDelete(key, transient) { - const hash = getHash(key); - transient.root = deleteFromNode(transient, transient.root, key, hash, 0); - return transient; -} - -function deleteFromNode(transient, node, key, hash, shift) { - const data = node.data; - const generation = transient.generation; - - // 1. Overflow Node - // overflow nodes only contain key/value-pairs. we walk the data linearly trying to find a match. - if (shift > 32) { - for (let i = 0; i < data.length; i += 2) { - if (isEqual(key, data[i])) { - transient.size -= 1; - return copyAndRemovePair(node, generation, 0, i); - } - } - - return node; - } - - const bit = hashbit(hash, shift); - const dataidx = Math.imul(index(node.datamap, bit), 2); - - // 2. Child Node - // We have to check first if there is already a child node we have to traverse to. - if ((node.nodemap & bit) !== 0) { - const nodeidx = data.length - 1 - index(node.nodemap, bit); - - let child = data[nodeidx]; - child = deleteFromNode(transient, child, key, hash, shift + bits); - - // the node did change, so let's copy to incorporate that change. - if (child.nodemap !== 0 || child.data.length > 2) { - return copyAndSet(node, generation, nodeidx, child); - } - - // this node only has a single data (k/v-pair) child. - // to restore the CHAMP invariant, we "pull" that pair up into ourselves. - // this ensures that every tree stays in its single optimal representation, - // and allows dicts to be structurally compared. - const length = data.length; - const newData = new Array(length + 1); - - let readIndex = 0; - let writeIndex = 0; - - while (readIndex < dataidx) newData[writeIndex++] = data[readIndex++]; - newData[writeIndex++] = child.data[0]; - newData[writeIndex++] = child.data[1]; - while (readIndex < nodeidx) newData[writeIndex++] = data[readIndex++]; - readIndex++; - while (readIndex < length) newData[writeIndex++] = data[readIndex++]; - - return makeNode(generation, node.datamap | bit, node.nodemap ^ bit, newData); - } - - // 3. Data Node - // There is no data entry here, or it is a prefix for a different key - if ((node.datamap & bit) === 0 || !isEqual(key, data[dataidx])) { - return node; - } - - // we found a data entry that we can delete. - transient.size -= 1; - return copyAndRemovePair(node, generation, bit, dataidx); -} - -export function map(dict, fun) { - // map can never modify the structure, so we can walk the dictionary directly, - // but still move to a new generation to make sure we get a new copy of every node. - const generation = nextGeneration(dict); - const root = copyNode(dict.root, generation); - const queue = [root]; - - while (queue.length) { - // order doesn't matter, so we can use push/pop for faster array usage. - const node = queue.pop(); - const data = node.data; - // every node contains popcount(datamap) direct entries - // We need to query the length from the nodemap, as we don't know if this - // is an overflow node or not! if it is, it will never have datamap set! - const edgesStart = data.length - popcount(node.nodemap); - for (let i = 0; i < edgesStart; i += 2) { - // we copied the node while queueing it, so direct mutation here is safe. - data[i + 1] = fun(data[i], data[i + 1]); - } - // the remaining entries are other nodes we can queue - for (let i = edgesStart; i < data.length; ++i) { - // copy the node first to make it safe to mutate - data[i] = copyNode(data[i], generation); - queue.push(data[i]); - } - } - - return new Dict(dict.size, root); -} - -export function fold(dict, state, fun) { - const queue = [dict.root]; - - while (queue.length) { - // order doesn't matter, so we can use push/pop for faster array usage. - const node = queue.pop(); - const data = node.data; - // every node contains popcount(datamap) direct entries - // We need to query the length from the nodemap, as we don't know if this - // is an overflow node or not! if it is, it will never have datamap set! - const edgesStart = data.length - popcount(node.nodemap); - for (let i = 0; i < edgesStart; i += 2) { - state = fun(state, data[i], data[i + 1]); - } - // the remaining entries are child nodes we can queue. - for (let i = edgesStart; i < data.length; ++i) { - queue.push(data[i]); - } - } - - return state; -} - -/** - * How many `1` bits are set in a 32-bit integer. - */ -function popcount(n) { - n -= (n >>> 1) & 0x55555555; - n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); - return Math.imul((n + (n >>> 4)) & 0x0f0f0f0f, 0x01010101) >>> 24; -} - -/** - * Given a population bitmap and a bit selected from that map, returns - * how many less significant 1 bits there are. - * - * For example, index(10101, 100) returns 1, since there is a single less - * significant `1` bit. This translates to the 0-based "index" of that bit. - */ -function index(bitmap, bit) { - return popcount(bitmap & (bit - 1)); -} - -/** - * Extracts a single slice of the hash, and returns a bitmask for the resulting value. - * For example, if the slice returns 5, this function returns 10000 = 1 << 5. - */ -function hashbit(hash, shift) { - return 1 << ((hash >>> shift) & mask); -} diff --git a/ui/javascript/gleam_stdlib/gleam.mjs b/ui/javascript/gleam_stdlib/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/ui/javascript/gleam_stdlib/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/ui/javascript/gleam_stdlib/gleam/bit_array.mjs b/ui/javascript/gleam_stdlib/gleam/bit_array.mjs deleted file mode 100644 index f776446..0000000 --- a/ui/javascript/gleam_stdlib/gleam/bit_array.mjs +++ /dev/null @@ -1,286 +0,0 @@ -import { Ok, toList, bitArraySlice, bitArraySliceToInt } from "../gleam.mjs"; -import * as $int from "../gleam/int.mjs"; -import * as $order from "../gleam/order.mjs"; -import * as $string from "../gleam/string.mjs"; -import { - bit_array_from_string as from_string, - bit_array_bit_size as bit_size, - bit_array_byte_size as byte_size, - bit_array_pad_to_bytes as pad_to_bytes, - bit_array_concat as concat, - bit_array_slice as slice, - bit_array_to_string as to_string, - base64_encode, - base64_decode as decode64, - base16_encode, - base16_decode, - bit_array_to_int_and_size, - bit_array_starts_with as starts_with, -} from "../gleam_stdlib.mjs"; - -export { - base16_decode, - base16_encode, - base64_encode, - bit_size, - byte_size, - concat, - from_string, - pad_to_bytes, - slice, - starts_with, - to_string, -}; - -/** - * Creates a new bit array by joining two bit arrays. - * - * ## Examples - * - * ```gleam - * assert append(to: from_string("butter"), suffix: from_string("fly")) - * == from_string("butterfly") - * ``` - */ -export function append(first, second) { - return concat(toList([first, second])); -} - -function is_utf8_loop(bits) { - let $ = to_string(bits); - if ($ instanceof Ok) { - return true; - } else { - return false; - } -} - -/** - * Tests to see whether a bit array is valid UTF-8. - */ -export function is_utf8(bits) { - return is_utf8_loop(bits); -} - -/** - * Decodes a base 64 encoded string into a `BitArray`. - */ -export function base64_decode(encoded) { - let _block; - let $ = byte_size(from_string(encoded)) % 4; - if ($ === 0) { - _block = encoded; - } else { - let n = $; - _block = $string.append(encoded, $string.repeat("=", 4 - n)); - } - let padded = _block; - return decode64(padded); -} - -/** - * Encodes a `BitArray` into a base 64 encoded string with URL and filename - * safe alphabet. - * - * If the bit array does not contain a whole number of bytes then it is padded - * with zero bits prior to being encoded. - */ -export function base64_url_encode(input, padding) { - let _pipe = input; - let _pipe$1 = base64_encode(_pipe, padding); - let _pipe$2 = $string.replace(_pipe$1, "+", "-"); - return $string.replace(_pipe$2, "/", "_"); -} - -/** - * Decodes a base 64 encoded string with URL and filename safe alphabet into a - * `BitArray`. - */ -export function base64_url_decode(encoded) { - let _pipe = encoded; - let _pipe$1 = $string.replace(_pipe, "-", "+"); - let _pipe$2 = $string.replace(_pipe$1, "_", "/"); - return base64_decode(_pipe$2); -} - -function inspect_loop(loop$input, loop$accumulator) { - while (true) { - let input = loop$input; - let accumulator = loop$accumulator; - if (input.bitSize === 0) { - return accumulator; - } else if (input.bitSize === 1) { - let x = bitArraySliceToInt(input, 0, 1, true, false); - return (accumulator + $int.to_string(x)) + ":size(1)"; - } else if (input.bitSize === 2) { - let x = bitArraySliceToInt(input, 0, 2, true, false); - return (accumulator + $int.to_string(x)) + ":size(2)"; - } else if (input.bitSize === 3) { - let x = bitArraySliceToInt(input, 0, 3, true, false); - return (accumulator + $int.to_string(x)) + ":size(3)"; - } else if (input.bitSize === 4) { - let x = bitArraySliceToInt(input, 0, 4, true, false); - return (accumulator + $int.to_string(x)) + ":size(4)"; - } else if (input.bitSize === 5) { - let x = bitArraySliceToInt(input, 0, 5, true, false); - return (accumulator + $int.to_string(x)) + ":size(5)"; - } else if (input.bitSize === 6) { - let x = bitArraySliceToInt(input, 0, 6, true, false); - return (accumulator + $int.to_string(x)) + ":size(6)"; - } else if (input.bitSize === 7) { - let x = bitArraySliceToInt(input, 0, 7, true, false); - return (accumulator + $int.to_string(x)) + ":size(7)"; - } else if (input.bitSize >= 8) { - let x = input.byteAt(0); - let rest = bitArraySlice(input, 8); - let _block; - if (rest.bitSize === 0) { - _block = ""; - } else { - _block = ", "; - } - let suffix = _block; - let accumulator$1 = (accumulator + $int.to_string(x)) + suffix; - loop$input = rest; - loop$accumulator = accumulator$1; - } else { - return accumulator; - } - } -} - -/** - * Converts a bit array to a string containing the decimal value of each byte. - * - * Use this over `string.inspect` when you have a bit array you want printed - * in the array syntax even if it is valid UTF-8. - * - * ## Examples - * - * ```gleam - * assert inspect(<<0, 20, 0x20, 255>>) == "<<0, 20, 32, 255>>" - * ``` - * - * ```gleam - * assert inspect(<<100, 5:3>>) == "<<100, 5:size(3)>>" - * ``` - */ -export function inspect(input) { - return inspect_loop(input, "<<") + ">>"; -} - -/** - * Compare two bit arrays as sequences of bytes. - * - * ## Examples - * - * ```gleam - * assert compare(<<1>>, <<2>>) == Lt - * ``` - * - * ```gleam - * assert compare(<<"AB":utf8>>, <<"AA":utf8>>) == Gt - * ``` - * - * ```gleam - * assert compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>) == Eq - * ``` - */ -export function compare(loop$a, loop$b) { - while (true) { - let a = loop$a; - let b = loop$b; - if (a.bitSize >= 8) { - if (b.bitSize >= 8) { - let first_byte = a.byteAt(0); - let first_rest = bitArraySlice(a, 8); - let second_byte = b.byteAt(0); - let second_rest = bitArraySlice(b, 8); - let f = first_byte; - let s = second_byte; - if (f > s) { - return new $order.Gt(); - } else { - let f = first_byte; - let s = second_byte; - if (f < s) { - return new $order.Lt(); - } else { - loop$a = first_rest; - loop$b = second_rest; - } - } - } else if (b.bitSize === 0) { - return new $order.Gt(); - } else { - let first = a; - let second = b; - let $ = bit_array_to_int_and_size(first); - let $1 = bit_array_to_int_and_size(second); - let a$1 = $[0]; - let b$1 = $1[0]; - if (a$1 > b$1) { - return new $order.Gt(); - } else { - let a$1 = $[0]; - let b$1 = $1[0]; - if (a$1 < b$1) { - return new $order.Lt(); - } else { - let size_a = $[1]; - let size_b = $1[1]; - if (size_a > size_b) { - return new $order.Gt(); - } else { - let size_a = $[1]; - let size_b = $1[1]; - if (size_a < size_b) { - return new $order.Lt(); - } else { - return new $order.Eq(); - } - } - } - } - } - } else if (b.bitSize === 0) { - if (a.bitSize === 0) { - return new $order.Eq(); - } else { - return new $order.Gt(); - } - } else if (a.bitSize === 0) { - return new $order.Lt(); - } else { - let first = a; - let second = b; - let $ = bit_array_to_int_and_size(first); - let $1 = bit_array_to_int_and_size(second); - let a$1 = $[0]; - let b$1 = $1[0]; - if (a$1 > b$1) { - return new $order.Gt(); - } else { - let a$1 = $[0]; - let b$1 = $1[0]; - if (a$1 < b$1) { - return new $order.Lt(); - } else { - let size_a = $[1]; - let size_b = $1[1]; - if (size_a > size_b) { - return new $order.Gt(); - } else { - let size_a = $[1]; - let size_b = $1[1]; - if (size_a < size_b) { - return new $order.Lt(); - } else { - return new $order.Eq(); - } - } - } - } - } - } -} diff --git a/ui/javascript/gleam_stdlib/gleam/bool.mjs b/ui/javascript/gleam_stdlib/gleam/bool.mjs deleted file mode 100644 index 4dbd86f..0000000 --- a/ui/javascript/gleam_stdlib/gleam/bool.mjs +++ /dev/null @@ -1,295 +0,0 @@ -/** - * Returns the and of two bools, but it evaluates both arguments. - * - * It's the function equivalent of the `&&` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert and(True, True) - * ``` - * - * ```gleam - * assert !and(False, True) - * ``` - * - * ```gleam - * assert !and(False, True) - * ``` - * - * ```gleam - * assert !and(False, False) - * ``` - */ -export function and(a, b) { - return a && b; -} - -/** - * Returns the or of two bools, but it evaluates both arguments. - * - * It's the function equivalent of the `||` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert or(True, True) - * ``` - * - * ```gleam - * assert or(False, True) - * ``` - * - * ```gleam - * assert or(True, False) - * ``` - * - * ```gleam - * assert !or(False, False) - * ``` - */ -export function or(a, b) { - return a || b; -} - -/** - * Returns the opposite bool value. - * - * This is the same as the `!` or `not` operators in some other languages. - * - * ## Examples - * - * ```gleam - * assert !negate(True) - * ``` - * - * ```gleam - * assert negate(False) - * ``` - */ -export function negate(bool) { - return !bool; -} - -/** - * Returns the nor of two bools. - * - * ## Examples - * - * ```gleam - * assert nor(False, False) - * ``` - * - * ```gleam - * assert !nor(False, True) - * ``` - * - * ```gleam - * assert !nor(True, False) - * ``` - * - * ```gleam - * assert !nor(True, True) - * ``` - */ -export function nor(a, b) { - return !(a || b); -} - -/** - * Returns the nand of two bools. - * - * ## Examples - * - * ```gleam - * assert nand(False, False) - * ``` - * - * ```gleam - * assert nand(False, True) - * ``` - * - * ```gleam - * assert nand(True, False) - * ``` - * - * ```gleam - * assert !nand(True, True) - * ``` - */ -export function nand(a, b) { - return !(a && b); -} - -/** - * Returns the exclusive or of two bools. - * - * ## Examples - * - * ```gleam - * assert !exclusive_or(False, False) - * ``` - * - * ```gleam - * assert exclusive_or(False, True) - * ``` - * - * ```gleam - * assert exclusive_or(True, False) - * ``` - * - * ```gleam - * assert !exclusive_or(True, True) - * ``` - */ -export function exclusive_or(a, b) { - return a !== b; -} - -/** - * Returns the exclusive nor of two bools. - * - * ## Examples - * - * ```gleam - * assert exclusive_nor(False, False) - * ``` - * - * ```gleam - * assert !exclusive_nor(False, True) - * ``` - * - * ```gleam - * assert !exclusive_nor(True, False) - * ``` - * - * ```gleam - * assert exclusive_nor(True, True) - * ``` - */ -export function exclusive_nor(a, b) { - return a === b; -} - -/** - * Returns a string representation of the given bool. - * - * ## Examples - * - * ```gleam - * assert to_string(True) == "True" - * ``` - * - * ```gleam - * assert to_string(False) == "False" - * ``` - */ -export function to_string(bool) { - if (bool) { - return "True"; - } else { - return "False"; - } -} - -/** - * Run a callback function if the given bool is `False`, otherwise return a - * default value. - * - * With a `use` expression this function can simulate the early-return pattern - * found in some other programming languages. - * - * In a procedural language: - * - * ```js - * if (predicate) return value; - * // ... - * ``` - * - * In Gleam with a `use` expression: - * - * ```gleam - * use <- guard(when: predicate, return: value) - * // ... - * ``` - * - * Like everything in Gleam `use` is an expression, so it short circuits the - * current block, not the entire function. As a result you can assign the value - * to a variable: - * - * ```gleam - * let x = { - * use <- guard(when: predicate, return: value) - * // ... - * } - * ``` - * - * Note that unlike in procedural languages the `return` value is evaluated - * even when the predicate is `False`, so it is advisable not to perform - * expensive computation nor side-effects there. - * - * - * ## Examples - * - * ```gleam - * let name = "" - * use <- guard(when: name == "", return: "Welcome!") - * "Hello, " <> name - * // -> "Welcome!" - * ``` - * - * ```gleam - * let name = "Kamaka" - * use <- guard(when: name == "", return: "Welcome!") - * "Hello, " <> name - * // -> "Hello, Kamaka" - * ``` - */ -export function guard(requirement, consequence, alternative) { - if (requirement) { - return consequence; - } else { - return alternative(); - } -} - -/** - * Runs a callback function if the given bool is `True`, otherwise runs an - * alternative callback function. - * - * Useful when further computation should be delayed regardless of the given - * bool's value. - * - * See [`guard`](#guard) for more info. - * - * ## Examples - * - * ```gleam - * let name = "Kamaka" - * let inquiry = fn() { "How may we address you?" } - * use <- lazy_guard(when: name == "", return: inquiry) - * "Hello, " <> name - * // -> "Hello, Kamaka" - * ``` - * - * ```gleam - * import gleam/int - * - * let name = "" - * let greeting = fn() { "Hello, " <> name } - * use <- lazy_guard(when: name == "", otherwise: greeting) - * let number = int.random(99) - * let name = "User " <> int.to_string(number) - * "Welcome, " <> name - * // -> "Welcome, User 54" - * ``` - */ -export function lazy_guard(requirement, consequence, alternative) { - if (requirement) { - return consequence(); - } else { - return alternative(); - } -} diff --git a/ui/javascript/gleam_stdlib/gleam/bytes_tree.mjs b/ui/javascript/gleam_stdlib/gleam/bytes_tree.mjs deleted file mode 100644 index c2cb9c9..0000000 --- a/ui/javascript/gleam_stdlib/gleam/bytes_tree.mjs +++ /dev/null @@ -1,225 +0,0 @@ -import { - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, -} from "../gleam.mjs"; -import * as $bit_array from "../gleam/bit_array.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $string_tree from "../gleam/string_tree.mjs"; - -class Bytes extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class Text extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class Many extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -/** - * Joins a list of bytes trees into a single one. - * - * Runs in constant time. - */ -export function concat(trees) { - return new Many(trees); -} - -/** - * Create an empty `BytesTree`. Useful as the start of a pipe chaining many - * trees together. - */ -export function new$() { - return concat(toList([])); -} - -function wrap_list(bits) { - return new Bytes(bits); -} - -/** - * Creates a new bytes tree from a bit array. - * - * Runs in constant time. - */ -export function from_bit_array(bits) { - let _pipe = bits; - let _pipe$1 = $bit_array.pad_to_bytes(_pipe); - return wrap_list(_pipe$1); -} - -/** - * Appends a bytes tree onto the end of another. - * - * Runs in constant time. - */ -export function append_tree(first, second) { - if (second instanceof Bytes) { - return new Many(toList([first, second])); - } else if (second instanceof Text) { - return new Many(toList([first, second])); - } else { - let trees = second[0]; - return new Many(listPrepend(first, trees)); - } -} - -/** - * Prepends a bit array to the start of a bytes tree. - * - * Runs in constant time. - */ -export function prepend(second, first) { - return append_tree(from_bit_array(first), second); -} - -/** - * Appends a bit array to the end of a bytes tree. - * - * Runs in constant time. - */ -export function append(first, second) { - return append_tree(first, from_bit_array(second)); -} - -/** - * Prepends a bytes tree onto the start of another. - * - * Runs in constant time. - */ -export function prepend_tree(second, first) { - return append_tree(first, second); -} - -/** - * Creates a new bytes tree from a string. - * - * Runs in constant time when running on Erlang. - * Runs in linear time otherwise. - */ -export function from_string(string) { - return new Text($string_tree.from_string(string)); -} - -/** - * Prepends a string onto the start of a bytes tree. - * - * Runs in constant time when running on Erlang. - * Runs in linear time with the length of the string otherwise. - */ -export function prepend_string(second, first) { - return append_tree(from_string(first), second); -} - -/** - * Appends a string onto the end of a bytes tree. - * - * Runs in constant time when running on Erlang. - * Runs in linear time with the length of the string otherwise. - */ -export function append_string(first, second) { - return append_tree(first, from_string(second)); -} - -/** - * Joins a list of bit arrays into a single bytes tree. - * - * Runs in constant time. - */ -export function concat_bit_arrays(bits) { - let _pipe = bits; - let _pipe$1 = $list.map(_pipe, from_bit_array); - return concat(_pipe$1); -} - -/** - * Creates a new bytes tree from a string tree. - * - * Runs in constant time when running on Erlang. - * Runs in linear time otherwise. - */ -export function from_string_tree(tree) { - return new Text(tree); -} - -function to_list(loop$stack, loop$acc) { - while (true) { - let stack = loop$stack; - let acc = loop$acc; - if (stack instanceof $Empty) { - return acc; - } else { - let $ = stack.head; - if ($ instanceof $Empty) { - let remaining_stack = stack.tail; - loop$stack = remaining_stack; - loop$acc = acc; - } else { - let $1 = $.head; - if ($1 instanceof Bytes) { - let remaining_stack = stack.tail; - let rest = $.tail; - let bits = $1[0]; - loop$stack = listPrepend(rest, remaining_stack); - loop$acc = listPrepend(bits, acc); - } else if ($1 instanceof Text) { - let remaining_stack = stack.tail; - let rest = $.tail; - let tree = $1[0]; - let bits = $bit_array.from_string($string_tree.to_string(tree)); - loop$stack = listPrepend(rest, remaining_stack); - loop$acc = listPrepend(bits, acc); - } else { - let remaining_stack = stack.tail; - let rest = $.tail; - let trees = $1[0]; - loop$stack = listPrepend(trees, listPrepend(rest, remaining_stack)); - loop$acc = acc; - } - } - } - } -} - -/** - * Turns a bytes tree into a bit array. - * - * Runs in linear time. - * - * When running on Erlang this function is implemented natively by the - * virtual machine and is highly optimised. - */ -export function to_bit_array(tree) { - let _pipe = toList([toList([tree])]); - let _pipe$1 = to_list(_pipe, toList([])); - let _pipe$2 = $list.reverse(_pipe$1); - return $bit_array.concat(_pipe$2); -} - -/** - * Returns the size of the bytes tree's content in bytes. - * - * Runs in linear time. - */ -export function byte_size(tree) { - let _pipe = toList([toList([tree])]); - let _pipe$1 = to_list(_pipe, toList([])); - return $list.fold( - _pipe$1, - 0, - (acc, bits) => { return $bit_array.byte_size(bits) + acc; }, - ); -} diff --git a/ui/javascript/gleam_stdlib/gleam/dict.mjs b/ui/javascript/gleam_stdlib/gleam/dict.mjs deleted file mode 100644 index cdde2f3..0000000 --- a/ui/javascript/gleam_stdlib/gleam/dict.mjs +++ /dev/null @@ -1,452 +0,0 @@ -import { - toTransient as to_transient, - fromTransient as from_transient, - size, - fold, - make as new$, - destructiveTransientInsert as transient_insert, - has as has_key, - get, - insert, - map as map_values, - destructiveTransientUpdateWith as transient_update_with, - destructiveTransientDelete as transient_delete, -} from "../dict.mjs"; -import { Ok, toList, Empty as $Empty, prepend as listPrepend } from "../gleam.mjs"; -import * as $option from "../gleam/option.mjs"; - -export { fold, get, has_key, insert, map_values, new$, size }; - -/** - * Determines whether or not the dict is empty. - * - * ## Examples - * - * ```gleam - * assert new() |> is_empty - * ``` - * - * ```gleam - * assert !{ new() |> insert("b", 1) |> is_empty } - * ``` - */ -export function is_empty(dict) { - return size(dict) === 0; -} - -/** - * Converts the dict to a list of 2-element tuples `#(key, value)`, one for - * each key-value pair in the dict. - * - * The tuples in the list have no specific order. - * - * ## Examples - * - * Calling `to_list` on an empty `dict` returns an empty list. - * - * ```gleam - * assert new() |> to_list == [] - * ``` - * - * The ordering of elements in the resulting list is an implementation detail - * that should not be relied upon. - * - * ```gleam - * assert new() - * |> insert("b", 1) - * |> insert("a", 0) - * |> insert("c", 2) - * |> to_list - * == [#("a", 0), #("b", 1), #("c", 2)] - * ``` - */ -export function to_list(dict) { - return fold( - dict, - toList([]), - (acc, key, value) => { return listPrepend([key, value], acc); }, - ); -} - -function from_list_loop(loop$transient, loop$list) { - while (true) { - let transient = loop$transient; - let list = loop$list; - if (list instanceof $Empty) { - return from_transient(transient); - } else { - let rest = list.tail; - let key = list.head[0]; - let value = list.head[1]; - loop$transient = transient_insert(key, value, transient); - loop$list = rest; - } - } -} - -/** - * Converts a list of 2-element tuples `#(key, value)` to a dict. - * - * If two tuples have the same key the last one in the list will be the one - * that is present in the dict. - */ -export function from_list(list) { - return from_list_loop(to_transient(new$()), list); -} - -/** - * Gets a list of all keys in a given dict. - * - * Dicts are not ordered so the keys are not returned in any specific order. Do - * not write code that relies on the order keys are returned by this function - * as it may change in later versions of Gleam or Erlang. - * - * ## Examples - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> keys == ["a", "b"] - * ``` - */ -export function keys(dict) { - return fold( - dict, - toList([]), - (acc, key, _) => { return listPrepend(key, acc); }, - ); -} - -/** - * Gets a list of all values in a given dict. - * - * Dicts are not ordered so the values are not returned in any specific order. Do - * not write code that relies on the order values are returned by this function - * as it may change in later versions of Gleam or Erlang. - * - * ## Examples - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> values == [0, 1] - * ``` - */ -export function values(dict) { - return fold( - dict, - toList([]), - (acc, _, value) => { return listPrepend(value, acc); }, - ); -} - -function do_filter(f, dict) { - let _pipe = to_transient(new$()); - let _pipe$1 = fold( - dict, - _pipe, - (transient, key, value) => { - let $ = f(key, value); - if ($) { - return transient_insert(key, value, transient); - } else { - return transient; - } - }, - ); - return from_transient(_pipe$1); -} - -/** - * Creates a new dict from a given dict, minus any entries that a given function - * returns `False` for. - * - * ## Examples - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) - * |> filter(fn(key, value) { value != 0 }) - * == from_list([#("b", 1)]) - * ``` - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) - * |> filter(fn(key, value) { True }) - * == from_list([#("a", 0), #("b", 1)]) - * ``` - */ -export function filter(dict, predicate) { - return do_filter(predicate, dict); -} - -function do_take_loop(loop$dict, loop$desired_keys, loop$acc) { - while (true) { - let dict = loop$dict; - let desired_keys = loop$desired_keys; - let acc = loop$acc; - if (desired_keys instanceof $Empty) { - return from_transient(acc); - } else { - let key = desired_keys.head; - let rest = desired_keys.tail; - let $ = get(dict, key); - if ($ instanceof Ok) { - let value = $[0]; - loop$dict = dict; - loop$desired_keys = rest; - loop$acc = transient_insert(key, value, acc); - } else { - loop$dict = dict; - loop$desired_keys = rest; - loop$acc = acc; - } - } - } -} - -function do_take(desired_keys, dict) { - return do_take_loop(dict, desired_keys, to_transient(new$())); -} - -/** - * Creates a new dict from a given dict, only including any entries for which the - * keys are in a given list. - * - * ## Examples - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) - * |> take(["b"]) - * == from_list([#("b", 1)]) - * ``` - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) - * |> take(["a", "b", "c"]) - * == from_list([#("a", 0), #("b", 1)]) - * ``` - */ -export function take(dict, desired_keys) { - return do_take(desired_keys, dict); -} - -function do_combine(combine, left, right) { - let _block; - let $1 = size(left) >= size(right); - if ($1) { - _block = [left, right, combine]; - } else { - _block = [right, left, (k, l, r) => { return combine(k, r, l); }]; - } - let $ = _block; - let big = $[0]; - let small = $[1]; - let combine$1 = $[2]; - let _pipe = to_transient(big); - let _pipe$1 = fold( - small, - _pipe, - (transient, key, value) => { - let update = (existing) => { return combine$1(key, existing, value); }; - return transient_update_with(key, update, value, transient); - }, - ); - return from_transient(_pipe$1); -} - -/** - * Creates a new dict from a pair of given dicts by combining their entries. - * - * If there are entries with the same keys in both dicts the given function is - * used to determine the new value to use in the resulting dict. - * - * ## Examples - * - * ```gleam - * let a = from_list([#("a", 0), #("b", 1)]) - * let b = from_list([#("a", 2), #("c", 3)]) - * assert combine(a, b, fn(one, other) { one + other }) - * == from_list([#("a", 2), #("b", 1), #("c", 3)]) - * ``` - */ -export function combine(dict, other, fun) { - return do_combine((_, l, r) => { return fun(l, r); }, dict, other); -} - -/** - * Creates a new dict from a pair of given dicts by combining their entries. - * - * If there are entries with the same keys in both dicts the entry from the - * second dict takes precedence. - * - * ## Examples - * - * ```gleam - * let a = from_list([#("a", 0), #("b", 1)]) - * let b = from_list([#("b", 2), #("c", 3)]) - * assert merge(a, b) == from_list([#("a", 0), #("b", 2), #("c", 3)]) - * ``` - */ -export function merge(dict, new_entries) { - return combine(dict, new_entries, (_, new_entry) => { return new_entry; }); -} - -/** - * Creates a new dict from a given dict with all the same entries except for the - * one with a given key, if it exists. - * - * ## Examples - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> delete("a") - * == from_list([#("b", 1)]) - * ``` - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> delete("c") - * == from_list([#("a", 0), #("b", 1)]) - * ``` - */ -export function delete$(dict, key) { - let _pipe = to_transient(dict); - let _pipe$1 = ((_capture) => { return transient_delete(key, _capture); })( - _pipe, - ); - return from_transient(_pipe$1); -} - -function drop_loop(loop$transient, loop$disallowed_keys) { - while (true) { - let transient = loop$transient; - let disallowed_keys = loop$disallowed_keys; - if (disallowed_keys instanceof $Empty) { - return from_transient(transient); - } else { - let key = disallowed_keys.head; - let rest = disallowed_keys.tail; - loop$transient = transient_delete(key, transient); - loop$disallowed_keys = rest; - } - } -} - -function do_drop(disallowed_keys, dict) { - return drop_loop(to_transient(dict), disallowed_keys); -} - -/** - * Creates a new dict from a given dict with all the same entries except any with - * keys found in a given list. - * - * ## Examples - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> drop(["a"]) - * == from_list([#("b", 1)]) - * ``` - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> drop(["c"]) - * == from_list([#("a", 0), #("b", 1)]) - * ``` - * - * ```gleam - * assert from_list([#("a", 0), #("b", 1)]) |> drop(["a", "b", "c"]) - * == from_list([]) - * ``` - */ -export function drop(dict, disallowed_keys) { - return do_drop(disallowed_keys, dict); -} - -/** - * Creates a new dict with one entry inserted or updated using a given function. - * - * If there was not an entry in the dict for the given key then the function - * gets `None` as its argument, otherwise it gets `Some(value)`. - * - * ## Examples - * - * ```gleam - * let dict = from_list([#("a", 0)]) - * let increment = fn(x) { - * case x { - * Some(i) -> i + 1 - * None -> 0 - * } - * } - * - * assert upsert(dict, "a", increment) == from_list([#("a", 1)]) - * ``` - * - * ```gleam - * assert upsert(dict, "b", increment) == from_list([#("a", 0), #("b", 0)]) - * ``` - */ -export function upsert(dict, key, fun) { - let $ = get(dict, key); - if ($ instanceof Ok) { - let value = $[0]; - return insert(dict, key, fun(new $option.Some(value))); - } else { - return insert(dict, key, fun(new $option.None())); - } -} - -/** - * Calls a function for each key and value in a dict, discarding the return - * value. - * - * Useful for producing a side effect for every item of a dict. - * - * ```gleam - * import gleam/io - * - * let dict = from_list([#("a", "apple"), #("b", "banana"), #("c", "cherry")]) - * - * assert - * each(dict, fn(k, v) { - * io.println(k <> " => " <> v) - * }) - * == Nil - * // a => apple - * // b => banana - * // c => cherry - * ``` - * - * The order of elements in the iteration is an implementation detail that - * should not be relied upon. - */ -export function each(dict, fun) { - return fold( - dict, - undefined, - (nil, k, v) => { - fun(k, v); - return nil; - }, - ); -} - -function group_loop(loop$transient, loop$to_key, loop$list) { - while (true) { - let transient = loop$transient; - let to_key = loop$to_key; - let list = loop$list; - if (list instanceof $Empty) { - return from_transient(transient); - } else { - let value = list.head; - let rest = list.tail; - let key = to_key(value); - let update = (existing) => { return listPrepend(value, existing); }; - let _pipe = transient; - let _pipe$1 = ((_capture) => { - return transient_update_with(key, update, toList([value]), _capture); - })(_pipe); - loop$transient = _pipe$1; - loop$to_key = to_key; - loop$list = rest; - } - } -} - -export function group(key, list) { - return group_loop(to_transient(new$()), key, list); -} diff --git a/ui/javascript/gleam_stdlib/gleam/dynamic.mjs b/ui/javascript/gleam_stdlib/gleam/dynamic.mjs deleted file mode 100644 index 875ec6c..0000000 --- a/ui/javascript/gleam_stdlib/gleam/dynamic.mjs +++ /dev/null @@ -1,35 +0,0 @@ -import * as $dict from "../gleam/dict.mjs"; -import { - classify_dynamic as classify, - identity as bool, - identity as string, - identity as float, - identity as int, - identity as bit_array, - identity as list, - list_to_array as array, - identity as cast, -} from "../gleam_stdlib.mjs"; - -export { array, bit_array, bool, classify, float, int, list, string }; - -/** - * Create a dynamic value made of an unordered series of keys and values, where - * the keys are unique. - * - * On Erlang this will be a map, on JavaScript this will be a Gleam dict - * object. - */ -export function properties(entries) { - return cast($dict.from_list(entries)); -} - -/** - * A dynamic value representing nothing. - * - * On Erlang this will be the atom `nil`, on JavaScript this will be - * `undefined`. - */ -export function nil() { - return cast(undefined); -} diff --git a/ui/javascript/gleam_stdlib/gleam/dynamic/decode.mjs b/ui/javascript/gleam_stdlib/gleam/dynamic/decode.mjs deleted file mode 100644 index 6ba81d5..0000000 --- a/ui/javascript/gleam_stdlib/gleam/dynamic/decode.mjs +++ /dev/null @@ -1,963 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - isEqual, -} from "../../gleam.mjs"; -import * as $bit_array from "../../gleam/bit_array.mjs"; -import * as $dict from "../../gleam/dict.mjs"; -import * as $dynamic from "../../gleam/dynamic.mjs"; -import * as $float from "../../gleam/float.mjs"; -import * as $int from "../../gleam/int.mjs"; -import * as $list from "../../gleam/list.mjs"; -import * as $option from "../../gleam/option.mjs"; -import { None, Some } from "../../gleam/option.mjs"; -import { - float as dynamic_float, - int as dynamic_int, - bit_array as dynamic_bit_array, - string as dynamic_string, - identity as cast, - list as decode_list, - index as bare_index, - dict as decode_dict, - is_null, -} from "../../gleam_stdlib.mjs"; - -export class DecodeError extends $CustomType { - constructor(expected, found, path) { - super(); - this.expected = expected; - this.found = found; - this.path = path; - } -} -export const DecodeError$DecodeError = (expected, found, path) => - new DecodeError(expected, found, path); -export const DecodeError$isDecodeError = (value) => - value instanceof DecodeError; -export const DecodeError$DecodeError$expected = (value) => value.expected; -export const DecodeError$DecodeError$0 = (value) => value.expected; -export const DecodeError$DecodeError$found = (value) => value.found; -export const DecodeError$DecodeError$1 = (value) => value.found; -export const DecodeError$DecodeError$path = (value) => value.path; -export const DecodeError$DecodeError$2 = (value) => value.path; - -class Decoder extends $CustomType { - constructor(function$) { - super(); - this.function = function$; - } -} - -/** - * A decoder that decodes `Dynamic` values. This decoder never returns an error. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.float(3.14), decode.dynamic) - * assert result == Ok(dynamic.float(3.14)) - * ``` - */ -export const dynamic = /* @__PURE__ */ new Decoder(decode_dynamic); - -/** - * A decoder that decodes `Float` values. - * - * This will not coerse int values into float values, so on platforms with - * distinct runtime int and float types (Erlang, not JavaScript) it will fail - * for ints. One time this may happen is when decoding JSON data. - * - * If you want to decode both ints and floats you may want to use the `one_of` - * function. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.float(3.14), decode.float) - * assert result == Ok(3.14) - * ``` - */ -export const float = /* @__PURE__ */ new Decoder(decode_float); - -/** - * A decoder that decodes `Int` values. - * - * This will not coerse float values into int values, so on platforms with - * distinct runtime int and float types (Erlang, not JavaScript) it will fail, - * even if the float is a whole number (e.g. 1.0). - * - * If you want to decode both ints and floats you may want to use the `one_of` - * function. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.int(147), decode.int) - * assert result == Ok(147) - * ``` - */ -export const int = /* @__PURE__ */ new Decoder(decode_int); - -/** - * A decoder that decodes `BitArray` values. This decoder never returns an error. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.bit_array(<<5, 7>>), decode.bit_array) - * assert result == Ok(<<5, 7>>) - * ``` - */ -export const bit_array = /* @__PURE__ */ new Decoder(decode_bit_array); - -/** - * A decoder that decodes `String` values. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.string("Hello!"), decode.string) - * assert result == Ok("Hello!") - * ``` - */ -export const string = /* @__PURE__ */ new Decoder(decode_string); - -/** - * A decoder that decodes `Bool` values. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.bool(True), decode.bool) - * assert result == Ok(True) - * ``` - */ -export const bool = /* @__PURE__ */ new Decoder(decode_bool); - -function decode_dynamic(data) { - return [data, toList([])]; -} - -/** - * Run a decoder on a `Dynamic` value, decoding the value if it is of the - * desired type, or returning errors. - * - * ## Examples - * - * ```gleam - * let decoder = { - * use name <- decode.field("name", decode.string) - * use email <- decode.field("email", decode.string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * decode.run(data, decoder) - * ``` - */ -export function run(data, decoder) { - let $ = decoder.function(data); - let maybe_invalid_data = $[0]; - let errors = $[1]; - if (errors instanceof $Empty) { - return new Ok(maybe_invalid_data); - } else { - return new Error(errors); - } -} - -function run_dynamic_function(data, name, f) { - let $ = f(data); - if ($ instanceof Ok) { - let data$1 = $[0]; - return [data$1, toList([])]; - } else { - let placeholder = $[0]; - return [ - placeholder, - toList([new DecodeError(name, $dynamic.classify(data), toList([]))]), - ]; - } -} - -function decode_float(data) { - return run_dynamic_function(data, "Float", dynamic_float); -} - -/** - * Apply a transformation function to any value decoded by the decoder. - * - * ## Examples - * - * ```gleam - * let decoder = decode.int |> decode.map(int.to_string) - * let result = decode.run(dynamic.int(1000), decoder) - * assert result == Ok("1000") - * ``` - */ -export function map(decoder, transformer) { - return new Decoder( - (d) => { - let $ = decoder.function(d); - let data = $[0]; - let errors = $[1]; - return [transformer(data), errors]; - }, - ); -} - -function decode_int(data) { - return run_dynamic_function(data, "Int", dynamic_int); -} - -function decode_bit_array(data) { - return run_dynamic_function(data, "BitArray", dynamic_bit_array); -} - -function decode_string(data) { - return run_dynamic_function(data, "String", dynamic_string); -} - -function run_decoders(loop$data, loop$failure, loop$decoders) { - while (true) { - let data = loop$data; - let failure = loop$failure; - let decoders = loop$decoders; - if (decoders instanceof $Empty) { - return failure; - } else { - let decoder = decoders.head; - let decoders$1 = decoders.tail; - let $ = decoder.function(data); - let layer = $; - let errors = $[1]; - if (errors instanceof $Empty) { - return layer; - } else { - loop$data = data; - loop$failure = failure; - loop$decoders = decoders$1; - } - } - } -} - -/** - * Create a new decoder from several other decoders. Each of the inner - * decoders is run in turn, and the value from the first to succeed is used. - * - * If no decoder succeeds then the errors from the first decoder are used. - * If you wish for different errors then you may wish to use the - * `collapse_errors` or `map_errors` functions. - * - * ## Examples - * - * ```gleam - * let decoder = decode.one_of(decode.string, or: [ - * decode.int |> decode.map(int.to_string), - * decode.float |> decode.map(float.to_string), - * ]) - * assert decode.run(dynamic.int(1000), decoder) == Ok("1000") - * ``` - */ -export function one_of(first, alternatives) { - return new Decoder( - (dynamic_data) => { - let $ = first.function(dynamic_data); - let layer = $; - let errors = $[1]; - if (errors instanceof $Empty) { - return layer; - } else { - return run_decoders(dynamic_data, layer, alternatives); - } - }, - ); -} - -function path_segment_to_string(key) { - let decoder = one_of( - string, - toList([ - (() => { - let _pipe = int; - return map(_pipe, $int.to_string); - })(), - (() => { - let _pipe = float; - return map(_pipe, $float.to_string); - })(), - ]), - ); - let $ = run(key, decoder); - if ($ instanceof Ok) { - let key$1 = $[0]; - return key$1; - } else { - return ("<" + $dynamic.classify(key)) + ">"; - } -} - -function push_path(layer, path) { - let path$1 = $list.map( - path, - (key) => { - let _pipe = key; - let _pipe$1 = cast(_pipe); - return path_segment_to_string(_pipe$1); - }, - ); - let errors = $list.map( - layer[1], - (error) => { - return new DecodeError( - error.expected, - error.found, - $list.append(path$1, error.path), - ); - }, - ); - return [layer[0], errors]; -} - -/** - * A decoder that decodes lists where all elements are decoded with a given - * decoder. - * - * ## Examples - * - * ```gleam - * let result = - * [1, 2, 3] - * |> list.map(dynamic.int) - * |> dynamic.list - * |> decode.run(decode.list(of: decode.int)) - * assert result == Ok([1, 2, 3]) - * ``` - */ -export function list(inner) { - return new Decoder( - (data) => { - return decode_list( - data, - inner.function, - (p, k) => { return push_path(p, toList([k])); }, - 0, - toList([]), - ); - }, - ); -} - -function index( - loop$path, - loop$position, - loop$inner, - loop$data, - loop$handle_miss -) { - while (true) { - let path = loop$path; - let position = loop$position; - let inner = loop$inner; - let data = loop$data; - let handle_miss = loop$handle_miss; - if (path instanceof $Empty) { - let _pipe = data; - let _pipe$1 = inner(_pipe); - return push_path(_pipe$1, $list.reverse(position)); - } else { - let key = path.head; - let path$1 = path.tail; - let $ = bare_index(data, key); - if ($ instanceof Ok) { - let $1 = $[0]; - if ($1 instanceof Some) { - let data$1 = $1[0]; - loop$path = path$1; - loop$position = listPrepend(key, position); - loop$inner = inner; - loop$data = data$1; - loop$handle_miss = handle_miss; - } else { - return handle_miss(data, listPrepend(key, position)); - } - } else { - let kind = $[0]; - let $1 = inner(data); - let default$ = $1[0]; - let _pipe = [ - default$, - toList([new DecodeError(kind, $dynamic.classify(data), toList([]))]), - ]; - return push_path(_pipe, $list.reverse(position)); - } - } - } -} - -/** - * The same as [`field`](#field), except taking a path to the value rather - * than a field name. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * ## Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("data"), dynamic.properties([ - * #(dynamic.string("email"), dynamic.string("lucy@example.com")), - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ]) - * ]) - * - * let decoder = { - * use name <- decode.subfield(["data", "name"], decode.string) - * use email <- decode.subfield(["data", "email"], decode.string) - * decode.success(SignUp(name: name, email: email)) - * } - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) - * ``` - */ -export function subfield(field_path, field_decoder, next) { - return new Decoder( - (data) => { - let $ = index( - field_path, - toList([]), - field_decoder.function, - data, - (data, position) => { - let $1 = field_decoder.function(data); - let default$ = $1[0]; - let _pipe = [ - default$, - toList([new DecodeError("Field", "Nothing", toList([]))]), - ]; - return push_path(_pipe, $list.reverse(position)); - }, - ); - let out = $[0]; - let errors1 = $[1]; - let $1 = next(out).function(data); - let out$1 = $1[0]; - let errors2 = $1[1]; - return [out$1, $list.append(errors1, errors2)]; - }, - ); -} - -/** - * A decoder that decodes a value that is nested within other values. For - * example, decoding a value that is within some deeply nested JSON objects. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * ## Examples - * - * ```gleam - * let decoder = decode.at(["one", "two"], decode.int) - * - * let data = dynamic.properties([ - * #(dynamic.string("one"), dynamic.properties([ - * #(dynamic.string("two"), dynamic.int(1000)), - * ]), - * ]) - * - * assert decode.run(data, decoder) == Ok(1000) - * ``` - * - * ```gleam - * assert dynamic.nil() - * |> decode.run(decode.optional(decode.int)) - * == Ok(option.None) - * ``` - */ -export function at(path, inner) { - return new Decoder( - (data) => { - return index( - path, - toList([]), - inner.function, - data, - (data, position) => { - let $ = inner.function(data); - let default$ = $[0]; - let _pipe = [ - default$, - toList([new DecodeError("Field", "Nothing", toList([]))]), - ]; - return push_path(_pipe, $list.reverse(position)); - }, - ); - }, - ); -} - -/** - * Finalise a decoder having successfully extracted a value. - * - * ## Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("email"), dynamic.string("lucy@example.com")), - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ]) - * - * let decoder = { - * use name <- decode.field("name", string) - * use email <- decode.field("email", string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) - * ``` - */ -export function success(data) { - return new Decoder((_) => { return [data, toList([])]; }); -} - -/** - * Construct a decode error for some unexpected dynamic data. - */ -export function decode_error(expected, found) { - return toList([ - new DecodeError(expected, $dynamic.classify(found), toList([])), - ]); -} - -/** - * Run a decoder on a field of a `Dynamic` value, decoding the value if it is - * of the desired type, or returning errors. An error is returned if there is - * no field for the specified key. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * ## Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("email"), dynamic.string("lucy@example.com")), - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ]) - * - * let decoder = { - * use name <- decode.field("name", string) - * use email <- decode.field("email", string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com")) - * ``` - * - * If you wish to decode a value that is more deeply nested within the dynamic - * data, see [`subfield`](#subfield) and [`at`](#at). - * - * If you wish to return a default in the event that a field is not present, - * see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at). - */ -export function field(field_name, field_decoder, next) { - return subfield(toList([field_name]), field_decoder, next); -} - -/** - * Run a decoder on a field of a `Dynamic` value, decoding the value if it is - * of the desired type, or returning errors. The given default value is - * returned if there is no field for the specified key. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * ## Examples - * - * ```gleam - * let data = dynamic.properties([ - * #(dynamic.string("name"), dynamic.string("Lucy")), - * ]) - * - * let decoder = { - * use name <- decode.field("name", string) - * use email <- decode.optional_field("email", "n/a", string) - * decode.success(SignUp(name: name, email: email)) - * } - * - * let result = decode.run(data, decoder) - * assert result == Ok(SignUp(name: "Lucy", email: "n/a")) - * ``` - */ -export function optional_field(key, default$, field_decoder, next) { - return new Decoder( - (data) => { - let _block; - let _block$1; - let $1 = bare_index(data, key); - if ($1 instanceof Ok) { - let $2 = $1[0]; - if ($2 instanceof Some) { - let data$1 = $2[0]; - _block$1 = field_decoder.function(data$1); - } else { - _block$1 = [default$, toList([])]; - } - } else { - let kind = $1[0]; - _block$1 = [ - default$, - toList([new DecodeError(kind, $dynamic.classify(data), toList([]))]), - ]; - } - let _pipe = _block$1; - _block = push_path(_pipe, toList([key])); - let $ = _block; - let out = $[0]; - let errors1 = $[1]; - let $2 = next(out).function(data); - let out$1 = $2[0]; - let errors2 = $2[1]; - return [out$1, $list.append(errors1, errors2)]; - }, - ); -} - -/** - * A decoder that decodes a value that is nested within other values. For - * example, decoding a value that is within some deeply nested JSON objects. - * - * This function will index into dictionaries with any key type, and if the key is - * an int then it'll also index into Erlang tuples and JavaScript arrays, and - * the first eight elements of Gleam lists. - * - * ## Examples - * - * ```gleam - * let decoder = decode.optionally_at(["one", "two"], 100, decode.int) - * - * let data = dynamic.properties([ - * #(dynamic.string("one"), dynamic.properties([])), - * ]) - * - * assert decode.run(data, decoder) == Ok(100) - * ``` - */ -export function optionally_at(path, default$, inner) { - return new Decoder( - (data) => { - return index( - path, - toList([]), - inner.function, - data, - (_, _1) => { return [default$, toList([])]; }, - ); - }, - ); -} - -function decode_bool(data) { - let $ = isEqual(cast(true), data); - if ($) { - return [true, toList([])]; - } else { - let $1 = isEqual(cast(false), data); - if ($1) { - return [false, toList([])]; - } else { - return [false, decode_error("Bool", data)]; - } - } -} - -function fold_dict(acc, key, value, key_decoder, value_decoder) { - let $ = key_decoder(key); - let $1 = $[1]; - if ($1 instanceof $Empty) { - let key_decoded = $[0]; - let $2 = value_decoder(value); - let $3 = $2[1]; - if ($3 instanceof $Empty) { - let value$1 = $2[0]; - let dict$1 = $dict.insert(acc[0], key_decoded, value$1); - return [dict$1, acc[1]]; - } else { - let errors = $3; - let key_identifier = path_segment_to_string(key); - return push_path([$dict.new$(), errors], toList([key_identifier])); - } - } else { - let errors = $1; - return push_path([$dict.new$(), errors], toList(["keys"])); - } -} - -/** - * A decoder that decodes dicts where all keys and values are decoded with - * given decoders. - * - * ## Examples - * - * ```gleam - * let values = dynamic.properties([ - * #(dynamic.string("one"), dynamic.int(1)), - * #(dynamic.string("two"), dynamic.int(2)), - * ]) - * - * let result = - * decode.run(values, decode.dict(decode.string, decode.int)) - * assert result == Ok(values) - * ``` - */ -export function dict(key, value) { - return new Decoder( - (data) => { - let $ = decode_dict(data); - if ($ instanceof Ok) { - let dict$1 = $[0]; - return $dict.fold( - dict$1, - [$dict.new$(), toList([])], - (a, k, v) => { - let $1 = a[1]; - if ($1 instanceof $Empty) { - return fold_dict(a, k, v, key.function, value.function); - } else { - return a; - } - }, - ); - } else { - return [$dict.new$(), decode_error("Dict", data)]; - } - }, - ); -} - -/** - * A decoder that decodes nullable values of a type decoded by with a given - * decoder. - * - * This function can handle common representations of null on all runtimes, such as - * `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on - * JavaScript. - * - * ## Examples - * - * ```gleam - * let result = decode.run(dynamic.int(100), decode.optional(decode.int)) - * assert result == Ok(option.Some(100)) - * ``` - * - * ```gleam - * let result = decode.run(dynamic.nil(), decode.optional(decode.int)) - * assert result == Ok(option.None) - * ``` - */ -export function optional(inner) { - return new Decoder( - (data) => { - let $ = is_null(data); - if ($) { - return [new $option.None(), toList([])]; - } else { - let $1 = inner.function(data); - let data$1 = $1[0]; - let errors = $1[1]; - return [new $option.Some(data$1), errors]; - } - }, - ); -} - -/** - * Apply a transformation function to any errors returned by the decoder. - */ -export function map_errors(decoder, transformer) { - return new Decoder( - (d) => { - let $ = decoder.function(d); - let data = $[0]; - let errors = $[1]; - return [data, transformer(errors)]; - }, - ); -} - -/** - * Replace all errors produced by a decoder with one single error for a named - * expected type. - * - * This function may be useful if you wish to simplify errors before - * presenting them to a user, particularly when using the `one_of` function. - * - * ## Examples - * - * ```gleam - * let decoder = decode.string |> decode.collapse_errors("MyThing") - * let result = decode.run(dynamic.int(1000), decoder) - * assert result == Error([DecodeError("MyThing", "Int", [])]) - * ``` - */ -export function collapse_errors(decoder, name) { - return new Decoder( - (dynamic_data) => { - let $ = decoder.function(dynamic_data); - let layer = $; - let data = $[0]; - let errors = $[1]; - if (errors instanceof $Empty) { - return layer; - } else { - return [data, decode_error(name, dynamic_data)]; - } - }, - ); -} - -/** - * Create a new decoder based upon the value of a previous decoder. - * - * This may be useful to run one previous decoder to use in further decoding. - */ -export function then$(decoder, next) { - return new Decoder( - (dynamic_data) => { - let $ = decoder.function(dynamic_data); - let data = $[0]; - let errors = $[1]; - let decoder$1 = next(data); - let $1 = decoder$1.function(dynamic_data); - let layer = $1; - let data$1 = $1[0]; - if (errors instanceof $Empty) { - return layer; - } else { - return [data$1, errors]; - } - }, - ); -} - -/** - * Define a decoder that always fails. - * - * The first parameter is a "placeholder" value, which is some default value that the - * decoder uses internally in place of the value that would have been produced - * if the decoder was successful. It doesn't matter what this value is, it is - * never returned by the decoder or shown to the user, so pick some arbitrary - * value. If it is an int you might pick `0`, if it is a list you might pick - * `[]`. - * - * The second parameter is the name of the type that has failed to decode. - * - * ```gleam - * decode.failure(User(name: "", score: 0, tags: []), expected: "User") - * ``` - */ -export function failure(placeholder, name) { - return new Decoder((d) => { return [placeholder, decode_error(name, d)]; }); -} - -/** - * Create a decoder for a new data type from a decoding function. - * - * This function is used for new primitive types. For example, you might - * define a decoder for Erlang's pid type. - * - * A default "placeholder" value is also required to make a decoder. When this - * decoder is used as part of a larger decoder this placeholder value is used - * so that the rest of the decoder can continue to run and - * collect all decoding errors. It doesn't matter what this value is, it is - * never returned by the decoder or shown to the user, so pick some arbitrary - * value. If it is an int you might pick `0`, if it is a list you might pick - * `[]`. - * - * If you were to make a decoder for the `Int` type (rather than using the - * built-in `Int` decoder) you would define it like so: - * - * ```gleam - * pub fn int_decoder() -> decode.Decoder(Int) { - * let default = "" - * decode.new_primitive_decoder("Int", int_from_dynamic) - * } - * - * @external(erlang, "my_module", "int_from_dynamic") - * fn int_from_dynamic(data: Int) -> Result(Int, Int) - * ``` - * - * ```erlang - * -module(my_module). - * -export([int_from_dynamic/1]). - * - * int_from_dynamic(Data) -> - * case is_integer(Data) of - * true -> {ok, Data}; - * false -> {error, 0} - * end. - * ``` - */ -export function new_primitive_decoder(name, decoding_function) { - return new Decoder( - (d) => { - let $ = decoding_function(d); - if ($ instanceof Ok) { - let t = $[0]; - return [t, toList([])]; - } else { - let placeholder = $[0]; - return [ - placeholder, - toList([new DecodeError(name, $dynamic.classify(d), toList([]))]), - ]; - } - }, - ); -} - -/** - * Create a decoder that can refer to itself, useful for decoding deeply - * nested data. - * - * Attempting to create a recursive decoder without this function could result - * in an infinite loop. If you are using `field` or other `use`able functions - * then you may not need to use this function. - * - * ## Examples - * - * ```gleam - * type Nested { - * Nested(List(Nested)) - * Value(String) - * } - * - * fn nested_decoder() -> decode.Decoder(Nested) { - * use <- decode.recursive - * decode.one_of(decode.string |> decode.map(Value), [ - * decode.list(nested_decoder()) |> decode.map(Nested), - * ]) - * } - * ``` - */ -export function recursive(inner) { - return new Decoder( - (data) => { - let decoder = inner(); - return decoder.function(data); - }, - ); -} diff --git a/ui/javascript/gleam_stdlib/gleam/float.mjs b/ui/javascript/gleam_stdlib/gleam/float.mjs deleted file mode 100644 index 9bb8e29..0000000 --- a/ui/javascript/gleam_stdlib/gleam/float.mjs +++ /dev/null @@ -1,528 +0,0 @@ -import { Ok, Error, Empty as $Empty, divideFloat } from "../gleam.mjs"; -import * as $order from "../gleam/order.mjs"; -import { - parse_float as parse, - float_to_string as to_string, - ceiling, - floor, - round as js_round, - truncate, - identity as do_to_float, - power as do_power, - random_uniform as random, - log as do_log, - exp as exponential, -} from "../gleam_stdlib.mjs"; - -export { ceiling, exponential, floor, parse, random, to_string, truncate }; - -/** - * Compares two `Float`s, returning the larger of the two. - * - * ## Examples - * - * ```gleam - * assert max(2.0, 2.3) == 2.3 - * ``` - */ -export function max(a, b) { - let $ = a > b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Compares two `Float`s, returning the smaller of the two. - * - * ## Examples - * - * ```gleam - * assert min(2.0, 2.3) == 2.0 - * ``` - */ -export function min(a, b) { - let $ = a < b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Restricts a float between two bounds. - * - * Note: If the `min` argument is larger than the `max` argument then they - * will be swapped, so the minimum bound is always lower than the maximum - * bound. - * - * - * ## Examples - * - * ```gleam - * assert clamp(1.2, min: 1.4, max: 1.6) == 1.4 - * ``` - * - * ```gleam - * assert clamp(1.2, min: 1.4, max: 0.6) == 1.2 - * ``` - */ -export function clamp(x, min_bound, max_bound) { - let $ = min_bound >= max_bound; - if ($) { - let _pipe = x; - let _pipe$1 = min(_pipe, min_bound); - return max(_pipe$1, max_bound); - } else { - let _pipe = x; - let _pipe$1 = min(_pipe, max_bound); - return max(_pipe$1, min_bound); - } -} - -/** - * Compares two `Float`s, returning an `Order`: - * `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. - * - * ## Examples - * - * ```gleam - * assert compare(2.0, 2.3) == Lt - * ``` - * - * To handle - * [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) - * you may use [`loosely_compare`](#loosely_compare) instead. - */ -export function compare(a, b) { - let $ = a === b; - if ($) { - return new $order.Eq(); - } else { - let $1 = a < b; - if ($1) { - return new $order.Lt(); - } else { - return new $order.Gt(); - } - } -} - -/** - * Returns the absolute value of the input as a `Float`. - * - * ## Examples - * - * ```gleam - * assert absolute_value(-12.5) == 12.5 - * ``` - * - * ```gleam - * assert absolute_value(10.2) == 10.2 - * ``` - */ -export function absolute_value(x) { - let $ = x >= 0.0; - if ($) { - return x; - } else { - return 0.0 - x; - } -} - -/** - * Compares two `Float`s within a tolerance, returning an `Order`: - * `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. - * - * This function allows Float comparison while handling - * [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). - * - * Notice: For `Float`s the tolerance won't be exact: - * `5.3 - 5.0` is not exactly `0.3`. - * - * ## Examples - * - * ```gleam - * assert loosely_compare(5.0, with: 5.3, tolerating: 0.5) == Eq - * ``` - * - * If you want to check only for equality you may use - * [`loosely_equals`](#loosely_equals) instead. - */ -export function loosely_compare(a, b, tolerance) { - let difference = absolute_value(a - b); - let $ = difference <= tolerance; - if ($) { - return new $order.Eq(); - } else { - return compare(a, b); - } -} - -/** - * Checks for equality of two `Float`s within a tolerance, - * returning a `Bool`. - * - * This function allows Float comparison while handling - * [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). - * - * Notice: For `Float`s the tolerance won't be exact: - * `5.3 - 5.0` is not exactly `0.3`. - * - * ## Examples - * - * ```gleam - * assert loosely_equals(5.0, with: 5.3, tolerating: 0.5) - * ``` - * - * ```gleam - * assert !loosely_equals(5.0, with: 5.1, tolerating: 0.1) - * ``` - */ -export function loosely_equals(a, b, tolerance) { - let difference = absolute_value(a - b); - return difference <= tolerance; -} - -/** - * Returns the negative of the value provided. - * - * ## Examples - * - * ```gleam - * assert negate(1.0) == -1.0 - * ``` - */ -export function negate(x) { - return -1.0 * x; -} - -/** - * Rounds the value to the nearest whole number as an `Int`. - * - * ## Examples - * - * ```gleam - * assert round(2.3) == 2 - * ``` - * - * ```gleam - * assert round(2.5) == 3 - * ``` - */ -export function round(x) { - let $ = x >= 0.0; - if ($) { - return js_round(x); - } else { - return 0 - js_round(negate(x)); - } -} - -/** - * Converts the value to a given precision as a `Float`. - * The precision is the number of allowed decimal places. - * Negative precisions are allowed and force rounding - * to the nearest tenth, hundredth, thousandth etc. - * - * ## Examples - * - * ```gleam - * assert to_precision(2.43434348473, 2) == 2.43 - * ``` - * - * ```gleam - * assert to_precision(547890.453444, -3) == 548000.0 - * ``` - */ -export function to_precision(x, precision) { - let $ = precision <= 0; - if ($) { - let factor = do_power(10.0, do_to_float(- precision)); - return do_to_float(round(divideFloat(x, factor))) * factor; - } else { - let factor = do_power(10.0, do_to_float(precision)); - return divideFloat(do_to_float(round(x * factor)), factor); - } -} - -/** - * Returns the result of the base being raised to the power of the - * exponent, as a `Float`. - * - * ## Examples - * - * ```gleam - * assert power(2.0, -1.0) == Ok(0.5) - * ``` - * - * ```gleam - * assert power(2.0, 2.0) == Ok(4.0) - * ``` - * - * ```gleam - * assert power(8.0, 1.5) == Ok(22.627416997969522) - * ``` - * - * ```gleam - * assert 4.0 |> power(of: 2.0) == Ok(16.0) - * ``` - * - * ```gleam - * assert power(-1.0, 0.5) == Error(Nil) - * ``` - */ -export function power(base, exponent) { - let fractional = (ceiling(exponent) - exponent) > 0.0; - let $ = ((base < 0.0) && fractional) || ((base === 0.0) && (exponent < 0.0)); - if ($) { - return new Error(undefined); - } else { - return new Ok(do_power(base, exponent)); - } -} - -/** - * Returns the square root of the input as a `Float`. - * - * ## Examples - * - * ```gleam - * assert square_root(4.0) == Ok(2.0) - * ``` - * - * ```gleam - * assert square_root(-16.0) == Error(Nil) - * ``` - */ -export function square_root(x) { - return power(x, 0.5); -} - -function sum_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first + initial; - } - } -} - -/** - * Sums a list of `Float`s. - * - * ## Example - * - * ```gleam - * assert sum([1.0, 2.2, 3.3]) == 6.5 - * ``` - */ -export function sum(numbers) { - return sum_loop(numbers, 0.0); -} - -function product_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first * initial; - } - } -} - -/** - * Multiplies a list of `Float`s and returns the product. - * - * ## Example - * - * ```gleam - * assert product([2.5, 3.2, 4.2]) == 33.6 - * ``` - */ -export function product(numbers) { - return product_loop(numbers, 1.0); -} - -/** - * Computes the modulo of a float division of inputs as a `Result`. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * The computed value will always have the same sign as the `divisor`. - * - * ## Examples - * - * ```gleam - * assert modulo(13.3, by: 3.3) == Ok(0.1) - * ``` - * - * ```gleam - * assert modulo(-13.3, by: 3.3) == Ok(3.2) - * ``` - * - * ```gleam - * assert modulo(13.3, by: -3.3) == Ok(-3.2) - * ``` - * - * ```gleam - * assert modulo(-13.3, by: -3.3) == Ok(-0.1) - * ``` - */ -export function modulo(dividend, divisor) { - if (divisor === 0.0) { - return new Error(undefined); - } else { - return new Ok(dividend - (floor(divideFloat(dividend, divisor)) * divisor)); - } -} - -/** - * Returns division of the inputs as a `Result`. - * - * ## Examples - * - * ```gleam - * assert divide(0.0, 1.0) == Ok(0.0) - * ``` - * - * ```gleam - * assert divide(1.0, 0.0) == Error(Nil) - * ``` - */ -export function divide(a, b) { - if (b === 0.0) { - return new Error(undefined); - } else { - let b$1 = b; - return new Ok(divideFloat(a, b$1)); - } -} - -/** - * Adds two floats together. - * - * It's the function equivalent of the `+.` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert add(1.0, 2.0) == 3.0 - * ``` - * - * ```gleam - * import gleam/list - * - * assert list.fold([1.0, 2.0, 3.0], 0.0, add) == 6.0 - * ``` - * - * ```gleam - * assert 3.0 |> add(2.0) == 5.0 - * ``` - */ -export function add(a, b) { - return a + b; -} - -/** - * Multiplies two floats together. - * - * It's the function equivalent of the `*.` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert multiply(2.0, 4.0) == 8.0 - * ``` - * - * ```gleam - * import gleam/list - * - * assert list.fold([2.0, 3.0, 4.0], 1.0, multiply) == 24.0 - * ``` - * - * ```gleam - * assert 3.0 |> multiply(2.0) == 6.0 - * ``` - */ -export function multiply(a, b) { - return a * b; -} - -/** - * Subtracts one float from another. - * - * It's the function equivalent of the `-.` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert subtract(3.0, 1.0) == 2.0 - * ``` - * - * ```gleam - * import gleam/list - * - * assert list.fold([1.0, 2.0, 3.0], 10.0, subtract) == 4.0 - * ``` - * - * ```gleam - * assert 3.0 |> subtract(_, 2.0) == 1.0 - * ``` - * - * ```gleam - * assert 3.0 |> subtract(2.0, _) == -1.0 - * ``` - */ -export function subtract(a, b) { - return a - b; -} - -/** - * Returns the natural logarithm (base e) of the given `Float` as a `Result`. If the - * input is less than or equal to 0, returns `Error(Nil)`. - * - * ## Examples - * - * ```gleam - * assert logarithm(1.0) == Ok(0.0) - * ``` - * - * ```gleam - * assert logarithm(2.718281828459045) == Ok(1.0) - * ``` - * - * ```gleam - * assert logarithm(0.0) == Error(Nil) - * ``` - * - * ```gleam - * assert logarithm(-1.0) == Error(Nil) - * ``` - */ -export function logarithm(x) { - let $ = x <= 0.0; - if ($) { - return new Error(undefined); - } else { - return new Ok(do_log(x)); - } -} diff --git a/ui/javascript/gleam_stdlib/gleam/function.mjs b/ui/javascript/gleam_stdlib/gleam/function.mjs deleted file mode 100644 index dffa927..0000000 --- a/ui/javascript/gleam_stdlib/gleam/function.mjs +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Takes a single argument and always returns its input value. - */ -export function identity(x) { - return x; -} diff --git a/ui/javascript/gleam_stdlib/gleam/int.mjs b/ui/javascript/gleam_stdlib/gleam/int.mjs deleted file mode 100644 index e619038..0000000 --- a/ui/javascript/gleam_stdlib/gleam/int.mjs +++ /dev/null @@ -1,764 +0,0 @@ -import { Ok, Error, Empty as $Empty, remainderInt, divideInt } from "../gleam.mjs"; -import * as $float from "../gleam/float.mjs"; -import * as $order from "../gleam/order.mjs"; -import { - identity as to_float, - parse_int as parse, - int_from_base_string as do_base_parse, - to_string, - int_to_base_string as do_to_base_string, - bitwise_and, - bitwise_not, - bitwise_or, - bitwise_exclusive_or, - bitwise_shift_left, - bitwise_shift_right, -} from "../gleam_stdlib.mjs"; - -export { - bitwise_and, - bitwise_exclusive_or, - bitwise_not, - bitwise_or, - bitwise_shift_left, - bitwise_shift_right, - parse, - to_float, - to_string, -}; - -/** - * Returns the absolute value of the input. - * - * ## Examples - * - * ```gleam - * assert absolute_value(-12) == 12 - * ``` - * - * ```gleam - * assert absolute_value(10) == 10 - * ``` - */ -export function absolute_value(x) { - let $ = x >= 0; - if ($) { - return x; - } else { - return x * -1; - } -} - -/** - * Returns the result of the base being raised to the power of the - * exponent, as a `Float`. - * - * ## Examples - * - * ```gleam - * assert power(2, -1.0) == Ok(0.5) - * ``` - * - * ```gleam - * assert power(2, 2.0) == Ok(4.0) - * ``` - * - * ```gleam - * assert power(8, 1.5) == Ok(22.627416997969522) - * ``` - * - * ```gleam - * assert 4 |> power(of: 2.0) == Ok(16.0) - * ``` - * - * ```gleam - * assert power(-1, 0.5) == Error(Nil) - * ``` - */ -export function power(base, exponent) { - let _pipe = base; - let _pipe$1 = to_float(_pipe); - return $float.power(_pipe$1, exponent); -} - -/** - * Returns the square root of the input as a `Float`. - * - * ## Examples - * - * ```gleam - * assert square_root(4) == Ok(2.0) - * ``` - * - * ```gleam - * assert square_root(-16) == Error(Nil) - * ``` - */ -export function square_root(x) { - let _pipe = x; - let _pipe$1 = to_float(_pipe); - return $float.square_root(_pipe$1); -} - -/** - * Parses a given string as an int in a given base if possible. - * Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. - * - * ## Examples - * - * ```gleam - * assert base_parse("10", 2) == Ok(2) - * ``` - * - * ```gleam - * assert base_parse("30", 16) == Ok(48) - * ``` - * - * ```gleam - * assert base_parse("1C", 36) == Ok(48) - * ``` - * - * ```gleam - * assert base_parse("48", 1) == Error(Nil) - * ``` - * - * ```gleam - * assert base_parse("48", 37) == Error(Nil) - * ``` - */ -export function base_parse(string, base) { - let $ = (base >= 2) && (base <= 36); - if ($) { - return do_base_parse(string, base); - } else { - return new Error(undefined); - } -} - -/** - * Prints a given int to a string using the base number provided. - * Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. - * For common bases (2, 8, 16, 36), use the `to_baseN` functions. - * - * ## Examples - * - * ```gleam - * assert to_base_string(2, 2) == Ok("10") - * ``` - * - * ```gleam - * assert to_base_string(48, 16) == Ok("30") - * ``` - * - * ```gleam - * assert to_base_string(48, 36) == Ok("1C") - * ``` - * - * ```gleam - * assert to_base_string(48, 1) == Error(Nil) - * ``` - * - * ```gleam - * assert to_base_string(48, 37) == Error(Nil) - * ``` - */ -export function to_base_string(x, base) { - let $ = (base >= 2) && (base <= 36); - if ($) { - return new Ok(do_to_base_string(x, base)); - } else { - return new Error(undefined); - } -} - -/** - * Prints a given int to a string using base-2. - * - * ## Examples - * - * ```gleam - * assert to_base2(2) == "10" - * ``` - */ -export function to_base2(x) { - return do_to_base_string(x, 2); -} - -/** - * Prints a given int to a string using base-8. - * - * ## Examples - * - * ```gleam - * assert to_base8(15) == "17" - * ``` - */ -export function to_base8(x) { - return do_to_base_string(x, 8); -} - -/** - * Prints a given int to a string using base-16. - * - * ## Examples - * - * ```gleam - * assert to_base16(48) == "30" - * ``` - */ -export function to_base16(x) { - return do_to_base_string(x, 16); -} - -/** - * Prints a given int to a string using base-36. - * - * ## Examples - * - * ```gleam - * assert to_base36(48) == "1C" - * ``` - */ -export function to_base36(x) { - return do_to_base_string(x, 36); -} - -/** - * Compares two ints, returning the larger of the two. - * - * ## Examples - * - * ```gleam - * assert max(2, 3) == 3 - * ``` - */ -export function max(a, b) { - let $ = a > b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Compares two ints, returning the smaller of the two. - * - * ## Examples - * - * ```gleam - * assert min(2, 3) == 2 - * ``` - */ -export function min(a, b) { - let $ = a < b; - if ($) { - return a; - } else { - return b; - } -} - -/** - * Restricts an int between two bounds. - * - * Note: If the `min` argument is larger than the `max` argument then they - * will be swapped, so the minimum bound is always lower than the maximum - * bound. - * - * ## Examples - * - * ```gleam - * assert clamp(40, min: 50, max: 60) == 50 - * ``` - * - * ```gleam - * assert clamp(40, min: 50, max: 30) == 40 - * ``` - */ -export function clamp(x, min_bound, max_bound) { - let $ = min_bound >= max_bound; - if ($) { - let _pipe = x; - let _pipe$1 = min(_pipe, min_bound); - return max(_pipe$1, max_bound); - } else { - let _pipe = x; - let _pipe$1 = min(_pipe, max_bound); - return max(_pipe$1, min_bound); - } -} - -/** - * Compares two ints, returning an order. - * - * ## Examples - * - * ```gleam - * assert compare(2, 3) == Lt - * ``` - * - * ```gleam - * assert compare(4, 3) == Gt - * ``` - * - * ```gleam - * assert compare(3, 3) == Eq - * ``` - */ -export function compare(a, b) { - let $ = a === b; - if ($) { - return new $order.Eq(); - } else { - let $1 = a < b; - if ($1) { - return new $order.Lt(); - } else { - return new $order.Gt(); - } - } -} - -/** - * Returns whether the value provided is even. - * - * ## Examples - * - * ```gleam - * assert is_even(2) - * ``` - * - * ```gleam - * assert !is_even(3) - * ``` - */ -export function is_even(x) { - return (x % 2) === 0; -} - -/** - * Returns whether the value provided is odd. - * - * ## Examples - * - * ```gleam - * assert is_odd(3) - * ``` - * - * ```gleam - * assert !is_odd(2) - * ``` - */ -export function is_odd(x) { - return (x % 2) !== 0; -} - -/** - * Returns the negative of the value provided. - * - * ## Examples - * - * ```gleam - * assert negate(1) == -1 - * ``` - */ -export function negate(x) { - return -1 * x; -} - -function sum_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first + initial; - } - } -} - -/** - * Sums a list of ints. - * - * ## Example - * - * ```gleam - * assert sum([1, 2, 3]) == 6 - * ``` - */ -export function sum(numbers) { - return sum_loop(numbers, 0); -} - -function product_loop(loop$numbers, loop$initial) { - while (true) { - let numbers = loop$numbers; - let initial = loop$initial; - if (numbers instanceof $Empty) { - return initial; - } else { - let first = numbers.head; - let rest = numbers.tail; - loop$numbers = rest; - loop$initial = first * initial; - } - } -} - -/** - * Multiplies a list of ints and returns the product. - * - * ## Example - * - * ```gleam - * assert product([2, 3, 4]) == 24 - * ``` - */ -export function product(numbers) { - return product_loop(numbers, 1); -} - -/** - * Generates a random int between zero and the given maximum. - * - * The lower number is inclusive, the upper number is exclusive. - * - * ## Examples - * - * ```gleam - * random(10) - * // -> 4 - * ``` - * - * ```gleam - * random(1) - * // -> 0 - * ``` - * - * ```gleam - * random(-1) - * // -> -1 - * ``` - */ -export function random(max) { - let _pipe = ($float.random() * to_float(max)); - let _pipe$1 = $float.floor(_pipe); - return $float.round(_pipe$1); -} - -/** - * Performs a truncated integer division. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * ## Examples - * - * ```gleam - * assert divide(0, 1) == Ok(0) - * ``` - * - * ```gleam - * assert divide(1, 0) == Error(Nil) - * ``` - * - * ```gleam - * assert divide(5, 2) == Ok(2) - * ``` - * - * ```gleam - * assert divide(-99, 2) == Ok(-49) - * ``` - */ -export function divide(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let divisor$1 = divisor; - return new Ok(divideInt(dividend, divisor$1)); - } -} - -/** - * Computes the remainder of an integer division of inputs as a `Result`. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * Most of the time you will want to use the `%` operator instead of this - * function. - * - * ## Examples - * - * ```gleam - * assert remainder(3, 2) == Ok(1) - * ``` - * - * ```gleam - * assert remainder(1, 0) == Error(Nil) - * ``` - * - * ```gleam - * assert remainder(10, -1) == Ok(0) - * ``` - * - * ```gleam - * assert remainder(13, by: 3) == Ok(1) - * ``` - * - * ```gleam - * assert remainder(-13, by: 3) == Ok(-1) - * ``` - * - * ```gleam - * assert remainder(13, by: -3) == Ok(1) - * ``` - * - * ```gleam - * assert remainder(-13, by: -3) == Ok(-1) - * ``` - */ -export function remainder(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let divisor$1 = divisor; - return new Ok(remainderInt(dividend, divisor$1)); - } -} - -/** - * Computes the modulo of an integer division of inputs as a `Result`. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * Note that this is different from `int.remainder` and `%` in that the - * computed value will always have the same sign as the `divisor`. - * - * ## Examples - * - * ```gleam - * assert modulo(3, 2) == Ok(1) - * ``` - * - * ```gleam - * assert modulo(1, 0) == Error(Nil) - * ``` - * - * ```gleam - * assert modulo(10, -1) == Ok(0) - * ``` - * - * ```gleam - * assert modulo(13, by: 3) == Ok(1) - * ``` - * - * ```gleam - * assert modulo(-13, by: 3) == Ok(2) - * ``` - * - * ```gleam - * assert modulo(13, by: -3) == Ok(-2) - * ``` - */ -export function modulo(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let remainder$1 = remainderInt(dividend, divisor); - let $ = remainder$1 * divisor < 0; - if ($) { - return new Ok(remainder$1 + divisor); - } else { - return new Ok(remainder$1); - } - } -} - -/** - * Performs a *floored* integer division, which means that the result will - * always be rounded towards negative infinity. - * - * If you want to perform truncated integer division (rounding towards zero), - * use `int.divide()` or the `/` operator instead. - * - * Returns division of the inputs as a `Result`: If the given divisor equals - * `0`, this function returns an `Error`. - * - * ## Examples - * - * ```gleam - * assert floor_divide(1, 0) == Error(Nil) - * ``` - * - * ```gleam - * assert floor_divide(5, 2) == Ok(2) - * ``` - * - * ```gleam - * assert floor_divide(6, -4) == Ok(-2) - * ``` - * - * ```gleam - * assert floor_divide(-99, 2) == Ok(-50) - * ``` - */ -export function floor_divide(dividend, divisor) { - if (divisor === 0) { - return new Error(undefined); - } else { - let divisor$1 = divisor; - let $ = (dividend * divisor$1 < 0) && ((remainderInt(dividend, divisor$1)) !== 0); - if ($) { - return new Ok((divideInt(dividend, divisor$1)) - 1); - } else { - return new Ok(divideInt(dividend, divisor$1)); - } - } -} - -/** - * Adds two integers together. - * - * It's the function equivalent of the `+` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert add(1, 2) == 3 - * ``` - * - * ```gleam - * import gleam/list - * assert list.fold([1, 2, 3], 0, add) == 6 - * ``` - * - * ```gleam - * assert 3 |> add(2) == 5 - * ``` - */ -export function add(a, b) { - return a + b; -} - -/** - * Multiplies two integers together. - * - * It's the function equivalent of the `*` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert multiply(2, 4) == 8 - * ``` - * - * ```gleam - * import gleam/list - * - * assert list.fold([2, 3, 4], 1, multiply) == 24 - * ``` - * - * ```gleam - * assert 3 |> multiply(2) == 6 - * ``` - */ -export function multiply(a, b) { - return a * b; -} - -/** - * Subtracts one int from another. - * - * It's the function equivalent of the `-` operator. - * This function is useful in higher order functions or pipes. - * - * ## Examples - * - * ```gleam - * assert subtract(3, 1) == 2 - * ``` - * - * ```gleam - * import gleam/list - * - * assert list.fold([1, 2, 3], 10, subtract) == 4 - * ``` - * - * ```gleam - * assert 3 |> subtract(2) == 1 - * ``` - * - * ```gleam - * assert 3 |> subtract(2, _) == -1 - * ``` - */ -export function subtract(a, b) { - return a - b; -} - -function range_loop( - loop$current, - loop$stop, - loop$increment, - loop$acc, - loop$reducer -) { - while (true) { - let current = loop$current; - let stop = loop$stop; - let increment = loop$increment; - let acc = loop$acc; - let reducer = loop$reducer; - let $ = current === stop; - if ($) { - return acc; - } else { - let acc$1 = reducer(acc, current); - let current$1 = current + increment; - loop$current = current$1; - loop$stop = stop; - loop$increment = increment; - loop$acc = acc$1; - loop$reducer = reducer; - } - } -} - -/** - * Run a function for each int between ints `from` and `to`. - * - * `from` is inclusive, and `to` is exclusive. - * - * ## Examples - * - * ```gleam - * assert - * range(from: 0, to: 3, with: "", run: fn(acc, i) { - * acc <> to_string(i) - * }) - * == "012" - * ``` - * - * ```gleam - * assert range(from: 1, to: -2, with: [], run: list.prepend) == [-1, 0, 1] - * ``` - */ -export function range(start, stop, acc, reducer) { - let _block; - let $ = start < stop; - if ($) { - _block = 1; - } else { - _block = -1; - } - let increment = _block; - return range_loop(start, stop, increment, acc, reducer); -} diff --git a/ui/javascript/gleam_stdlib/gleam/io.mjs b/ui/javascript/gleam_stdlib/gleam/io.mjs deleted file mode 100644 index ddab435..0000000 --- a/ui/javascript/gleam_stdlib/gleam/io.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import { - print, - print_error, - console_log as println, - console_error as println_error, -} from "../gleam_stdlib.mjs"; - -export { print, print_error, println, println_error }; diff --git a/ui/javascript/gleam_stdlib/gleam/list.mjs b/ui/javascript/gleam_stdlib/gleam/list.mjs deleted file mode 100644 index c7ecc1c..0000000 --- a/ui/javascript/gleam_stdlib/gleam/list.mjs +++ /dev/null @@ -1,3029 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - makeError, - divideFloat, - isEqual, -} from "../gleam.mjs"; -import * as $dict from "../gleam/dict.mjs"; -import * as $float from "../gleam/float.mjs"; -import * as $int from "../gleam/int.mjs"; -import * as $order from "../gleam/order.mjs"; - -const FILEPATH = "src/gleam/list.gleam"; - -export class Continue extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const ContinueOrStop$Continue = ($0) => new Continue($0); -export const ContinueOrStop$isContinue = (value) => value instanceof Continue; -export const ContinueOrStop$Continue$0 = (value) => value[0]; - -export class Stop extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const ContinueOrStop$Stop = ($0) => new Stop($0); -export const ContinueOrStop$isStop = (value) => value instanceof Stop; -export const ContinueOrStop$Stop$0 = (value) => value[0]; - -class Ascending extends $CustomType {} - -class Descending extends $CustomType {} - -const min_positive = 2.2250738585072014e-308; - -function length_loop(loop$list, loop$count) { - while (true) { - let list = loop$list; - let count = loop$count; - if (list instanceof $Empty) { - return count; - } else { - let list$1 = list.tail; - loop$list = list$1; - loop$count = count + 1; - } - } -} - -/** - * Counts the number of elements in a given list. - * - * This function has to traverse the list to determine the number of elements, - * so it runs in linear time. - * - * This function is natively implemented by the virtual machine and is highly - * optimised. - * - * ## Examples - * - * ```gleam - * assert length([]) == 0 - * ``` - * - * ```gleam - * assert length([1]) == 1 - * ``` - * - * ```gleam - * assert length([1, 2]) == 2 - * ``` - */ -export function length(list) { - return length_loop(list, 0); -} - -function count_loop(loop$list, loop$predicate, loop$acc) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - let acc = loop$acc; - if (list instanceof $Empty) { - return acc; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - loop$acc = acc + 1; - } else { - loop$list = rest$1; - loop$predicate = predicate; - loop$acc = acc; - } - } - } -} - -/** - * Counts the number of elements in a given list satisfying a given predicate. - * - * This function has to traverse the list to determine the number of elements, - * so it runs in linear time. - * - * ## Examples - * - * ```gleam - * assert count([], fn(a) { a > 0 }) == 0 - * ``` - * - * ```gleam - * assert count([1], fn(a) { a > 0 }) == 1 - * ``` - * - * ```gleam - * assert count([1, 2, 3], int.is_odd) == 2 - * ``` - */ -export function count(list, predicate) { - return count_loop(list, predicate, 0); -} - -/** - * Reverses a list and prepends it to another list. - * This function runs in linear time, proportional to the length of the list - * to prepend. - * - * @ignore - */ -function reverse_and_prepend(loop$prefix, loop$suffix) { - while (true) { - let prefix = loop$prefix; - let suffix = loop$suffix; - if (prefix instanceof $Empty) { - return suffix; - } else { - let first$1 = prefix.head; - let rest$1 = prefix.tail; - loop$prefix = rest$1; - loop$suffix = listPrepend(first$1, suffix); - } - } -} - -/** - * Creates a new list from a given list containing the same elements but in the - * opposite order. - * - * This function has to traverse the list to create the new reversed list, so - * it runs in linear time. - * - * This function is natively implemented by the virtual machine and is highly - * optimised. - * - * ## Examples - * - * ```gleam - * assert reverse([]) == [] - * ``` - * - * ```gleam - * assert reverse([1]) == [1] - * ``` - * - * ```gleam - * assert reverse([1, 2]) == [2, 1] - * ``` - */ -export function reverse(list) { - return reverse_and_prepend(list, toList([])); -} - -/** - * Determines whether or not the list is empty. - * - * This function runs in constant time. - * - * ## Examples - * - * ```gleam - * assert is_empty([]) - * ``` - * - * ```gleam - * assert !is_empty([1]) - * ``` - * - * ```gleam - * assert !is_empty([1, 1]) - * ``` - */ -export function is_empty(list) { - return isEqual(list, toList([])); -} - -/** - * Determines whether or not a given element exists within a given list. - * - * This function traverses the list to find the element, so it runs in linear - * time. - * - * ## Examples - * - * ```gleam - * assert !contains([], any: 0) - * ``` - * - * ```gleam - * assert [0] |> contains(any: 0) - * ``` - * - * ```gleam - * assert !contains([1], any: 0) - * ``` - * - * ```gleam - * assert !contains([1, 1], any: 0) - * ``` - * - * ```gleam - * assert [1, 0] |> contains(any: 0) - * ``` - */ -export function contains(loop$list, loop$elem) { - while (true) { - let list = loop$list; - let elem = loop$elem; - if (list instanceof $Empty) { - return false; - } else { - let first$1 = list.head; - if (isEqual(first$1, elem)) { - return true; - } else { - let rest$1 = list.tail; - loop$list = rest$1; - loop$elem = elem; - } - } - } -} - -/** - * Gets the first element from the start of the list, if there is one. - * - * ## Examples - * - * ```gleam - * assert first([]) == Error(Nil) - * ``` - * - * ```gleam - * assert first([0]) == Ok(0) - * ``` - * - * ```gleam - * assert first([1, 2]) == Ok(1) - * ``` - */ -export function first(list) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - return new Ok(first$1); - } -} - -/** - * Returns the list minus the first element. If the list is empty, `Error(Nil)` is - * returned. - * - * This function runs in constant time and does not make a copy of the list. - * - * ## Examples - * - * ```gleam - * assert rest([]) == Error(Nil) - * ``` - * - * ```gleam - * assert rest([0]) == Ok([]) - * ``` - * - * ```gleam - * assert rest([1, 2]) == Ok([2]) - * ``` - */ -export function rest(list) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let rest$1 = list.tail; - return new Ok(rest$1); - } -} - -/** - * Groups the elements from the given list by the given key function. - * - * Does not preserve the initial value order. - * - * ## Examples - * - * ```gleam - * import gleam/dict - * - * assert - * [Ok(3), Error("Wrong"), Ok(200), Ok(73)] - * |> group(by: fn(i) { - * case i { - * Ok(_) -> "Successful" - * Error(_) -> "Failed" - * } - * }) - * |> dict.to_list - * == [ - * #("Failed", [Error("Wrong")]), - * #("Successful", [Ok(73), Ok(200), Ok(3)]) - * ] - * ``` - * - * ```gleam - * import gleam/dict - * - * assert group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 }) - * |> dict.to_list - * == [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])] - * ``` - */ -export function group(list, key) { - return $dict.group(key, list); -} - -function filter_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let _block; - let $ = fun(first$1); - if ($) { - _block = listPrepend(first$1, acc); - } else { - _block = acc; - } - let new_acc = _block; - loop$list = rest$1; - loop$fun = fun; - loop$acc = new_acc; - } - } -} - -/** - * Returns a new list containing only the elements from the first list for - * which the given functions returns `True`. - * - * ## Examples - * - * ```gleam - * assert filter([2, 4, 6, 1], fn(x) { x > 2 }) == [4, 6] - * ``` - * - * ```gleam - * assert filter([2, 4, 6, 1], fn(x) { x > 6 }) == [] - * ``` - */ -export function filter(list, predicate) { - return filter_loop(list, predicate, toList([])); -} - -function filter_map_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let _block; - let $ = fun(first$1); - if ($ instanceof Ok) { - let first$2 = $[0]; - _block = listPrepend(first$2, acc); - } else { - _block = acc; - } - let new_acc = _block; - loop$list = rest$1; - loop$fun = fun; - loop$acc = new_acc; - } - } -} - -/** - * Returns a new list containing only the elements from the first list for - * which the given functions returns `Ok(_)`. - * - * ## Examples - * - * ```gleam - * assert filter_map([2, 4, 6, 1], Error) == [] - * ``` - * - * ```gleam - * assert filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) == [3, 5, 7, 2] - * ``` - */ -export function filter_map(list, fun) { - return filter_map_loop(list, fun, toList([])); -} - -function map_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$fun = fun; - loop$acc = listPrepend(fun(first$1), acc); - } - } -} - -/** - * Returns a new list containing the results of applying the supplied function to each element. - * - * ## Examples - * - * ```gleam - * assert map([2, 4, 6], fn(x) { x * 2 }) == [4, 8, 12] - * ``` - */ -export function map(list, fun) { - return map_loop(list, fun, toList([])); -} - -function map2_loop(loop$list1, loop$list2, loop$fun, loop$acc) { - while (true) { - let list1 = loop$list1; - let list2 = loop$list2; - let fun = loop$fun; - let acc = loop$acc; - if (list1 instanceof $Empty) { - return reverse(acc); - } else if (list2 instanceof $Empty) { - return reverse(acc); - } else { - let a = list1.head; - let as_ = list1.tail; - let b = list2.head; - let bs = list2.tail; - loop$list1 = as_; - loop$list2 = bs; - loop$fun = fun; - loop$acc = listPrepend(fun(a, b), acc); - } - } -} - -/** - * Combines two lists into a single list using the given function. - * - * If a list is longer than the other, the extra elements are dropped. - * - * ## Examples - * - * ```gleam - * assert map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) == [5, 7, 9] - * ``` - * - * ```gleam - * assert map2([1, 2], ["a", "b", "c"], fn(i, x) { #(i, x) }) - * == [#(1, "a"), #(2, "b")] - * ``` - */ -export function map2(list1, list2, fun) { - return map2_loop(list1, list2, fun, toList([])); -} - -function map_fold_loop(loop$list, loop$fun, loop$acc, loop$list_acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - let list_acc = loop$list_acc; - if (list instanceof $Empty) { - return [acc, reverse(list_acc)]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(acc, first$1); - let acc$1 = $[0]; - let first$2 = $[1]; - loop$list = rest$1; - loop$fun = fun; - loop$acc = acc$1; - loop$list_acc = listPrepend(first$2, list_acc); - } - } -} - -/** - * Similar to `map` but also lets you pass around an accumulated value. - * - * ## Examples - * - * ```gleam - * assert - * map_fold( - * over: [1, 2, 3], - * from: 100, - * with: fn(memo, i) { #(memo + i, i * 2) } - * ) - * == #(106, [2, 4, 6]) - * ``` - */ -export function map_fold(list, initial, fun) { - return map_fold_loop(list, fun, initial, toList([])); -} - -function index_map_loop(loop$list, loop$fun, loop$index, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let index = loop$index; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let acc$1 = listPrepend(fun(first$1, index), acc); - loop$list = rest$1; - loop$fun = fun; - loop$index = index + 1; - loop$acc = acc$1; - } - } -} - -/** - * Similar to `map`, but the supplied function will also be passed the index - * of the element being mapped as an additional argument. - * - * The index starts at 0, so the first element is 0, the second is 1, and so - * on. - * - * ## Examples - * - * ```gleam - * assert index_map(["a", "b"], fn(x, i) { #(i, x) }) == [#(0, "a"), #(1, "b")] - * ``` - */ -export function index_map(list, fun) { - return index_map_loop(list, fun, 0, toList([])); -} - -function try_map_loop(loop$list, loop$fun, loop$acc) { - while (true) { - let list = loop$list; - let fun = loop$fun; - let acc = loop$acc; - if (list instanceof $Empty) { - return new Ok(reverse(acc)); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(first$1); - if ($ instanceof Ok) { - let first$2 = $[0]; - loop$list = rest$1; - loop$fun = fun; - loop$acc = listPrepend(first$2, acc); - } else { - return $; - } - } - } -} - -/** - * Takes a function that returns a `Result` and applies it to each element in a - * given list in turn. - * - * If the function returns `Ok(new_value)` for all elements in the list then a - * list of the new values is returned. - * - * If the function returns `Error(reason)` for any of the elements then it is - * returned immediately. None of the elements in the list are processed after - * one returns an `Error`. - * - * ## Examples - * - * ```gleam - * assert try_map([1, 2, 3], fn(x) { Ok(x + 2) }) == Ok([3, 4, 5]) - * ``` - * - * ```gleam - * assert try_map([1, 2, 3], fn(_) { Error(0) }) == Error(0) - * ``` - * - * ```gleam - * assert try_map([[1], [2, 3]], first) == Ok([1, 2]) - * ``` - * - * ```gleam - * assert try_map([[1], [], [2]], first) == Error(Nil) - * ``` - */ -export function try_map(list, fun) { - return try_map_loop(list, fun, toList([])); -} - -/** - * Returns a list that is the given list with up to the given number of - * elements removed from the front of the list. - * - * If the list has less than the number of elements an empty list is - * returned. - * - * This function runs in linear time but does not copy the list. - * - * ## Examples - * - * ```gleam - * assert drop([1, 2, 3, 4], 2) == [3, 4] - * ``` - * - * ```gleam - * assert drop([1, 2, 3, 4], 9) == [] - * ``` - */ -export function drop(loop$list, loop$n) { - while (true) { - let list = loop$list; - let n = loop$n; - let $ = n <= 0; - if ($) { - return list; - } else { - if (list instanceof $Empty) { - return list; - } else { - let rest$1 = list.tail; - loop$list = rest$1; - loop$n = n - 1; - } - } - } -} - -function take_loop(loop$list, loop$n, loop$acc) { - while (true) { - let list = loop$list; - let n = loop$n; - let acc = loop$acc; - let $ = n <= 0; - if ($) { - return reverse(acc); - } else { - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$n = n - 1; - loop$acc = listPrepend(first$1, acc); - } - } - } -} - -/** - * Returns a list containing the first given number of elements from the given - * list. - * - * If the list has less than the number of elements then the full list is - * returned. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * assert take([1, 2, 3, 4], 2) == [1, 2] - * ``` - * - * ```gleam - * assert take([1, 2, 3, 4], 9) == [1, 2, 3, 4] - * ``` - */ -export function take(list, n) { - return take_loop(list, n, toList([])); -} - -/** - * Returns a new empty list. - * - * ## Examples - * - * ```gleam - * assert new() == [] - * ``` - */ -export function new$() { - return toList([]); -} - -/** - * Returns the given item wrapped in a list. - * - * ## Examples - * - * ```gleam - * assert wrap(1) == [1] - * ``` - * - * ```gleam - * assert wrap(["a", "b", "c"]) == [["a", "b", "c"]] - * ``` - * - * ```gleam - * assert wrap([[]]) == [[[]]] - * ``` - */ -export function wrap(item) { - return toList([item]); -} - -function append_loop(loop$first, loop$second) { - while (true) { - let first = loop$first; - let second = loop$second; - if (first instanceof $Empty) { - return second; - } else { - let first$1 = first.head; - let rest$1 = first.tail; - loop$first = rest$1; - loop$second = listPrepend(first$1, second); - } - } -} - -/** - * Joins one list onto the end of another. - * - * This function runs in linear time, and it traverses and copies the first - * list. - * - * ## Examples - * - * ```gleam - * assert append([1, 2], [3]) == [1, 2, 3] - * ``` - */ -export function append(first, second) { - return append_loop(reverse(first), second); -} - -/** - * Prefixes an item to a list. This can also be done using the dedicated - * syntax instead. - * - * ```gleam - * let existing_list = [2, 3, 4] - * assert [1, ..existing_list] == [1, 2, 3, 4] - * ``` - * - * ```gleam - * let existing_list = [2, 3, 4] - * assert prepend(to: existing_list, this: 1) == [1, 2, 3, 4] - * ``` - */ -export function prepend(list, item) { - return listPrepend(item, list); -} - -function flatten_loop(loop$lists, loop$acc) { - while (true) { - let lists = loop$lists; - let acc = loop$acc; - if (lists instanceof $Empty) { - return reverse(acc); - } else { - let list = lists.head; - let further_lists = lists.tail; - loop$lists = further_lists; - loop$acc = reverse_and_prepend(list, acc); - } - } -} - -/** - * Joins a list of lists into a single list. - * - * This function traverses all elements twice on the JavaScript target. - * This function traverses all elements once on the Erlang target. - * - * ## Examples - * - * ```gleam - * assert flatten([[1], [2, 3], []]) == [1, 2, 3] - * ``` - */ -export function flatten(lists) { - return flatten_loop(lists, toList([])); -} - -/** - * Maps the list with the given function into a list of lists, and then flattens it. - * - * ## Examples - * - * ```gleam - * assert flat_map([2, 4, 6], fn(x) { [x, x + 1] }) == [2, 3, 4, 5, 6, 7] - * ``` - */ -export function flat_map(list, fun) { - return flatten(map(list, fun)); -} - -/** - * Reduces a list of elements into a single value by calling a given function - * on each element, going from left to right. - * - * `fold([1, 2, 3], 0, add)` is the equivalent of - * `add(add(add(0, 1), 2), 3)`. - * - * This function runs in linear time. - */ -export function fold(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return initial; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$initial = fun(initial, first$1); - loop$fun = fun; - } - } -} - -/** - * Reduces a list of elements into a single value by calling a given function - * on each element, going from right to left. - * - * `fold_right([1, 2, 3], 0, add)` is the equivalent of - * `add(add(add(0, 3), 2), 1)`. - * - * This function runs in linear time. - * - * Unlike `fold` this function is not tail recursive. Where possible use - * `fold` instead as it will use less memory. - */ -export function fold_right(list, initial, fun) { - if (list instanceof $Empty) { - return initial; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return fun(fold_right(rest$1, initial, fun), first$1); - } -} - -function index_fold_loop(loop$over, loop$acc, loop$with, loop$index) { - while (true) { - let over = loop$over; - let acc = loop$acc; - let with$ = loop$with; - let index = loop$index; - if (over instanceof $Empty) { - return acc; - } else { - let first$1 = over.head; - let rest$1 = over.tail; - loop$over = rest$1; - loop$acc = with$(acc, first$1, index); - loop$with = with$; - loop$index = index + 1; - } - } -} - -/** - * Like `fold` but the folding function also receives the index of the current element. - * - * ## Examples - * - * ```gleam - * assert ["a", "b", "c"] - * |> index_fold("", fn(acc, item, index) { - * acc <> int.to_string(index) <> ":" <> item <> " " - * }) - * == "0:a 1:b 2:c" - * ``` - * - * ```gleam - * assert [10, 20, 30] - * |> index_fold(0, fn(acc, item, index) { acc + item * index }) - * == 80 - * ``` - */ -export function index_fold(list, initial, fun) { - return index_fold_loop(list, initial, fun, 0); -} - -/** - * A variant of fold that might fail. - * - * The folding function should return `Result(accumulator, error)`. - * If the returned value is `Ok(accumulator)` try_fold will try the next value in the list. - * If the returned value is `Error(error)` try_fold will stop and return that error. - * - * ## Examples - * - * ```gleam - * assert [1, 2, 3, 4] - * |> try_fold(0, fn(acc, i) { - * case i < 3 { - * True -> Ok(acc + i) - * False -> Error(Nil) - * } - * }) - * == Error(Nil) - * ``` - */ -export function try_fold(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return new Ok(initial); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(initial, first$1); - if ($ instanceof Ok) { - let result = $[0]; - loop$list = rest$1; - loop$initial = result; - loop$fun = fun; - } else { - return $; - } - } - } -} - -/** - * A variant of fold that allows to stop folding earlier. - * - * The folding function should return `ContinueOrStop(accumulator)`. - * If the returned value is `Continue(accumulator)` fold_until will try the next value in the list. - * If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator. - * - * ## Examples - * - * ```gleam - * assert [1, 2, 3, 4] - * |> fold_until(0, fn(acc, i) { - * case i < 3 { - * True -> Continue(acc + i) - * False -> Stop(acc) - * } - * }) - * == 3 - * ``` - */ -export function fold_until(loop$list, loop$initial, loop$fun) { - while (true) { - let list = loop$list; - let initial = loop$initial; - let fun = loop$fun; - if (list instanceof $Empty) { - return initial; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(initial, first$1); - if ($ instanceof Continue) { - let next_accumulator = $[0]; - loop$list = rest$1; - loop$initial = next_accumulator; - loop$fun = fun; - } else { - let b = $[0]; - return b; - } - } - } -} - -/** - * Finds the first element in a given list for which the given function returns - * `True`. - * - * Returns `Error(Nil)` if no such element is found. - * - * ## Examples - * - * ```gleam - * assert find([1, 2, 3], fn(x) { x > 2 }) == Ok(3) - * ``` - * - * ```gleam - * assert find([1, 2, 3], fn(x) { x > 4 }) == Error(Nil) - * ``` - * - * ```gleam - * assert find([], fn(_) { True }) == Error(Nil) - * ``` - */ -export function find(loop$list, loop$is_desired) { - while (true) { - let list = loop$list; - let is_desired = loop$is_desired; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = is_desired(first$1); - if ($) { - return new Ok(first$1); - } else { - loop$list = rest$1; - loop$is_desired = is_desired; - } - } - } -} - -/** - * Finds the first element in a given list for which the given function returns - * `Ok(new_value)`, then returns the wrapped `new_value`. - * - * Returns `Error(Nil)` if no such element is found. - * - * ## Examples - * - * ```gleam - * assert find_map([[], [2], [3]], first) == Ok(2) - * ``` - * - * ```gleam - * assert find_map([[], []], first) == Error(Nil) - * ``` - * - * ```gleam - * assert find_map([], first) == Error(Nil) - * ``` - */ -export function find_map(loop$list, loop$fun) { - while (true) { - let list = loop$list; - let fun = loop$fun; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(first$1); - if ($ instanceof Ok) { - return $; - } else { - loop$list = rest$1; - loop$fun = fun; - } - } - } -} - -/** - * Returns `True` if the given function returns `True` for all the elements in - * the given list. If the function returns `False` for any of the elements it - * immediately returns `False` without checking the rest of the list. - * - * ## Examples - * - * ```gleam - * assert all([], fn(x) { x > 3 }) - * ``` - * - * ```gleam - * assert all([4, 5], fn(x) { x > 3 }) - * ``` - * - * ```gleam - * assert !all([4, 3], fn(x) { x > 3 }) - * ``` - */ -export function all(loop$list, loop$predicate) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - if (list instanceof $Empty) { - return true; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - } else { - return $; - } - } - } -} - -/** - * Returns `True` if the given function returns `True` for any the elements in - * the given list. If the function returns `True` for any of the elements it - * immediately returns `True` without checking the rest of the list. - * - * ## Examples - * - * ```gleam - * assert !any([], fn(x) { x > 3 }) - * ``` - * - * ```gleam - * assert any([4, 5], fn(x) { x > 3 }) - * ``` - * - * ```gleam - * assert any([4, 3], fn(x) { x > 4 }) - * ``` - * - * ```gleam - * assert any([3, 4], fn(x) { x > 3 }) - * ``` - */ -export function any(loop$list, loop$predicate) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - if (list instanceof $Empty) { - return false; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - return $; - } else { - loop$list = rest$1; - loop$predicate = predicate; - } - } - } -} - -function zip_loop(loop$one, loop$other, loop$acc) { - while (true) { - let one = loop$one; - let other = loop$other; - let acc = loop$acc; - if (one instanceof $Empty) { - return reverse(acc); - } else if (other instanceof $Empty) { - return reverse(acc); - } else { - let first_one = one.head; - let rest_one = one.tail; - let first_other = other.head; - let rest_other = other.tail; - loop$one = rest_one; - loop$other = rest_other; - loop$acc = listPrepend([first_one, first_other], acc); - } - } -} - -/** - * Takes two lists and returns a single list of 2-element tuples. - * - * If one of the lists is longer than the other, the remaining elements from - * the longer list are not used. - * - * ## Examples - * - * ```gleam - * assert zip([], []) == [] - * ``` - * - * ```gleam - * assert zip([1, 2], [3]) == [#(1, 3)] - * ``` - * - * ```gleam - * assert zip([1], [3, 4]) == [#(1, 3)] - * ``` - * - * ```gleam - * assert zip([1, 2], [3, 4]) == [#(1, 3), #(2, 4)] - * ``` - */ -export function zip(list, other) { - return zip_loop(list, other, toList([])); -} - -function strict_zip_loop(loop$one, loop$other, loop$acc) { - while (true) { - let one = loop$one; - let other = loop$other; - let acc = loop$acc; - if (one instanceof $Empty) { - if (other instanceof $Empty) { - return new Ok(reverse(acc)); - } else { - return new Error(undefined); - } - } else if (other instanceof $Empty) { - return new Error(undefined); - } else { - let first_one = one.head; - let rest_one = one.tail; - let first_other = other.head; - let rest_other = other.tail; - loop$one = rest_one; - loop$other = rest_other; - loop$acc = listPrepend([first_one, first_other], acc); - } - } -} - -/** - * Takes two lists and returns a single list of 2-element tuples. - * - * If one of the lists is longer than the other, an `Error` is returned. - * - * ## Examples - * - * ```gleam - * assert strict_zip([], []) == Ok([]) - * ``` - * - * ```gleam - * assert strict_zip([1, 2], [3]) == Error(Nil) - * ``` - * - * ```gleam - * assert strict_zip([1], [3, 4]) == Error(Nil) - * ``` - * - * ```gleam - * assert strict_zip([1, 2], [3, 4]) == Ok([#(1, 3), #(2, 4)]) - * ``` - */ -export function strict_zip(list, other) { - return strict_zip_loop(list, other, toList([])); -} - -function unzip_loop(loop$input, loop$one, loop$other) { - while (true) { - let input = loop$input; - let one = loop$one; - let other = loop$other; - if (input instanceof $Empty) { - return [reverse(one), reverse(other)]; - } else { - let rest$1 = input.tail; - let first_one = input.head[0]; - let first_other = input.head[1]; - loop$input = rest$1; - loop$one = listPrepend(first_one, one); - loop$other = listPrepend(first_other, other); - } - } -} - -/** - * Takes a single list of 2-element tuples and returns two lists. - * - * ## Examples - * - * ```gleam - * assert unzip([#(1, 2), #(3, 4)]) == #([1, 3], [2, 4]) - * ``` - * - * ```gleam - * assert unzip([]) == #([], []) - * ``` - */ -export function unzip(input) { - return unzip_loop(input, toList([]), toList([])); -} - -function intersperse_loop(loop$list, loop$separator, loop$acc) { - while (true) { - let list = loop$list; - let separator = loop$separator; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$separator = separator; - loop$acc = listPrepend(first$1, listPrepend(separator, acc)); - } - } -} - -/** - * Inserts a given value between each existing element in a given list. - * - * This function runs in linear time and copies the list. - * - * ## Examples - * - * ```gleam - * assert intersperse([1, 1, 1], 2) == [1, 2, 1, 2, 1] - * ``` - * - * ```gleam - * assert intersperse([], 2) == [] - * ``` - */ -export function intersperse(list, elem) { - if (list instanceof $Empty) { - return list; - } else { - let $ = list.tail; - if ($ instanceof $Empty) { - return list; - } else { - let first$1 = list.head; - let rest$1 = $; - return intersperse_loop(rest$1, elem, toList([first$1])); - } - } -} - -function unique_loop(loop$list, loop$seen, loop$acc) { - while (true) { - let list = loop$list; - let seen = loop$seen; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = $dict.has_key(seen, first$1); - if ($) { - loop$list = rest$1; - loop$seen = seen; - loop$acc = acc; - } else { - loop$list = rest$1; - loop$seen = $dict.insert(seen, first$1, undefined); - loop$acc = listPrepend(first$1, acc); - } - } - } -} - -/** - * Removes any duplicate elements from a given list. - * - * This function returns in loglinear time. - * - * ## Examples - * - * ```gleam - * assert unique([1, 1, 1, 4, 7, 3, 3, 4]) == [1, 4, 7, 3] - * ``` - */ -export function unique(list) { - return unique_loop(list, $dict.new$(), toList([])); -} - -/** - * This is exactly the same as merge_ascendings but mirrored: it merges two - * lists sorted in descending order into a single list sorted in ascending - * order according to the given comparator function. - * - * This reversing of the sort order is not avoidable if we want to implement - * merge as a tail recursive function. We could reverse the accumulator before - * returning it but that would end up being less efficient; so the merging - * algorithm has to play around this. - * - * @ignore - */ -function merge_descendings(loop$list1, loop$list2, loop$compare, loop$acc) { - while (true) { - let list1 = loop$list1; - let list2 = loop$list2; - let compare = loop$compare; - let acc = loop$acc; - if (list1 instanceof $Empty) { - let list = list2; - return reverse_and_prepend(list, acc); - } else if (list2 instanceof $Empty) { - let list = list1; - return reverse_and_prepend(list, acc); - } else { - let first1 = list1.head; - let rest1 = list1.tail; - let first2 = list2.head; - let rest2 = list2.tail; - let $ = compare(first1, first2); - if ($ instanceof $order.Lt) { - loop$list1 = list1; - loop$list2 = rest2; - loop$compare = compare; - loop$acc = listPrepend(first2, acc); - } else if ($ instanceof $order.Eq) { - loop$list1 = rest1; - loop$list2 = list2; - loop$compare = compare; - loop$acc = listPrepend(first1, acc); - } else { - loop$list1 = rest1; - loop$list2 = list2; - loop$compare = compare; - loop$acc = listPrepend(first1, acc); - } - } - } -} - -/** - * This is the same as merge_ascending_pairs but flipped for descending lists. - * - * @ignore - */ -function merge_descending_pairs(loop$sequences, loop$compare, loop$acc) { - while (true) { - let sequences = loop$sequences; - let compare = loop$compare; - let acc = loop$acc; - if (sequences instanceof $Empty) { - return reverse(acc); - } else { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return reverse(listPrepend(reverse(sequence), acc)); - } else { - let descending1 = sequences.head; - let descending2 = $.head; - let rest$1 = $.tail; - let ascending = merge_descendings( - descending1, - descending2, - compare, - toList([]), - ); - loop$sequences = rest$1; - loop$compare = compare; - loop$acc = listPrepend(ascending, acc); - } - } - } -} - -/** - * Merges two lists sorted in ascending order into a single list sorted in - * descending order according to the given comparator function. - * - * This reversing of the sort order is not avoidable if we want to implement - * merge as a tail recursive function. We could reverse the accumulator before - * returning it but that would end up being less efficient; so the merging - * algorithm has to play around this. - * - * @ignore - */ -function merge_ascendings(loop$list1, loop$list2, loop$compare, loop$acc) { - while (true) { - let list1 = loop$list1; - let list2 = loop$list2; - let compare = loop$compare; - let acc = loop$acc; - if (list1 instanceof $Empty) { - let list = list2; - return reverse_and_prepend(list, acc); - } else if (list2 instanceof $Empty) { - let list = list1; - return reverse_and_prepend(list, acc); - } else { - let first1 = list1.head; - let rest1 = list1.tail; - let first2 = list2.head; - let rest2 = list2.tail; - let $ = compare(first1, first2); - if ($ instanceof $order.Lt) { - loop$list1 = rest1; - loop$list2 = list2; - loop$compare = compare; - loop$acc = listPrepend(first1, acc); - } else if ($ instanceof $order.Eq) { - loop$list1 = list1; - loop$list2 = rest2; - loop$compare = compare; - loop$acc = listPrepend(first2, acc); - } else { - loop$list1 = list1; - loop$list2 = rest2; - loop$compare = compare; - loop$acc = listPrepend(first2, acc); - } - } - } -} - -/** - * Given a list of ascending lists, it merges adjacent pairs into a single - * descending list, halving their number. - * It returns a list of the remaining descending lists. - * - * @ignore - */ -function merge_ascending_pairs(loop$sequences, loop$compare, loop$acc) { - while (true) { - let sequences = loop$sequences; - let compare = loop$compare; - let acc = loop$acc; - if (sequences instanceof $Empty) { - return reverse(acc); - } else { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return reverse(listPrepend(reverse(sequence), acc)); - } else { - let ascending1 = sequences.head; - let ascending2 = $.head; - let rest$1 = $.tail; - let descending = merge_ascendings( - ascending1, - ascending2, - compare, - toList([]), - ); - loop$sequences = rest$1; - loop$compare = compare; - loop$acc = listPrepend(descending, acc); - } - } - } -} - -/** - * Given some some sorted sequences (assumed to be sorted in `direction`) it - * merges them all together until we're left with just a list sorted in - * ascending order. - * - * @ignore - */ -function merge_all(loop$sequences, loop$direction, loop$compare) { - while (true) { - let sequences = loop$sequences; - let direction = loop$direction; - let compare = loop$compare; - if (sequences instanceof $Empty) { - return sequences; - } else if (direction instanceof Ascending) { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return sequence; - } else { - let sequences$1 = merge_ascending_pairs(sequences, compare, toList([])); - loop$sequences = sequences$1; - loop$direction = new Descending(); - loop$compare = compare; - } - } else { - let $ = sequences.tail; - if ($ instanceof $Empty) { - let sequence = sequences.head; - return reverse(sequence); - } else { - let sequences$1 = merge_descending_pairs(sequences, compare, toList([])); - loop$sequences = sequences$1; - loop$direction = new Ascending(); - loop$compare = compare; - } - } - } -} - -/** - * Given a list it returns slices of it that are locally sorted in ascending - * order. - * - * Imagine you have this list: - * - * ``` - * [1, 2, 3, 2, 1, 0] - * ^^^^^^^ ^^^^^^^ This is a slice in descending order - * | - * | This is a slice that is sorted in ascending order - * ``` - * - * So the produced result will contain these two slices, each one sorted in - * ascending order: `[[1, 2, 3], [0, 1, 2]]`. - * - * - `growing` is an accumulator with the current slice being grown - * - `direction` is the growing direction of the slice being grown, it could - * either be ascending or strictly descending - * - `prev` is the previous element that needs to be added to the growing slice - * it is carried around to check whether we have to keep growing the current - * slice or not - * - `acc` is the accumulator containing the slices sorted in ascending order - * - * @ignore - */ -function sequences( - loop$list, - loop$compare, - loop$growing, - loop$direction, - loop$prev, - loop$acc -) { - while (true) { - let list = loop$list; - let compare = loop$compare; - let growing = loop$growing; - let direction = loop$direction; - let prev = loop$prev; - let acc = loop$acc; - let growing$1 = listPrepend(prev, growing); - if (list instanceof $Empty) { - if (direction instanceof Ascending) { - return listPrepend(reverse(growing$1), acc); - } else { - return listPrepend(growing$1, acc); - } - } else { - let new$1 = list.head; - let rest$1 = list.tail; - let $ = compare(prev, new$1); - if (direction instanceof Ascending) { - if ($ instanceof $order.Lt) { - loop$list = rest$1; - loop$compare = compare; - loop$growing = growing$1; - loop$direction = direction; - loop$prev = new$1; - loop$acc = acc; - } else if ($ instanceof $order.Eq) { - loop$list = rest$1; - loop$compare = compare; - loop$growing = growing$1; - loop$direction = direction; - loop$prev = new$1; - loop$acc = acc; - } else { - let _block; - if (direction instanceof Ascending) { - _block = listPrepend(reverse(growing$1), acc); - } else { - _block = listPrepend(growing$1, acc); - } - let acc$1 = _block; - if (rest$1 instanceof $Empty) { - return listPrepend(toList([new$1]), acc$1); - } else { - let next = rest$1.head; - let rest$2 = rest$1.tail; - let _block$1; - let $1 = compare(new$1, next); - if ($1 instanceof $order.Lt) { - _block$1 = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block$1 = new Ascending(); - } else { - _block$1 = new Descending(); - } - let direction$1 = _block$1; - loop$list = rest$2; - loop$compare = compare; - loop$growing = toList([new$1]); - loop$direction = direction$1; - loop$prev = next; - loop$acc = acc$1; - } - } - } else if ($ instanceof $order.Lt) { - let _block; - if (direction instanceof Ascending) { - _block = listPrepend(reverse(growing$1), acc); - } else { - _block = listPrepend(growing$1, acc); - } - let acc$1 = _block; - if (rest$1 instanceof $Empty) { - return listPrepend(toList([new$1]), acc$1); - } else { - let next = rest$1.head; - let rest$2 = rest$1.tail; - let _block$1; - let $1 = compare(new$1, next); - if ($1 instanceof $order.Lt) { - _block$1 = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block$1 = new Ascending(); - } else { - _block$1 = new Descending(); - } - let direction$1 = _block$1; - loop$list = rest$2; - loop$compare = compare; - loop$growing = toList([new$1]); - loop$direction = direction$1; - loop$prev = next; - loop$acc = acc$1; - } - } else if ($ instanceof $order.Eq) { - let _block; - if (direction instanceof Ascending) { - _block = listPrepend(reverse(growing$1), acc); - } else { - _block = listPrepend(growing$1, acc); - } - let acc$1 = _block; - if (rest$1 instanceof $Empty) { - return listPrepend(toList([new$1]), acc$1); - } else { - let next = rest$1.head; - let rest$2 = rest$1.tail; - let _block$1; - let $1 = compare(new$1, next); - if ($1 instanceof $order.Lt) { - _block$1 = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block$1 = new Ascending(); - } else { - _block$1 = new Descending(); - } - let direction$1 = _block$1; - loop$list = rest$2; - loop$compare = compare; - loop$growing = toList([new$1]); - loop$direction = direction$1; - loop$prev = next; - loop$acc = acc$1; - } - } else { - loop$list = rest$1; - loop$compare = compare; - loop$growing = growing$1; - loop$direction = direction; - loop$prev = new$1; - loop$acc = acc; - } - } - } -} - -/** - * Sorts from smallest to largest based upon the ordering specified by a given - * function. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * assert sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) == [1, 2, 3, 4, 4, 5, 6] - * ``` - */ -export function sort(list, compare) { - if (list instanceof $Empty) { - return list; - } else { - let $ = list.tail; - if ($ instanceof $Empty) { - return list; - } else { - let x = list.head; - let y = $.head; - let rest$1 = $.tail; - let _block; - let $1 = compare(x, y); - if ($1 instanceof $order.Lt) { - _block = new Ascending(); - } else if ($1 instanceof $order.Eq) { - _block = new Ascending(); - } else { - _block = new Descending(); - } - let direction = _block; - let sequences$1 = sequences( - rest$1, - compare, - toList([x]), - direction, - y, - toList([]), - ); - return merge_all(sequences$1, new Ascending(), compare); - } - } -} - -function repeat_loop(loop$item, loop$times, loop$acc) { - while (true) { - let item = loop$item; - let times = loop$times; - let acc = loop$acc; - let $ = times <= 0; - if ($) { - return acc; - } else { - loop$item = item; - loop$times = times - 1; - loop$acc = listPrepend(item, acc); - } - } -} - -/** - * Builds a list of a given value a given number of times. - * - * ## Examples - * - * ```gleam - * assert repeat("a", times: 0) == [] - * ``` - * - * ```gleam - * assert repeat("a", times: 5) == ["a", "a", "a", "a", "a"] - * ``` - */ -export function repeat(a, times) { - return repeat_loop(a, times, toList([])); -} - -function split_loop(loop$list, loop$n, loop$taken) { - while (true) { - let list = loop$list; - let n = loop$n; - let taken = loop$taken; - let $ = n <= 0; - if ($) { - return [reverse(taken), list]; - } else { - if (list instanceof $Empty) { - return [reverse(taken), toList([])]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$n = n - 1; - loop$taken = listPrepend(first$1, taken); - } - } - } -} - -/** - * Splits a list in two before the given index. - * - * If the list is not long enough to have the given index the before list will - * be the input list, and the after list will be empty. - * - * ## Examples - * - * ```gleam - * assert split([6, 7, 8, 9], 0) == #([], [6, 7, 8, 9]) - * ``` - * - * ```gleam - * assert split([6, 7, 8, 9], 2) == #([6, 7], [8, 9]) - * ``` - * - * ```gleam - * assert split([6, 7, 8, 9], 4) == #([6, 7, 8, 9], []) - * ``` - */ -export function split(list, index) { - return split_loop(list, index, toList([])); -} - -function split_while_loop(loop$list, loop$f, loop$acc) { - while (true) { - let list = loop$list; - let f = loop$f; - let acc = loop$acc; - if (list instanceof $Empty) { - return [reverse(acc), toList([])]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = f(first$1); - if ($) { - loop$list = rest$1; - loop$f = f; - loop$acc = listPrepend(first$1, acc); - } else { - return [reverse(acc), list]; - } - } - } -} - -/** - * Splits a list in two before the first element that a given function returns - * `False` for. - * - * If the function returns `True` for all elements the first list will be the - * input list, and the second list will be empty. - * - * ## Examples - * - * ```gleam - * assert split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 }) - * == #([1, 2, 3], [4, 5]) - * ``` - * - * ```gleam - * assert split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 }) - * == #([1, 2, 3, 4, 5], []) - * ``` - */ -export function split_while(list, predicate) { - return split_while_loop(list, predicate, toList([])); -} - -/** - * Given a list of 2-element tuples, finds the first tuple that has a given - * key as the first element and returns the second element. - * - * If no tuple is found with the given key then `Error(Nil)` is returned. - * - * This function may be useful for interacting with Erlang code where lists of - * tuples are common. - * - * ## Examples - * - * ```gleam - * assert key_find([#("a", 0), #("b", 1)], "a") == Ok(0) - * ``` - * - * ```gleam - * assert key_find([#("a", 0), #("b", 1)], "b") == Ok(1) - * ``` - * - * ```gleam - * assert key_find([#("a", 0), #("b", 1)], "c") == Error(Nil) - * ``` - */ -export function key_find(keyword_list, desired_key) { - return find_map( - keyword_list, - (keyword) => { - let key = keyword[0]; - let value = keyword[1]; - let $ = isEqual(key, desired_key); - if ($) { - return new Ok(value); - } else { - return new Error(undefined); - } - }, - ); -} - -/** - * Given a list of 2-element tuples, finds all tuples that have a given - * key as the first element and returns the second element. - * - * This function may be useful for interacting with Erlang code where lists of - * tuples are common. - * - * ## Examples - * - * ```gleam - * assert key_filter([#("a", 0), #("b", 1), #("a", 2)], "a") == [0, 2] - * ``` - * - * ```gleam - * assert key_filter([#("a", 0), #("b", 1)], "c") == [] - * ``` - */ -export function key_filter(keyword_list, desired_key) { - return filter_map( - keyword_list, - (keyword) => { - let key = keyword[0]; - let value = keyword[1]; - let $ = isEqual(key, desired_key); - if ($) { - return new Ok(value); - } else { - return new Error(undefined); - } - }, - ); -} - -function key_pop_loop(loop$list, loop$key, loop$checked) { - while (true) { - let list = loop$list; - let key = loop$key; - let checked = loop$checked; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let k = list.head[0]; - if (isEqual(k, key)) { - let rest$1 = list.tail; - let v = list.head[1]; - return new Ok([v, reverse_and_prepend(checked, rest$1)]); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$key = key; - loop$checked = listPrepend(first$1, checked); - } - } - } -} - -/** - * Given a list of 2-element tuples, finds the first tuple that has a given - * key as the first element. This function will return the second element - * of the found tuple and list with tuple removed. - * - * If no tuple is found with the given key then `Error(Nil)` is returned. - * - * ## Examples - * - * ```gleam - * assert key_pop([#("a", 0), #("b", 1)], "a") == Ok(#(0, [#("b", 1)])) - * ``` - * - * ```gleam - * assert key_pop([#("a", 0), #("b", 1)], "b") == Ok(#(1, [#("a", 0)])) - * ``` - * - * ```gleam - * assert key_pop([#("a", 0), #("b", 1)], "c") == Error(Nil) - * ``` - */ -export function key_pop(list, key) { - return key_pop_loop(list, key, toList([])); -} - -function key_set_loop(loop$list, loop$key, loop$value, loop$inspected) { - while (true) { - let list = loop$list; - let key = loop$key; - let value = loop$value; - let inspected = loop$inspected; - if (list instanceof $Empty) { - return reverse(listPrepend([key, value], inspected)); - } else { - let k = list.head[0]; - if (isEqual(k, key)) { - let rest$1 = list.tail; - return reverse_and_prepend(inspected, listPrepend([k, value], rest$1)); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - loop$list = rest$1; - loop$key = key; - loop$value = value; - loop$inspected = listPrepend(first$1, inspected); - } - } - } -} - -/** - * Given a list of 2-element tuples, inserts a key and value into the list. - * - * If there was already a tuple with the key then it is replaced, otherwise it - * is added to the end of the list. - * - * ## Examples - * - * ```gleam - * assert key_set([#(5, 0), #(4, 1)], 4, 100) == [#(5, 0), #(4, 100)] - * ``` - * - * ```gleam - * assert key_set([#(5, 0), #(4, 1)], 1, 100) == [#(5, 0), #(4, 1), #(1, 100)] - * ``` - */ -export function key_set(list, key, value) { - return key_set_loop(list, key, value, toList([])); -} - -/** - * Calls a function for each element in a list, discarding the return value. - * - * Useful for calling a side effect for every item of a list. - * - * ```gleam - * import gleam/io - * - * assert each(["1", "2", "3"], io.println) == Nil - * // 1 - * // 2 - * // 3 - * ``` - */ -export function each(loop$list, loop$f) { - while (true) { - let list = loop$list; - let f = loop$f; - if (list instanceof $Empty) { - return undefined; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - f(first$1); - loop$list = rest$1; - loop$f = f; - } - } -} - -/** - * Calls a `Result` returning function for each element in a list, discarding - * the return value. If the function returns `Error` then the iteration is - * stopped and the error is returned. - * - * Useful for calling a side effect for every item of a list. - * - * ## Examples - * - * ```gleam - * assert - * try_each( - * over: [1, 2, 3], - * with: function_that_might_fail, - * ) - * == Ok(Nil) - * ``` - */ -export function try_each(loop$list, loop$fun) { - while (true) { - let list = loop$list; - let fun = loop$fun; - if (list instanceof $Empty) { - return new Ok(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = fun(first$1); - if ($ instanceof Ok) { - loop$list = rest$1; - loop$fun = fun; - } else { - return $; - } - } - } -} - -function partition_loop(loop$list, loop$categorise, loop$trues, loop$falses) { - while (true) { - let list = loop$list; - let categorise = loop$categorise; - let trues = loop$trues; - let falses = loop$falses; - if (list instanceof $Empty) { - return [reverse(trues), reverse(falses)]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = categorise(first$1); - if ($) { - loop$list = rest$1; - loop$categorise = categorise; - loop$trues = listPrepend(first$1, trues); - loop$falses = falses; - } else { - loop$list = rest$1; - loop$categorise = categorise; - loop$trues = trues; - loop$falses = listPrepend(first$1, falses); - } - } - } -} - -/** - * Partitions a list into a tuple/pair of lists - * by a given categorisation function. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * assert [1, 2, 3, 4, 5] |> partition(int.is_odd) == #([1, 3, 5], [2, 4]) - * ``` - */ -export function partition(list, categorise) { - return partition_loop(list, categorise, toList([]), toList([])); -} - -function permutation_prepend( - loop$el, - loop$permutations, - loop$list_1, - loop$list_2, - loop$acc -) { - while (true) { - let el = loop$el; - let permutations = loop$permutations; - let list_1 = loop$list_1; - let list_2 = loop$list_2; - let acc = loop$acc; - if (permutations instanceof $Empty) { - return permutation_zip(list_1, list_2, acc); - } else { - let head = permutations.head; - let tail = permutations.tail; - loop$el = el; - loop$permutations = tail; - loop$list_1 = list_1; - loop$list_2 = list_2; - loop$acc = listPrepend(listPrepend(el, head), acc); - } - } -} - -function permutation_zip(list, rest, acc) { - if (list instanceof $Empty) { - return reverse(acc); - } else { - let head = list.head; - let tail = list.tail; - return permutation_prepend( - head, - permutations(reverse_and_prepend(rest, tail)), - tail, - listPrepend(head, rest), - acc, - ); - } -} - -/** - * Returns all the permutations of a list. - * - * ## Examples - * - * ```gleam - * assert permutations([1, 2]) == [[1, 2], [2, 1]] - * ``` - */ -export function permutations(list) { - if (list instanceof $Empty) { - return toList([toList([])]); - } else { - let l = list; - return permutation_zip(l, toList([]), toList([])); - } -} - -function window_loop(loop$acc, loop$list, loop$n) { - while (true) { - let acc = loop$acc; - let list = loop$list; - let n = loop$n; - let window$1 = take(list, n); - let $ = length(window$1) === n; - if ($) { - loop$acc = listPrepend(window$1, acc); - loop$list = drop(list, 1); - loop$n = n; - } else { - return reverse(acc); - } - } -} - -/** - * Returns a list of sliding windows. - * - * ## Examples - * - * ```gleam - * assert window([1,2,3,4,5], 3) == [[1, 2, 3], [2, 3, 4], [3, 4, 5]] - * ``` - * - * ```gleam - * assert window([1, 2], 4) == [] - * ``` - */ -export function window(list, n) { - let $ = n <= 0; - if ($) { - return toList([]); - } else { - return window_loop(toList([]), list, n); - } -} - -/** - * Returns a list of tuples containing two contiguous elements. - * - * ## Examples - * - * ```gleam - * assert window_by_2([1,2,3,4]) == [#(1, 2), #(2, 3), #(3, 4)] - * ``` - * - * ```gleam - * assert window_by_2([1]) == [] - * ``` - */ -export function window_by_2(list) { - return zip(list, drop(list, 1)); -} - -/** - * Drops the first elements in a given list for which the predicate function returns `True`. - * - * ## Examples - * - * ```gleam - * assert drop_while([1, 2, 3, 4], fn (x) { x < 3 }) == [3, 4] - * ``` - */ -export function drop_while(loop$list, loop$predicate) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - if (list instanceof $Empty) { - return list; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - } else { - return listPrepend(first$1, rest$1); - } - } - } -} - -function take_while_loop(loop$list, loop$predicate, loop$acc) { - while (true) { - let list = loop$list; - let predicate = loop$predicate; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = predicate(first$1); - if ($) { - loop$list = rest$1; - loop$predicate = predicate; - loop$acc = listPrepend(first$1, acc); - } else { - return reverse(acc); - } - } - } -} - -/** - * Takes the first elements in a given list for which the predicate function returns `True`. - * - * ## Examples - * - * ```gleam - * assert take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) == [1, 2] - * ``` - */ -export function take_while(list, predicate) { - return take_while_loop(list, predicate, toList([])); -} - -function chunk_loop( - loop$list, - loop$f, - loop$previous_key, - loop$current_chunk, - loop$acc -) { - while (true) { - let list = loop$list; - let f = loop$f; - let previous_key = loop$previous_key; - let current_chunk = loop$current_chunk; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(listPrepend(reverse(current_chunk), acc)); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let key = f(first$1); - let $ = isEqual(key, previous_key); - if ($) { - loop$list = rest$1; - loop$f = f; - loop$previous_key = key; - loop$current_chunk = listPrepend(first$1, current_chunk); - loop$acc = acc; - } else { - let new_acc = listPrepend(reverse(current_chunk), acc); - loop$list = rest$1; - loop$f = f; - loop$previous_key = key; - loop$current_chunk = toList([first$1]); - loop$acc = new_acc; - } - } - } -} - -/** - * Returns a list of chunks in which - * the return value of calling `f` on each element is the same. - * - * ## Examples - * - * ```gleam - * assert [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 }) - * == [[1], [2, 2], [3], [4, 4, 6], [7, 7]] - * ``` - */ -export function chunk(list, f) { - if (list instanceof $Empty) { - return list; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return chunk_loop(rest$1, f, f(first$1), toList([first$1]), toList([])); - } -} - -function sized_chunk_loop( - loop$list, - loop$count, - loop$left, - loop$current_chunk, - loop$acc -) { - while (true) { - let list = loop$list; - let count = loop$count; - let left = loop$left; - let current_chunk = loop$current_chunk; - let acc = loop$acc; - if (list instanceof $Empty) { - if (current_chunk instanceof $Empty) { - return reverse(acc); - } else { - let remaining = current_chunk; - return reverse(listPrepend(reverse(remaining), acc)); - } - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let chunk$1 = listPrepend(first$1, current_chunk); - let $ = left > 1; - if ($) { - loop$list = rest$1; - loop$count = count; - loop$left = left - 1; - loop$current_chunk = chunk$1; - loop$acc = acc; - } else { - loop$list = rest$1; - loop$count = count; - loop$left = count; - loop$current_chunk = toList([]); - loop$acc = listPrepend(reverse(chunk$1), acc); - } - } - } -} - -/** - * Returns a list of chunks containing `count` elements each. - * - * If the last chunk does not have `count` elements, it is instead - * a partial chunk, with less than `count` elements. - * - * For any `count` less than 1 this function behaves as if it was set to 1. - * - * ## Examples - * - * ```gleam - * assert [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2) - * == [[1, 2], [3, 4], [5, 6]] - * ``` - * - * ```gleam - * assert [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3) - * == [[1, 2, 3], [4, 5, 6], [7, 8]] - * ``` - */ -export function sized_chunk(list, count) { - return sized_chunk_loop(list, count, count, toList([]), toList([])); -} - -/** - * This function acts similar to fold, but does not take an initial state. - * Instead, it starts from the first element in the list - * and combines it with each subsequent element in turn using the given - * function. The function is called as `fun(accumulator, current_element)`. - * - * Returns `Ok` to indicate a successful run, and `Error` if called on an - * empty list. - * - * ## Examples - * - * ```gleam - * assert [] |> reduce(fn(acc, x) { acc + x }) == Error(Nil) - * ``` - * - * ```gleam - * assert [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) == Ok(15) - * ``` - */ -export function reduce(list, fun) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return new Ok(fold(rest$1, first$1, fun)); - } -} - -function scan_loop(loop$list, loop$accumulator, loop$accumulated, loop$fun) { - while (true) { - let list = loop$list; - let accumulator = loop$accumulator; - let accumulated = loop$accumulated; - let fun = loop$fun; - if (list instanceof $Empty) { - return reverse(accumulated); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let next = fun(accumulator, first$1); - loop$list = rest$1; - loop$accumulator = next; - loop$accumulated = listPrepend(next, accumulated); - loop$fun = fun; - } - } -} - -/** - * Similar to `fold`, but yields the state of the accumulator at each stage. - * - * ## Examples - * - * ```gleam - * assert scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i }) - * == [101, 103, 106] - * ``` - */ -export function scan(list, initial, fun) { - return scan_loop(list, initial, toList([]), fun); -} - -/** - * Returns the last element in the given list. - * - * Returns `Error(Nil)` if the list is empty. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * assert last([]) == Error(Nil) - * ``` - * - * ```gleam - * assert last([1, 2, 3, 4, 5]) == Ok(5) - * ``` - */ -export function last(loop$list) { - while (true) { - let list = loop$list; - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let $ = list.tail; - if ($ instanceof $Empty) { - let last$1 = list.head; - return new Ok(last$1); - } else { - let rest$1 = $; - loop$list = rest$1; - } - } - } -} - -/** - * Return unique combinations of elements in the list. - * - * ## Examples - * - * ```gleam - * assert combinations([1, 2, 3], 2) == [[1, 2], [1, 3], [2, 3]] - * ``` - * - * ```gleam - * assert combinations([1, 2, 3, 4], 3) - * == [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]] - * ``` - */ -export function combinations(items, n) { - if (n === 0) { - return toList([toList([])]); - } else if (items instanceof $Empty) { - return items; - } else { - let first$1 = items.head; - let rest$1 = items.tail; - let _pipe = rest$1; - let _pipe$1 = combinations(_pipe, n - 1); - let _pipe$2 = map( - _pipe$1, - (combination) => { return listPrepend(first$1, combination); }, - ); - let _pipe$3 = reverse(_pipe$2); - return fold( - _pipe$3, - combinations(rest$1, n), - (acc, c) => { return listPrepend(c, acc); }, - ); - } -} - -function combination_pairs_loop(loop$items, loop$acc) { - while (true) { - let items = loop$items; - let acc = loop$acc; - if (items instanceof $Empty) { - return reverse(acc); - } else { - let first$1 = items.head; - let rest$1 = items.tail; - let first_combinations = map( - rest$1, - (other) => { return [first$1, other]; }, - ); - let acc$1 = reverse_and_prepend(first_combinations, acc); - loop$items = rest$1; - loop$acc = acc$1; - } - } -} - -/** - * Return unique pair combinations of elements in the list. - * - * ## Examples - * - * ```gleam - * assert combination_pairs([1, 2, 3]) == [#(1, 2), #(1, 3), #(2, 3)] - * ``` - */ -export function combination_pairs(items) { - return combination_pairs_loop(items, toList([])); -} - -function take_firsts(loop$rows, loop$column, loop$remaining_rows) { - while (true) { - let rows = loop$rows; - let column = loop$column; - let remaining_rows = loop$remaining_rows; - if (rows instanceof $Empty) { - return [reverse(column), reverse(remaining_rows)]; - } else { - let $ = rows.head; - if ($ instanceof $Empty) { - let rest$1 = rows.tail; - loop$rows = rest$1; - loop$column = column; - loop$remaining_rows = remaining_rows; - } else { - let rest_rows = rows.tail; - let first$1 = $.head; - let remaining_row = $.tail; - let remaining_rows$1 = listPrepend(remaining_row, remaining_rows); - loop$rows = rest_rows; - loop$column = listPrepend(first$1, column); - loop$remaining_rows = remaining_rows$1; - } - } - } -} - -function transpose_loop(loop$rows, loop$columns) { - while (true) { - let rows = loop$rows; - let columns = loop$columns; - if (rows instanceof $Empty) { - return reverse(columns); - } else { - let $ = take_firsts(rows, toList([]), toList([])); - let column = $[0]; - let rest$1 = $[1]; - if (column instanceof $Empty) { - loop$rows = rest$1; - loop$columns = columns; - } else { - loop$rows = rest$1; - loop$columns = listPrepend(column, columns); - } - } - } -} - -/** - * Transpose rows and columns of the list of lists. - * - * Notice: This function is not tail recursive, - * and thus may exceed stack size if called, - * with large lists (on the JavaScript target). - * - * ## Examples - * - * ```gleam - * assert transpose([[1, 2, 3], [101, 102, 103]]) - * == [[1, 101], [2, 102], [3, 103]] - * ``` - */ -export function transpose(list_of_lists) { - return transpose_loop(list_of_lists, toList([])); -} - -/** - * Make a list alternating the elements from the given lists - * - * ## Examples - * - * ```gleam - * assert interleave([[1, 2], [101, 102], [201, 202]]) - * == [1, 101, 201, 2, 102, 202] - * ``` - */ -export function interleave(list) { - let _pipe = list; - let _pipe$1 = transpose(_pipe); - return flatten(_pipe$1); -} - -function shuffle_pair_unwrap_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return acc; - } else { - let elem_pair = list.head; - let enumerable = list.tail; - loop$list = enumerable; - loop$acc = listPrepend(elem_pair[1], acc); - } - } -} - -function do_shuffle_by_pair_indexes(list_of_pairs) { - return sort( - list_of_pairs, - (a_pair, b_pair) => { return $float.compare(a_pair[0], b_pair[0]); }, - ); -} - -/** - * Takes a list, randomly sorts all items and returns the shuffled list. - * - * This function uses `float.random` to decide the order of the elements. - * - * ## Example - * - * ```gleam - * [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |> shuffle - * // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5] - * ``` - */ -export function shuffle(list) { - let _pipe = list; - let _pipe$1 = fold( - _pipe, - toList([]), - (acc, a) => { return listPrepend([$float.random(), a], acc); }, - ); - let _pipe$2 = do_shuffle_by_pair_indexes(_pipe$1); - return shuffle_pair_unwrap_loop(_pipe$2, toList([])); -} - -function max_loop(loop$list, loop$compare, loop$max) { - while (true) { - let list = loop$list; - let compare = loop$compare; - let max = loop$max; - if (list instanceof $Empty) { - return max; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let $ = compare(first$1, max); - if ($ instanceof $order.Lt) { - loop$list = rest$1; - loop$compare = compare; - loop$max = max; - } else if ($ instanceof $order.Eq) { - loop$list = rest$1; - loop$compare = compare; - loop$max = max; - } else { - loop$list = rest$1; - loop$compare = compare; - loop$max = first$1; - } - } - } -} - -/** - * Takes a list and a comparator, and returns the maximum element in the list - * - * ## Examples - * - * ```gleam - * assert [1, 2, 3, 4, 5] |> list.max(int.compare) == Ok(5) - * ``` - * - * ```gleam - * assert ["a", "c", "b"] |> list.max(string.compare) == Ok("c") - * ``` - */ -export function max(list, compare) { - if (list instanceof $Empty) { - return new Error(undefined); - } else { - let first$1 = list.head; - let rest$1 = list.tail; - return new Ok(max_loop(rest$1, compare, first$1)); - } -} - -function log_random() { - let $ = $float.logarithm($float.random() + min_positive); - let random; - if ($ instanceof Ok) { - random = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam/list", - 2244, - "log_random", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 55129, - end: 55200, - pattern_start: 55140, - pattern_end: 55150 - } - ) - } - return random; -} - -function sample_loop(loop$list, loop$reservoir, loop$n, loop$w) { - while (true) { - let list = loop$list; - let reservoir = loop$reservoir; - let n = loop$n; - let w = loop$w; - let _block; - { - let $ = $float.logarithm(1.0 - w); - let log; - if ($ instanceof Ok) { - log = $[0]; - } else { - throw makeError( - "let_assert", - FILEPATH, - "gleam/list", - 2227, - "sample_loop", - "Pattern match failed, no pattern matched the value.", - { - value: $, - start: 54690, - end: 54736, - pattern_start: 54701, - pattern_end: 54708 - } - ) - } - _block = $float.round($float.floor(divideFloat(log_random(), log))); - } - let skip = _block; - let $ = drop(list, skip); - if ($ instanceof $Empty) { - return reservoir; - } else { - let first$1 = $.head; - let rest$1 = $.tail; - let reservoir$1 = $dict.insert(reservoir, $int.random(n), first$1); - let w$1 = w * $float.exponential( - divideFloat(log_random(), $int.to_float(n)), - ); - loop$list = rest$1; - loop$reservoir = reservoir$1; - loop$n = n; - loop$w = w$1; - } - } -} - -function build_reservoir_loop(loop$list, loop$size, loop$reservoir) { - while (true) { - let list = loop$list; - let size = loop$size; - let reservoir = loop$reservoir; - let reservoir_size = $dict.size(reservoir); - let $ = reservoir_size >= size; - if ($) { - return [reservoir, list]; - } else { - if (list instanceof $Empty) { - return [reservoir, toList([])]; - } else { - let first$1 = list.head; - let rest$1 = list.tail; - let reservoir$1 = $dict.insert(reservoir, reservoir_size, first$1); - loop$list = rest$1; - loop$size = size; - loop$reservoir = reservoir$1; - } - } - } -} - -/** - * Builds the initial reservoir used by Algorithm L. - * This is a dictionary with keys ranging from `0` up to `n - 1` where each - * value is the corresponding element at that position in `list`. - * - * This also returns the remaining elements of `list` that didn't end up in - * the reservoir. - * - * @ignore - */ -function build_reservoir(list, n) { - return build_reservoir_loop(list, n, $dict.new$()); -} - -/** - * Returns a random sample of up to n elements from a list using reservoir - * sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L). - * Returns an empty list if the sample size is less than or equal to 0. - * - * Order is not random, only selection is. - * - * ## Examples - * - * ```gleam - * sample([1, 2, 3, 4, 5], 3) - * // -> [2, 4, 5] // A random sample of 3 items - * ``` - */ -export function sample(list, n) { - let $ = build_reservoir(list, n); - let reservoir = $[0]; - let rest$1 = $[1]; - let $1 = $dict.is_empty(reservoir); - if ($1) { - return toList([]); - } else { - let w = $float.exponential(divideFloat(log_random(), $int.to_float(n))); - return $dict.values(sample_loop(rest$1, reservoir, n, w)); - } -} diff --git a/ui/javascript/gleam_stdlib/gleam/option.mjs b/ui/javascript/gleam_stdlib/gleam/option.mjs deleted file mode 100644 index 45c88cb..0000000 --- a/ui/javascript/gleam_stdlib/gleam/option.mjs +++ /dev/null @@ -1,386 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, -} from "../gleam.mjs"; - -export class Some extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Option$Some = ($0) => new Some($0); -export const Option$isSome = (value) => value instanceof Some; -export const Option$Some$0 = (value) => value[0]; - -export class None extends $CustomType {} -export const Option$None = () => new None(); -export const Option$isNone = (value) => value instanceof None; - -function reverse_and_prepend(loop$prefix, loop$suffix) { - while (true) { - let prefix = loop$prefix; - let suffix = loop$suffix; - if (prefix instanceof $Empty) { - return suffix; - } else { - let first = prefix.head; - let rest = prefix.tail; - loop$prefix = rest; - loop$suffix = listPrepend(first, suffix); - } - } -} - -function reverse(list) { - return reverse_and_prepend(list, toList([])); -} - -function all_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return new Some(reverse(acc)); - } else { - let $ = list.head; - if ($ instanceof Some) { - let rest = list.tail; - let first = $[0]; - loop$list = rest; - loop$acc = listPrepend(first, acc); - } else { - return new None(); - } - } - } -} - -/** - * Combines a list of `Option`s into a single `Option`. - * If all elements in the list are `Some` then returns a `Some` holding the list of values. - * If any element is `None` then returns `None`. - * - * ## Examples - * - * ```gleam - * assert all([Some(1), Some(2)]) == Some([1, 2]) - * ``` - * - * ```gleam - * assert all([Some(1), None]) == None - * ``` - */ -export function all(list) { - return all_loop(list, toList([])); -} - -/** - * Checks whether the `Option` is a `Some` value. - * - * ## Examples - * - * ```gleam - * assert is_some(Some(1)) - * ``` - * - * ```gleam - * assert !is_some(None) - * ``` - */ -export function is_some(option) { - return !(option instanceof None); -} - -/** - * Checks whether the `Option` is a `None` value. - * - * ## Examples - * - * ```gleam - * assert !is_none(Some(1)) - * ``` - * - * ```gleam - * assert is_none(None) - * ``` - */ -export function is_none(option) { - return option instanceof None; -} - -/** - * Converts an `Option` type to a `Result` type. - * - * ## Examples - * - * ```gleam - * assert to_result(Some(1), "some_error") == Ok(1) - * ``` - * - * ```gleam - * assert to_result(None, "some_error") == Error("some_error") - * ``` - */ -export function to_result(option, e) { - if (option instanceof Some) { - let a = option[0]; - return new Ok(a); - } else { - return new Error(e); - } -} - -/** - * Converts a `Result` type to an `Option` type. - * - * ## Examples - * - * ```gleam - * assert from_result(Ok(1)) == Some(1) - * ``` - * - * ```gleam - * assert from_result(Error("some_error")) == None - * ``` - */ -export function from_result(result) { - if (result instanceof Ok) { - let a = result[0]; - return new Some(a); - } else { - return new None(); - } -} - -/** - * Extracts the value from an `Option`, returning a default value if there is none. - * - * ## Examples - * - * ```gleam - * assert unwrap(Some(1), 0) == 1 - * ``` - * - * ```gleam - * assert unwrap(None, 0) == 0 - * ``` - */ -export function unwrap(option, default$) { - if (option instanceof Some) { - let x = option[0]; - return x; - } else { - return default$; - } -} - -/** - * Extracts the value from an `Option`, evaluating the default function if the option is `None`. - * - * ## Examples - * - * ```gleam - * assert lazy_unwrap(Some(1), fn() { 0 }) == 1 - * ``` - * - * ```gleam - * assert lazy_unwrap(None, fn() { 0 }) == 0 - * ``` - */ -export function lazy_unwrap(option, default$) { - if (option instanceof Some) { - let x = option[0]; - return x; - } else { - return default$(); - } -} - -/** - * Updates a value held within the `Some` of an `Option` by calling a given function - * on it. - * - * If the `Option` is a `None` rather than `Some`, the function is not called and the - * `Option` stays the same. - * - * ## Examples - * - * ```gleam - * assert map(over: Some(1), with: fn(x) { x + 1 }) == Some(2) - * ``` - * - * ```gleam - * assert map(over: None, with: fn(x) { x + 1 }) == None - * ``` - */ -export function map(option, fun) { - if (option instanceof Some) { - let x = option[0]; - return new Some(fun(x)); - } else { - return option; - } -} - -/** - * Merges a nested `Option` into a single layer. - * - * ## Examples - * - * ```gleam - * assert flatten(Some(Some(1))) == Some(1) - * ``` - * - * ```gleam - * assert flatten(Some(None)) == None - * ``` - * - * ```gleam - * assert flatten(None) == None - * ``` - */ -export function flatten(option) { - if (option instanceof Some) { - let x = option[0]; - return x; - } else { - return option; - } -} - -/** - * Updates a value held within the `Some` of an `Option` by calling a given function - * on it, where the given function also returns an `Option`. The two options are - * then merged together into one `Option`. - * - * If the `Option` is a `None` rather than `Some` the function is not called and the - * option stays the same. - * - * This function is the equivalent of calling `map` followed by `flatten`, and - * it is useful for chaining together multiple functions that return `Option`. - * - * ## Examples - * - * ```gleam - * assert then(Some(1), fn(x) { Some(x + 1) }) == Some(2) - * ``` - * - * ```gleam - * assert then(Some(1), fn(x) { Some(#("a", x)) }) == Some(#("a", 1)) - * ``` - * - * ```gleam - * assert then(Some(1), fn(_) { None }) == None - * ``` - * - * ```gleam - * assert then(None, fn(x) { Some(x + 1) }) == None - * ``` - */ -export function then$(option, fun) { - if (option instanceof Some) { - let x = option[0]; - return fun(x); - } else { - return option; - } -} - -/** - * Returns the first value if it is `Some`, otherwise returns the second value. - * - * ## Examples - * - * ```gleam - * assert or(Some(1), Some(2)) == Some(1) - * ``` - * - * ```gleam - * assert or(Some(1), None) == Some(1) - * ``` - * - * ```gleam - * assert or(None, Some(2)) == Some(2) - * ``` - * - * ```gleam - * assert or(None, None) == None - * ``` - */ -export function or(first, second) { - if (first instanceof Some) { - return first; - } else { - return second; - } -} - -/** - * Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value. - * - * ## Examples - * - * ```gleam - * assert lazy_or(Some(1), fn() { Some(2) }) == Some(1) - * ``` - * - * ```gleam - * assert lazy_or(Some(1), fn() { None }) == Some(1) - * ``` - * - * ```gleam - * assert lazy_or(None, fn() { Some(2) }) == Some(2) - * ``` - * - * ```gleam - * assert lazy_or(None, fn() { None }) == None - * ``` - */ -export function lazy_or(first, second) { - if (first instanceof Some) { - return first; - } else { - return second(); - } -} - -function values_loop(loop$list, loop$acc) { - while (true) { - let list = loop$list; - let acc = loop$acc; - if (list instanceof $Empty) { - return reverse(acc); - } else { - let $ = list.head; - if ($ instanceof Some) { - let rest = list.tail; - let first = $[0]; - loop$list = rest; - loop$acc = listPrepend(first, acc); - } else { - let rest = list.tail; - loop$list = rest; - loop$acc = acc; - } - } - } -} - -/** - * Given a list of `Option`s, - * returns only the values inside `Some`. - * - * ## Examples - * - * ```gleam - * assert values([Some(1), None, Some(3)]) == [1, 3] - * ``` - */ -export function values(options) { - return values_loop(options, toList([])); -} diff --git a/ui/javascript/gleam_stdlib/gleam/order.mjs b/ui/javascript/gleam_stdlib/gleam/order.mjs deleted file mode 100644 index 6324f45..0000000 --- a/ui/javascript/gleam_stdlib/gleam/order.mjs +++ /dev/null @@ -1,175 +0,0 @@ -import { CustomType as $CustomType, isEqual } from "../gleam.mjs"; - -/** - * Less-than - */ -export class Lt extends $CustomType {} -export const Order$Lt = () => new Lt(); -export const Order$isLt = (value) => value instanceof Lt; - -/** - * Equal - */ -export class Eq extends $CustomType {} -export const Order$Eq = () => new Eq(); -export const Order$isEq = (value) => value instanceof Eq; - -/** - * Greater than - */ -export class Gt extends $CustomType {} -export const Order$Gt = () => new Gt(); -export const Order$isGt = (value) => value instanceof Gt; - -/** - * Inverts an order, so less-than becomes greater-than and greater-than - * becomes less-than. - * - * ## Examples - * - * ```gleam - * assert negate(Lt) == Gt - * ``` - * - * ```gleam - * assert negate(Eq) == Eq - * ``` - * - * ```gleam - * assert negate(Gt) == Lt - * ``` - */ -export function negate(order) { - if (order instanceof Lt) { - return new Gt(); - } else if (order instanceof Eq) { - return order; - } else { - return new Lt(); - } -} - -/** - * Produces a numeric representation of the order. - * - * ## Examples - * - * ```gleam - * assert to_int(Lt) == -1 - * ``` - * - * ```gleam - * assert to_int(Eq) == 0 - * ``` - * - * ```gleam - * assert to_int(Gt) == 1 - * ``` - */ -export function to_int(order) { - if (order instanceof Lt) { - return -1; - } else if (order instanceof Eq) { - return 0; - } else { - return 1; - } -} - -/** - * Compares two `Order` values to one another, producing a new `Order`. - * - * ## Examples - * - * ```gleam - * assert compare(Eq, with: Lt) == Gt - * ``` - */ -export function compare(a, b) { - let x = a; - let y = b; - if (isEqual(x, y)) { - return new Eq(); - } else if (a instanceof Lt) { - return new Lt(); - } else if (a instanceof Eq && b instanceof Gt) { - return new Lt(); - } else { - return new Gt(); - } -} - -/** - * Inverts an ordering function, so less-than becomes greater-than and greater-than - * becomes less-than. - * - * ## Examples - * - * ```gleam - * import gleam/int - * import gleam/list - * - * assert list.sort([1, 5, 4], by: reverse(int.compare)) == [5, 4, 1] - * ``` - */ -export function reverse(orderer) { - return (a, b) => { return orderer(b, a); }; -} - -/** - * Return a fallback `Order` in case the first argument is `Eq`. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * assert break_tie(in: int.compare(1, 1), with: Lt) == Lt - * ``` - * - * ```gleam - * import gleam/int - * - * assert break_tie(in: int.compare(1, 0), with: Eq) == Gt - * ``` - */ -export function break_tie(order, other) { - if (order instanceof Lt) { - return order; - } else if (order instanceof Eq) { - return other; - } else { - return order; - } -} - -/** - * Invokes a fallback function returning an `Order` in case the first argument - * is `Eq`. - * - * This can be useful when the fallback comparison might be expensive and it - * needs to be delayed until strictly necessary. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * assert lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt }) == Lt - * ``` - * - * ```gleam - * import gleam/int - * - * assert lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq }) == Gt - * ``` - */ -export function lazy_break_tie(order, comparison) { - if (order instanceof Lt) { - return order; - } else if (order instanceof Eq) { - return comparison(); - } else { - return order; - } -} diff --git a/ui/javascript/gleam_stdlib/gleam/pair.mjs b/ui/javascript/gleam_stdlib/gleam/pair.mjs deleted file mode 100644 index 0964079..0000000 --- a/ui/javascript/gleam_stdlib/gleam/pair.mjs +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Returns the first element in a pair. - * - * ## Examples - * - * ```gleam - * assert first(#(1, 2)) == 1 - * ``` - */ -export function first(pair) { - let a = pair[0]; - return a; -} - -/** - * Returns the second element in a pair. - * - * ## Examples - * - * ```gleam - * assert second(#(1, 2)) == 2 - * ``` - */ -export function second(pair) { - let a = pair[1]; - return a; -} - -/** - * Returns a new pair with the elements swapped. - * - * ## Examples - * - * ```gleam - * assert swap(#(1, 2)) == #(2, 1) - * ``` - */ -export function swap(pair) { - let a = pair[0]; - let b = pair[1]; - return [b, a]; -} - -/** - * Returns a new pair with the first element having had `with` applied to - * it. - * - * ## Examples - * - * ```gleam - * assert #(1, 2) |> map_first(fn(n) { n * 2 }) == #(2, 2) - * ``` - */ -export function map_first(pair, fun) { - let a = pair[0]; - let b = pair[1]; - return [fun(a), b]; -} - -/** - * Returns a new pair with the second element having had `with` applied to - * it. - * - * ## Examples - * - * ```gleam - * assert #(1, 2) |> map_second(fn(n) { n * 2 }) == #(1, 4) - * ``` - */ -export function map_second(pair, fun) { - let a = pair[0]; - let b = pair[1]; - return [a, fun(b)]; -} - -/** - * Returns a new pair with the given elements. This can also be done using the dedicated - * syntax instead: `new(1, 2) == #(1, 2)`. - * - * ## Examples - * - * ```gleam - * assert new(1, 2) == #(1, 2) - * ``` - */ -export function new$(first, second) { - return [first, second]; -} diff --git a/ui/javascript/gleam_stdlib/gleam/result.mjs b/ui/javascript/gleam_stdlib/gleam/result.mjs deleted file mode 100644 index 21085d9..0000000 --- a/ui/javascript/gleam_stdlib/gleam/result.mjs +++ /dev/null @@ -1,448 +0,0 @@ -import { Ok, Error, toList, Empty as $Empty, prepend as listPrepend } from "../gleam.mjs"; -import * as $list from "../gleam/list.mjs"; - -/** - * Checks whether the result is an `Ok` value. - * - * ## Examples - * - * ```gleam - * assert is_ok(Ok(1)) - * ``` - * - * ```gleam - * assert !is_ok(Error(Nil)) - * ``` - */ -export function is_ok(result) { - if (result instanceof Ok) { - return true; - } else { - return false; - } -} - -/** - * Checks whether the result is an `Error` value. - * - * ## Examples - * - * ```gleam - * assert !is_error(Ok(1)) - * ``` - * - * ```gleam - * assert is_error(Error(Nil)) - * ``` - */ -export function is_error(result) { - if (result instanceof Ok) { - return false; - } else { - return true; - } -} - -/** - * Updates a value held within the `Ok` of a result by calling a given function - * on it. - * - * If the result is an `Error` rather than `Ok` the function is not called and the - * result stays the same. - * - * ## Examples - * - * ```gleam - * assert map(over: Ok(1), with: fn(x) { x + 1 }) == Ok(2) - * ``` - * - * ```gleam - * assert map(over: Error(1), with: fn(x) { x + 1 }) == Error(1) - * ``` - */ -export function map(result, fun) { - if (result instanceof Ok) { - let x = result[0]; - return new Ok(fun(x)); - } else { - return result; - } -} - -/** - * Updates a value held within the `Error` of a result by calling a given function - * on it. - * - * If the result is `Ok` rather than `Error` the function is not called and the - * result stays the same. - * - * ## Examples - * - * ```gleam - * assert map_error(over: Error(1), with: fn(x) { x + 1 }) == Error(2) - * ``` - * - * ```gleam - * assert map_error(over: Ok(1), with: fn(x) { x + 1 }) == Ok(1) - * ``` - */ -export function map_error(result, fun) { - if (result instanceof Ok) { - return result; - } else { - let error = result[0]; - return new Error(fun(error)); - } -} - -/** - * Merges a nested `Result` into a single layer. - * - * ## Examples - * - * ```gleam - * assert flatten(Ok(Ok(1))) == Ok(1) - * ``` - * - * ```gleam - * assert flatten(Ok(Error(""))) == Error("") - * ``` - * - * ```gleam - * assert flatten(Error(Nil)) == Error(Nil) - * ``` - */ -export function flatten(result) { - if (result instanceof Ok) { - let x = result[0]; - return x; - } else { - return result; - } -} - -/** - * "Updates" an `Ok` result by passing its value to a function that yields a result, - * and returning the yielded result. (This may "replace" the `Ok` with an `Error`.) - * - * If the input is an `Error` rather than an `Ok`, the function is not called and - * the original `Error` is returned. - * - * This function is the equivalent of calling `map` followed by `flatten`, and - * it is useful for chaining together multiple functions that may fail. - * - * ## Examples - * - * ```gleam - * assert try(Ok(1), fn(x) { Ok(x + 1) }) == Ok(2) - * ``` - * - * ```gleam - * assert try(Ok(1), fn(x) { Ok(#("a", x)) }) == Ok(#("a", 1)) - * ``` - * - * ```gleam - * assert try(Ok(1), fn(_) { Error("Oh no") }) == Error("Oh no") - * ``` - * - * ```gleam - * assert try(Error(Nil), fn(x) { Ok(x + 1) }) == Error(Nil) - * ``` - */ -export function try$(result, fun) { - if (result instanceof Ok) { - let x = result[0]; - return fun(x); - } else { - return result; - } -} - -/** - * Extracts the `Ok` value from a result, returning a default value if the result - * is an `Error`. - * - * ## Examples - * - * ```gleam - * assert unwrap(Ok(1), 0) == 1 - * ``` - * - * ```gleam - * assert unwrap(Error(""), 0) == 0 - * ``` - */ -export function unwrap(result, default$) { - if (result instanceof Ok) { - let v = result[0]; - return v; - } else { - return default$; - } -} - -/** - * Extracts the `Ok` value from a result, evaluating the default function if the result - * is an `Error`. - * - * ## Examples - * - * ```gleam - * assert lazy_unwrap(Ok(1), fn() { 0 }) == 1 - * ``` - * - * ```gleam - * assert lazy_unwrap(Error(""), fn() { 0 }) == 0 - * ``` - */ -export function lazy_unwrap(result, default$) { - if (result instanceof Ok) { - let v = result[0]; - return v; - } else { - return default$(); - } -} - -/** - * Extracts the `Error` value from a result, returning a default value if the result - * is an `Ok`. - * - * ## Examples - * - * ```gleam - * assert unwrap_error(Error(1), 0) == 1 - * ``` - * - * ```gleam - * assert unwrap_error(Ok(""), 0) == 0 - * ``` - */ -export function unwrap_error(result, default$) { - if (result instanceof Ok) { - return default$; - } else { - let e = result[0]; - return e; - } -} - -/** - * Returns the first value if it is `Ok`, otherwise returns the second value. - * - * ## Examples - * - * ```gleam - * assert or(Ok(1), Ok(2)) == Ok(1) - * ``` - * - * ```gleam - * assert or(Ok(1), Error("Error 2")) == Ok(1) - * ``` - * - * ```gleam - * assert or(Error("Error 1"), Ok(2)) == Ok(2) - * ``` - * - * ```gleam - * assert or(Error("Error 1"), Error("Error 2")) == Error("Error 2") - * ``` - */ -export function or(first, second) { - if (first instanceof Ok) { - return first; - } else { - return second; - } -} - -/** - * Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value. - * - * If you need access to the initial error value, use `result.try_recover`. - * - * ## Examples - * - * ```gleam - * assert lazy_or(Ok(1), fn() { Ok(2) }) == Ok(1) - * ``` - * - * ```gleam - * assert lazy_or(Ok(1), fn() { Error("Error 2") }) == Ok(1) - * ``` - * - * ```gleam - * assert lazy_or(Error("Error 1"), fn() { Ok(2) }) == Ok(2) - * ``` - * - * ```gleam - * assert lazy_or(Error("Error 1"), fn() { Error("Error 2") }) - * == Error("Error 2") - * ``` - */ -export function lazy_or(first, second) { - if (first instanceof Ok) { - return first; - } else { - return second(); - } -} - -/** - * Combines a list of results into a single result. - * If all elements in the list are `Ok` then returns an `Ok` holding the list of values. - * If any element is `Error` then returns the first error. - * - * ## Examples - * - * ```gleam - * assert all([Ok(1), Ok(2)]) == Ok([1, 2]) - * ``` - * - * ```gleam - * assert all([Ok(1), Error("e")]) == Error("e") - * ``` - */ -export function all(results) { - return $list.try_map(results, (result) => { return result; }); -} - -function partition_loop(loop$results, loop$oks, loop$errors) { - while (true) { - let results = loop$results; - let oks = loop$oks; - let errors = loop$errors; - if (results instanceof $Empty) { - return [oks, errors]; - } else { - let $ = results.head; - if ($ instanceof Ok) { - let rest = results.tail; - let a = $[0]; - loop$results = rest; - loop$oks = listPrepend(a, oks); - loop$errors = errors; - } else { - let rest = results.tail; - let e = $[0]; - loop$results = rest; - loop$oks = oks; - loop$errors = listPrepend(e, errors); - } - } - } -} - -/** - * Given a list of results, returns a pair where the first element is a list - * of all the values inside `Ok` and the second element is a list with all the - * values inside `Error`. The values in both lists appear in reverse order with - * respect to their position in the original list of results. - * - * ## Examples - * - * ```gleam - * assert partition([Ok(1), Error("a"), Error("b"), Ok(2)]) - * == #([2, 1], ["b", "a"]) - * ``` - */ -export function partition(results) { - return partition_loop(results, toList([]), toList([])); -} - -/** - * Replace the value within a result - * - * ## Examples - * - * ```gleam - * assert replace(Ok(1), Nil) == Ok(Nil) - * ``` - * - * ```gleam - * assert replace(Error(1), Nil) == Error(1) - * ``` - */ -export function replace(result, value) { - if (result instanceof Ok) { - return new Ok(value); - } else { - return result; - } -} - -/** - * Replace the error within a result - * - * ## Examples - * - * ```gleam - * assert replace_error(Error(1), Nil) == Error(Nil) - * ``` - * - * ```gleam - * assert replace_error(Ok(1), Nil) == Ok(1) - * ``` - */ -export function replace_error(result, error) { - if (result instanceof Ok) { - return result; - } else { - return new Error(error); - } -} - -/** - * Given a list of results, returns only the values inside `Ok`. - * - * ## Examples - * - * ```gleam - * assert values([Ok(1), Error("a"), Ok(3)]) == [1, 3] - * ``` - */ -export function values(results) { - return $list.filter_map(results, (result) => { return result; }); -} - -/** - * Updates a value held within the `Error` of a result by calling a given function - * on it, where the given function also returns a result. The two results are - * then merged together into one result. - * - * If the result is an `Ok` rather than `Error` the function is not called and the - * result stays the same. - * - * This function is useful for chaining together computations that may fail - * and trying to recover from possible errors. - * - * If you do not need access to the initial error value, use `result.lazy_or`. - * - * ## Examples - * - * ```gleam - * assert Ok(1) - * |> try_recover(with: fn(_) { Error("failed to recover") }) - * == Ok(1) - * ``` - * - * ```gleam - * assert Error(1) - * |> try_recover(with: fn(error) { Ok(error + 1) }) - * == Ok(2) - * ``` - * - * ```gleam - * assert Error(1) - * |> try_recover(with: fn(error) { Error("failed to recover") }) - * == Error("failed to recover") - * ``` - */ -export function try_recover(result, fun) { - if (result instanceof Ok) { - return result; - } else { - let error = result[0]; - return fun(error); - } -} diff --git a/ui/javascript/gleam_stdlib/gleam/set.mjs b/ui/javascript/gleam_stdlib/gleam/set.mjs deleted file mode 100644 index 6bec848..0000000 --- a/ui/javascript/gleam_stdlib/gleam/set.mjs +++ /dev/null @@ -1,409 +0,0 @@ -import { CustomType as $CustomType, isEqual } from "../gleam.mjs"; -import * as $dict from "../gleam/dict.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $result from "../gleam/result.mjs"; - -class Set extends $CustomType { - constructor(dict) { - super(); - this.dict = dict; - } -} - -const token = undefined; - -/** - * Creates a new empty set. - */ -export function new$() { - return new Set($dict.new$()); -} - -/** - * Gets the number of members in a set. - * - * This function runs in constant time. - * - * ## Examples - * - * ```gleam - * assert new() - * |> insert(1) - * |> insert(2) - * |> size - * == 2 - * ``` - */ -export function size(set) { - return $dict.size(set.dict); -} - -/** - * Determines whether or not the set is empty. - * - * ## Examples - * - * ```gleam - * assert new() |> is_empty - * ``` - * - * ```gleam - * assert !{ new() |> insert(1) |> is_empty } - * ``` - */ -export function is_empty(set) { - return isEqual(set, new$()); -} - -/** - * Inserts a member into the set. - * - * This function runs in logarithmic time. - * - * ## Examples - * - * ```gleam - * assert new() - * |> insert(1) - * |> insert(2) - * |> size - * == 2 - * ``` - */ -export function insert(set, member) { - return new Set($dict.insert(set.dict, member, token)); -} - -/** - * Checks whether a set contains a given member. - * - * This function runs in logarithmic time. - * - * ## Examples - * - * ```gleam - * assert new() - * |> insert(2) - * |> contains(2) - * ``` - * - * ```gleam - * assert !{ - * new() - * |> insert(2) - * |> contains(1) - * } - * ``` - */ -export function contains(set, member) { - let _pipe = set.dict; - let _pipe$1 = $dict.get(_pipe, member); - return $result.is_ok(_pipe$1); -} - -/** - * Removes a member from a set. If the set does not contain the member then - * the set is returned unchanged. - * - * This function runs in logarithmic time. - * - * ## Examples - * - * ```gleam - * assert !{ - * new() - * |> insert(2) - * |> delete(2) - * |> contains(2) - * } - * ``` - */ -export function delete$(set, member) { - return new Set($dict.delete$(set.dict, member)); -} - -/** - * Converts the set into a list of the contained members. - * - * The list has no specific ordering, any unintentional ordering may change in - * future versions of Gleam or Erlang. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * assert new() |> insert(2) |> to_list == [2] - * ``` - */ -export function to_list(set) { - return $dict.keys(set.dict); -} - -/** - * Creates a new set of the members in a given list. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * import gleam/int - * import gleam/list - * - * assert [1, 1, 2, 4, 3, 2] - * |> from_list - * |> to_list - * |> list.sort(by: int.compare) - * == [1, 2, 3, 4] - * ``` - */ -export function from_list(members) { - let dict = $list.fold( - members, - $dict.new$(), - (m, k) => { return $dict.insert(m, k, token); }, - ); - return new Set(dict); -} - -/** - * Combines all entries into a single value by calling a given function on each - * one. - * - * Sets are not ordered so the values are not returned in any specific order. - * Do not write code that relies on the order entries are used by this - * function as it may change in later versions of Gleam or Erlang. - * - * ## Examples - * - * ```gleam - * assert from_list([1, 3, 9]) - * |> fold(0, fn(accumulator, member) { accumulator + member }) - * == 13 - * ``` - */ -export function fold(set, initial, reducer) { - return $dict.fold(set.dict, initial, (a, k, _) => { return reducer(a, k); }); -} - -/** - * Creates a new set from an existing set, minus any members that a given - * function returns `False` for. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * import gleam/int - * - * assert from_list([1, 4, 6, 3, 675, 44, 67]) - * |> filter(keeping: int.is_even) - * |> to_list - * == [4, 6, 44] - * ``` - */ -export function filter(set, predicate) { - return new Set($dict.filter(set.dict, (m, _) => { return predicate(m); })); -} - -/** - * Creates a new set from a given set with the result of applying the given - * function to each member. - * - * ## Examples - * - * ```gleam - * assert from_list([1, 2, 3, 4]) - * |> map(with: fn(x) { x * 2 }) - * |> to_list - * == [2, 4, 6, 8] - * ``` - */ -export function map(set, fun) { - return fold( - set, - new$(), - (acc, member) => { return insert(acc, fun(member)); }, - ); -} - -/** - * Creates a new set from a given set with all the same entries except any - * entry found on the given list. - * - * ## Examples - * - * ```gleam - * assert from_list([1, 2, 3, 4]) - * |> drop([1, 3]) - * |> to_list - * == [2, 4] - * ``` - */ -export function drop(set, disallowed) { - return $list.fold(disallowed, set, delete$); -} - -/** - * Creates a new set from a given set, only including any members which are in - * a given list. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * assert from_list([1, 2, 3]) - * |> take([1, 3, 5]) - * |> to_list - * == [1, 3] - * ``` - */ -export function take(set, desired) { - return new Set($dict.take(set.dict, desired)); -} - -function order(first, second) { - let $ = $dict.size(first.dict) > $dict.size(second.dict); - if ($) { - return [first, second]; - } else { - return [second, first]; - } -} - -/** - * Creates a new set that contains all members of both given sets. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * assert union(from_list([1, 2]), from_list([2, 3])) |> to_list - * == [1, 2, 3] - * ``` - */ -export function union(first, second) { - let $ = order(first, second); - let larger = $[0]; - let smaller = $[1]; - return fold(smaller, larger, insert); -} - -/** - * Creates a new set that contains members that are present in both given sets. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * assert intersection(from_list([1, 2]), from_list([2, 3])) |> to_list - * == [2] - * ``` - */ -export function intersection(first, second) { - let $ = order(first, second); - let larger = $[0]; - let smaller = $[1]; - return take(larger, to_list(smaller)); -} - -/** - * Creates a new set that contains members that are present in the first set - * but not the second. - * - * ## Examples - * - * ```gleam - * assert difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list - * == [1] - * ``` - */ -export function difference(first, second) { - return drop(first, to_list(second)); -} - -/** - * Determines if a set is fully contained by another. - * - * ## Examples - * - * ```gleam - * assert is_subset(from_list([1]), from_list([1, 2])) - * ``` - * - * ```gleam - * assert !is_subset(from_list([1, 2, 3]), from_list([3, 4, 5])) - * ``` - */ -export function is_subset(first, second) { - return isEqual(intersection(first, second), first); -} - -/** - * Determines if two sets contain no common members - * - * ## Examples - * - * ```gleam - * assert is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6])) - * ``` - * - * ```gleam - * assert !is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5])) - * ``` - */ -export function is_disjoint(first, second) { - return isEqual(intersection(first, second), new$()); -} - -/** - * Creates a new set that contains members that are present in either set, but - * not both. - * - * ## Examples - * - * ```gleam - * assert symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) - * |> to_list - * == [1, 2, 4] - * ``` - */ -export function symmetric_difference(first, second) { - return difference(union(first, second), intersection(first, second)); -} - -/** - * Calls a function for each member in a set, discarding the return - * value. - * - * Useful for producing a side effect for every item of a set. - * - * The order of elements in the iteration is an implementation detail that - * should not be relied upon. - * - * ## Examples - * - * ```gleam - * let set = from_list(["apple", "banana", "cherry"]) - * - * assert each(set, io.println) == Nil - * // apple - * // banana - * // cherry - * ``` - */ -export function each(set, fun) { - return fold( - set, - undefined, - (nil, member) => { - fun(member); - return nil; - }, - ); -} diff --git a/ui/javascript/gleam_stdlib/gleam/string.mjs b/ui/javascript/gleam_stdlib/gleam/string.mjs deleted file mode 100644 index 434794d..0000000 --- a/ui/javascript/gleam_stdlib/gleam/string.mjs +++ /dev/null @@ -1,699 +0,0 @@ -import { - Ok, - Error, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - remainderInt, - divideInt, -} from "../gleam.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $option from "../gleam/option.mjs"; -import { None, Some } from "../gleam/option.mjs"; -import * as $order from "../gleam/order.mjs"; -import * as $string_tree from "../gleam/string_tree.mjs"; -import { - string_length as length, - lowercase, - uppercase, - less_than, - string_grapheme_slice as grapheme_slice, - string_byte_slice as unsafe_byte_slice, - crop_string as crop, - byte_size, - contains_string as contains, - starts_with, - ends_with, - pop_grapheme, - graphemes as to_graphemes, - split_once, - trim_end, - trim_start, - codepoint as unsafe_int_to_utf_codepoint, - string_to_codepoint_integer_list, - utf_codepoint_list_to_string as from_utf_codepoints, - utf_codepoint_to_int, - inspect as do_inspect, - string_remove_prefix as remove_prefix, - string_remove_suffix as remove_suffix, -} from "../gleam_stdlib.mjs"; - -export { - byte_size, - contains, - crop, - ends_with, - from_utf_codepoints, - length, - lowercase, - pop_grapheme, - remove_prefix, - remove_suffix, - split_once, - starts_with, - to_graphemes, - trim_end, - trim_start, - uppercase, - utf_codepoint_to_int, -}; - -class Leading extends $CustomType {} - -class Trailing extends $CustomType {} - -/** - * Determines if a `String` is empty. - * - * ## Examples - * - * ```gleam - * assert is_empty("") - * ``` - * - * ```gleam - * assert !is_empty("the world") - * ``` - */ -export function is_empty(str) { - return str === ""; -} - -/** - * Reverses a `String`. - * - * This function has to iterate across the whole `String` so it runs in linear - * time. Avoid using this in a loop. - * - * ## Examples - * - * ```gleam - * assert reverse("stressed") == "desserts" - * ``` - */ -export function reverse(string) { - let _pipe = string; - let _pipe$1 = $string_tree.from_string(_pipe); - let _pipe$2 = $string_tree.reverse(_pipe$1); - return $string_tree.to_string(_pipe$2); -} - -/** - * Creates a new `String` by replacing all occurrences of a given substring. - * - * ## Examples - * - * ```gleam - * assert replace("www.example.com", each: ".", with: "-") == "www-example-com" - * ``` - * - * ```gleam - * assert replace("a,b,c,d,e", each: ",", with: "/") == "a/b/c/d/e" - * ``` - */ -export function replace(string, pattern, substitute) { - let _pipe = string; - let _pipe$1 = $string_tree.from_string(_pipe); - let _pipe$2 = $string_tree.replace(_pipe$1, pattern, substitute); - return $string_tree.to_string(_pipe$2); -} - -/** - * Compares two `String`s to see which is "larger" by comparing their graphemes. - * - * This does not compare the size or length of the given `String`s. - * - * ## Examples - * - * ```gleam - * import gleam/order - * - * assert compare("Anthony", "Anthony") == order.Eq - * ``` - * - * ```gleam - * import gleam/order - * - * assert compare("A", "B") == order.Lt - * ``` - */ -export function compare(a, b) { - let $ = a === b; - if ($) { - return new $order.Eq(); - } else { - let $1 = less_than(a, b); - if ($1) { - return new $order.Lt(); - } else { - return new $order.Gt(); - } - } -} - -/** - * Takes a substring given a start grapheme index and a length. Negative indexes - * are taken starting from the *end* of the string. - * - * This function runs in linear time with the size of the index and the - * length. Negative indexes are linear with the size of the input string in - * addition to the other costs. - * - * ## Examples - * - * ```gleam - * assert slice(from: "gleam", at_index: 1, length: 2) == "le" - * ``` - * - * ```gleam - * assert slice(from: "gleam", at_index: 1, length: 10) == "leam" - * ``` - * - * ```gleam - * assert slice(from: "gleam", at_index: 10, length: 3) == "" - * ``` - * - * ```gleam - * assert slice(from: "gleam", at_index: -2, length: 2) == "am" - * ``` - * - * ```gleam - * assert slice(from: "gleam", at_index: -12, length: 2) == "" - * ``` - */ -export function slice(string, idx, len) { - let $ = len <= 0; - if ($) { - return ""; - } else { - let $1 = idx < 0; - if ($1) { - let translated_idx = length(string) + idx; - let $2 = translated_idx < 0; - if ($2) { - return ""; - } else { - return grapheme_slice(string, translated_idx, len); - } - } else { - return grapheme_slice(string, idx, len); - } - } -} - -/** - * Drops *n* graphemes from the start of a `String`. - * - * This function runs in linear time with the number of graphemes to drop. - * - * ## Examples - * - * ```gleam - * assert drop_start(from: "The Lone Gunmen", up_to: 2) == "e Lone Gunmen" - * ``` - */ -export function drop_start(string, num_graphemes) { - let $ = num_graphemes <= 0; - if ($) { - return string; - } else { - let prefix = grapheme_slice(string, 0, num_graphemes); - let prefix_size = byte_size(prefix); - return unsafe_byte_slice( - string, - prefix_size, - byte_size(string) - prefix_size, - ); - } -} - -/** - * Drops *n* graphemes from the end of a `String`. - * - * This function traverses the full string, so it runs in linear time with the - * size of the string. Avoid using this in a loop. - * - * ## Examples - * - * ```gleam - * assert drop_end(from: "Cigarette Smoking Man", up_to: 2) - * == "Cigarette Smoking M" - * ``` - */ -export function drop_end(string, num_graphemes) { - let $ = num_graphemes <= 0; - if ($) { - return string; - } else { - return slice(string, 0, length(string) - num_graphemes); - } -} - -function to_graphemes_loop(loop$string, loop$acc) { - while (true) { - let string = loop$string; - let acc = loop$acc; - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let grapheme = $[0][0]; - let rest = $[0][1]; - loop$string = rest; - loop$acc = listPrepend(grapheme, acc); - } else { - return acc; - } - } -} - -/** - * Creates a list of `String`s by splitting a given string on a given substring. - * - * ## Examples - * - * ```gleam - * assert split("home/gleam/desktop/", on: "/") - * == ["home", "gleam", "desktop", ""] - * ``` - */ -export function split(x, substring) { - if (substring === "") { - return to_graphemes(x); - } else { - let _pipe = x; - let _pipe$1 = $string_tree.from_string(_pipe); - let _pipe$2 = $string_tree.split(_pipe$1, substring); - return $list.map(_pipe$2, $string_tree.to_string); - } -} - -/** - * Creates a new `String` by joining two `String`s together. - * - * This function typically copies both `String`s and runs in linear time, but - * the exact behaviour will depend on how the runtime you are using optimises - * your code. Benchmark and profile your code if you need to understand its - * performance better. - * - * If you are joining together large string and want to avoid copying any data - * you may want to investigate using the [`string_tree`](../gleam/string_tree.html) - * module. - * - * ## Examples - * - * ```gleam - * assert append(to: "butter", suffix: "fly") == "butterfly" - * ``` - */ -export function append(first, second) { - return first + second; -} - -function concat_loop(loop$strings, loop$accumulator) { - while (true) { - let strings = loop$strings; - let accumulator = loop$accumulator; - if (strings instanceof $Empty) { - return accumulator; - } else { - let string = strings.head; - let strings$1 = strings.tail; - loop$strings = strings$1; - loop$accumulator = accumulator + string; - } - } -} - -/** - * Creates a new `String` by joining many `String`s together. - * - * This function copies all the `String`s and runs in linear time. - * - * ## Examples - * - * ```gleam - * assert concat(["never", "the", "less"]) == "nevertheless" - * ``` - */ -export function concat(strings) { - return concat_loop(strings, ""); -} - -function repeat_loop(loop$times, loop$doubling_acc, loop$acc) { - while (true) { - let times = loop$times; - let doubling_acc = loop$doubling_acc; - let acc = loop$acc; - let _block; - let $ = times % 2; - if ($ === 0) { - _block = acc; - } else { - _block = acc + doubling_acc; - } - let acc$1 = _block; - let times$1 = globalThis.Math.trunc(times / 2); - let $1 = times$1 <= 0; - if ($1) { - return acc$1; - } else { - loop$times = times$1; - loop$doubling_acc = doubling_acc + doubling_acc; - loop$acc = acc$1; - } - } -} - -/** - * Creates a new `String` by repeating a `String` a given number of times. - * - * This function runs in loglinear time. - * - * ## Examples - * - * ```gleam - * assert repeat("ha", times: 3) == "hahaha" - * ``` - */ -export function repeat(string, times) { - let $ = times <= 0; - if ($) { - return ""; - } else { - return repeat_loop(times, string, ""); - } -} - -function join_loop(loop$strings, loop$separator, loop$accumulator) { - while (true) { - let strings = loop$strings; - let separator = loop$separator; - let accumulator = loop$accumulator; - if (strings instanceof $Empty) { - return accumulator; - } else { - let string = strings.head; - let strings$1 = strings.tail; - loop$strings = strings$1; - loop$separator = separator; - loop$accumulator = (accumulator + separator) + string; - } - } -} - -/** - * Joins many `String`s together with a given separator. - * - * This function runs in linear time. - * - * ## Examples - * - * ```gleam - * assert join(["home","evan","Desktop"], with: "/") == "home/evan/Desktop" - * ``` - */ -export function join(strings, separator) { - if (strings instanceof $Empty) { - return ""; - } else { - let first$1 = strings.head; - let rest = strings.tail; - return join_loop(rest, separator, first$1); - } -} - -function padding(size, pad_string) { - let pad_string_length = length(pad_string); - let num_pads = divideInt(size, pad_string_length); - let extra = remainderInt(size, pad_string_length); - return repeat(pad_string, num_pads) + slice(pad_string, 0, extra); -} - -/** - * Pads the start of a `String` until it has a given length. - * - * ## Examples - * - * ```gleam - * assert pad_start("121", to: 5, with: ".") == "..121" - * ``` - * - * ```gleam - * assert pad_start("121", to: 3, with: ".") == "121" - * ``` - * - * ```gleam - * assert pad_start("121", to: 2, with: ".") == "121" - * ``` - */ -export function pad_start(string, desired_length, pad_string) { - let current_length = length(string); - let to_pad_length = desired_length - current_length; - let $ = to_pad_length <= 0; - if ($) { - return string; - } else { - return padding(to_pad_length, pad_string) + string; - } -} - -/** - * Pads the end of a `String` until it has a given length. - * - * ## Examples - * - * ```gleam - * assert pad_end("123", to: 5, with: ".") == "123.." - * ``` - * - * ```gleam - * assert pad_end("123", to: 3, with: ".") == "123" - * ``` - * - * ```gleam - * assert pad_end("123", to: 2, with: ".") == "123" - * ``` - */ -export function pad_end(string, desired_length, pad_string) { - let current_length = length(string); - let to_pad_length = desired_length - current_length; - let $ = to_pad_length <= 0; - if ($) { - return string; - } else { - return string + padding(to_pad_length, pad_string); - } -} - -/** - * Removes whitespace on both sides of a `String`. - * - * Whitespace in this function is the set of nonbreakable whitespace - * codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1]. - * - * [1]: https://unicode.org/reports/tr31/ - * - * ## Examples - * - * ```gleam - * assert trim(" hats \n") == "hats" - * ``` - */ -export function trim(string) { - let _pipe = string; - let _pipe$1 = trim_start(_pipe); - return trim_end(_pipe$1); -} - -function do_to_utf_codepoints(string) { - let _pipe = string; - let _pipe$1 = string_to_codepoint_integer_list(_pipe); - return $list.map(_pipe$1, unsafe_int_to_utf_codepoint); -} - -/** - * Converts a `String` to a `List` of `UtfCodepoint`. - * - * See and - * for an - * explanation on code points. - * - * ## Examples - * - * ```gleam - * assert "a" |> to_utf_codepoints == [UtfCodepoint(97)] - * ``` - * - * ```gleam - * // Semantically the same as: - * // ["🏳", "️", "‍", "🌈"] or: - * // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow] - * assert "🏳️‍🌈" |> to_utf_codepoints - * == [ - * UtfCodepoint(127987), - * UtfCodepoint(65039), - * UtfCodepoint(8205), - * UtfCodepoint(127752), - * ] - * ``` - */ -export function to_utf_codepoints(string) { - return do_to_utf_codepoints(string); -} - -/** - * Converts an integer to a `UtfCodepoint`. - * - * Returns an `Error` if the integer does not represent a valid UTF codepoint. - */ -export function utf_codepoint(value) { - let i = value; - if (i > 1_114_111) { - return new Error(undefined); - } else { - let i = value; - if ((i >= 55_296) && (i <= 57_343)) { - return new Error(undefined); - } else { - let i = value; - if (i < 0) { - return new Error(undefined); - } else { - let i = value; - return new Ok(unsafe_int_to_utf_codepoint(i)); - } - } - } -} - -/** - * Converts a `String` into `Option(String)` where an empty `String` becomes - * `None`. - * - * ## Examples - * - * ```gleam - * assert to_option("") == None - * ``` - * - * ```gleam - * assert to_option("hats") == Some("hats") - * ``` - */ -export function to_option(string) { - if (string === "") { - return new None(); - } else { - return new Some(string); - } -} - -/** - * Returns the first grapheme cluster in a given `String` and wraps it in a - * `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. - * Otherwise, it returns `Ok(String)`. - * - * ## Examples - * - * ```gleam - * assert first("") == Error(Nil) - * ``` - * - * ```gleam - * assert first("icecream") == Ok("i") - * ``` - */ -export function first(string) { - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let first$1 = $[0][0]; - return new Ok(first$1); - } else { - return $; - } -} - -/** - * Returns the last grapheme cluster in a given `String` and wraps it in a - * `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. - * Otherwise, it returns `Ok(String)`. - * - * This function traverses the full string, so it runs in linear time with the - * length of the string. Avoid using this in a loop. - * - * ## Examples - * - * ```gleam - * assert last("") == Error(Nil) - * ``` - * - * ```gleam - * assert last("icecream") == Ok("m") - * ``` - */ -export function last(string) { - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let $1 = $[0][1]; - if ($1 === "") { - let first$1 = $[0][0]; - return new Ok(first$1); - } else { - let rest = $1; - return new Ok(slice(rest, -1, 1)); - } - } else { - return $; - } -} - -/** - * Creates a new `String` with the first grapheme in the input `String` - * converted to uppercase and the remaining graphemes to lowercase. - * - * ## Examples - * - * ```gleam - * assert capitalise("mamouna") == "Mamouna" - * ``` - */ -export function capitalise(string) { - let $ = pop_grapheme(string); - if ($ instanceof Ok) { - let first$1 = $[0][0]; - let rest = $[0][1]; - return append(uppercase(first$1), lowercase(rest)); - } else { - return ""; - } -} - -/** - * Returns a `String` representation of a term in Gleam syntax. - * - * This may be occasionally useful for quick-and-dirty printing of values in - * scripts. For error reporting and other uses prefer constructing strings by - * pattern matching on the values. - * - * ## Limitations - * - * The output format of this function is not stable and could change at any - * time. The output is not suitable for parsing. - * - * This function works using runtime reflection, so the output may not be - * perfectly accurate for data structures where the runtime structure doesn't - * hold enough information to determine the original syntax. For example, - * tuples with an Erlang atom in the first position will be mistaken for Gleam - * records. - * - * ## Security and safety - * - * There is no limit to how large the strings that this function can produce. - * Be careful not to call this function with large data structures or you - * could use very large amounts of memory, potentially causing runtime - * problems. - */ -export function inspect(term) { - let _pipe = term; - let _pipe$1 = do_inspect(_pipe); - return $string_tree.to_string(_pipe$1); -} diff --git a/ui/javascript/gleam_stdlib/gleam/string_tree.mjs b/ui/javascript/gleam_stdlib/gleam/string_tree.mjs deleted file mode 100644 index f9d78f4..0000000 --- a/ui/javascript/gleam_stdlib/gleam/string_tree.mjs +++ /dev/null @@ -1,128 +0,0 @@ -import { toList, CustomType as $CustomType, isEqual } from "../gleam.mjs"; -import * as $list from "../gleam/list.mjs"; -import { - concat as from_strings, - identity as from_string, - add as append_tree, - concat, - identity as to_string, - length as byte_size, - lowercase, - uppercase, - graphemes as do_to_graphemes, - split, - string_replace as replace, -} from "../gleam_stdlib.mjs"; - -export { - append_tree, - byte_size, - concat, - from_string, - from_strings, - lowercase, - replace, - split, - to_string, - uppercase, -}; - -class All extends $CustomType {} - -/** - * Create an empty `StringTree`. Useful as the start of a pipe chaining many - * trees together. - */ -export function new$() { - return from_strings(toList([])); -} - -/** - * Prepends a `String` onto the start of some `StringTree`. - * - * Runs in constant time. - */ -export function prepend(tree, prefix) { - return append_tree(from_string(prefix), tree); -} - -/** - * Appends a `String` onto the end of some `StringTree`. - * - * Runs in constant time. - */ -export function append(tree, second) { - return append_tree(tree, from_string(second)); -} - -/** - * Prepends some `StringTree` onto the start of another. - * - * Runs in constant time. - */ -export function prepend_tree(tree, prefix) { - return append_tree(prefix, tree); -} - -/** - * Joins the given trees into a new tree separated with the given string. - */ -export function join(trees, sep) { - let _pipe = trees; - let _pipe$1 = $list.intersperse(_pipe, from_string(sep)); - return concat(_pipe$1); -} - -/** - * Converts a `StringTree` to a new one with the contents reversed. - */ -export function reverse(tree) { - let _pipe = tree; - let _pipe$1 = to_string(_pipe); - let _pipe$2 = do_to_graphemes(_pipe$1); - let _pipe$3 = $list.reverse(_pipe$2); - return from_strings(_pipe$3); -} - -/** - * Compares two string trees to determine if they have the same textual - * content. - * - * Comparing two string trees using the `==` operator may return `False` even - * if they have the same content as they may have been built in different ways, - * so using this function is often preferred. - * - * ## Examples - * - * ```gleam - * assert from_strings(["a", "b"]) != from_string("ab") - * ``` - * - * ```gleam - * assert is_equal(from_strings(["a", "b"]), from_string("ab")) - * ``` - */ -export function is_equal(a, b) { - return isEqual(a, b); -} - -/** - * Inspects a `StringTree` to determine if it is equivalent to an empty string. - * - * ## Examples - * - * ```gleam - * assert !{ from_string("ok") |> is_empty } - * ``` - * - * ```gleam - * assert from_string("") |> is_empty - * ``` - * - * ```gleam - * assert from_strings([]) |> is_empty - * ``` - */ -export function is_empty(tree) { - return isEqual(from_string(""), tree); -} diff --git a/ui/javascript/gleam_stdlib/gleam/uri.mjs b/ui/javascript/gleam_stdlib/gleam/uri.mjs deleted file mode 100644 index 1b1e18f..0000000 --- a/ui/javascript/gleam_stdlib/gleam/uri.mjs +++ /dev/null @@ -1,1147 +0,0 @@ -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - isEqual, -} from "../gleam.mjs"; -import * as $int from "../gleam/int.mjs"; -import * as $list from "../gleam/list.mjs"; -import * as $option from "../gleam/option.mjs"; -import { None, Some } from "../gleam/option.mjs"; -import * as $string from "../gleam/string.mjs"; -import * as $string_tree from "../gleam/string_tree.mjs"; -import { - pop_codeunit, - string_codeunit_slice as codeunit_slice, - parse_query, - percent_encode, - percent_decode, -} from "../gleam_stdlib.mjs"; - -export { parse_query, percent_decode, percent_encode }; - -export class Uri extends $CustomType { - constructor(scheme, userinfo, host, port, path, query, fragment) { - super(); - this.scheme = scheme; - this.userinfo = userinfo; - this.host = host; - this.port = port; - this.path = path; - this.query = query; - this.fragment = fragment; - } -} -export const Uri$Uri = (scheme, userinfo, host, port, path, query, fragment) => - new Uri(scheme, userinfo, host, port, path, query, fragment); -export const Uri$isUri = (value) => value instanceof Uri; -export const Uri$Uri$scheme = (value) => value.scheme; -export const Uri$Uri$0 = (value) => value.scheme; -export const Uri$Uri$userinfo = (value) => value.userinfo; -export const Uri$Uri$1 = (value) => value.userinfo; -export const Uri$Uri$host = (value) => value.host; -export const Uri$Uri$2 = (value) => value.host; -export const Uri$Uri$port = (value) => value.port; -export const Uri$Uri$3 = (value) => value.port; -export const Uri$Uri$path = (value) => value.path; -export const Uri$Uri$4 = (value) => value.path; -export const Uri$Uri$query = (value) => value.query; -export const Uri$Uri$5 = (value) => value.query; -export const Uri$Uri$fragment = (value) => value.fragment; -export const Uri$Uri$6 = (value) => value.fragment; - -/** - * Constant representing an empty URI, equivalent to "". - * - * ## Examples - * - * ```gleam - * assert Uri(..empty, scheme: Some("https"), host: Some("example.com")) - * == Uri( - * scheme: Some("https"), - * userinfo: None, - * host: Some("example.com"), - * port: None, - * path: "", - * query: None, - * fragment: None, - * ) - * ``` - */ -export const empty = /* @__PURE__ */ new Uri( - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), - "", - /* @__PURE__ */ new None(), - /* @__PURE__ */ new None(), -); - -function parse_fragment(rest, pieces) { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - new Some(rest), - ), - ); -} - -function parse_query_with_question_mark_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - if (uri_string.charCodeAt(0) === 35) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else { - let rest = uri_string.slice(1); - let query = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - new Some(query), - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - new Some(original), - pieces.fragment, - ), - ); - } else { - let $ = pop_codeunit(uri_string); - let rest = $[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_query_with_question_mark(uri_string, pieces) { - return parse_query_with_question_mark_loop(uri_string, uri_string, pieces, 0); -} - -function parse_path_loop(loop$original, loop$uri_string, loop$pieces, loop$size) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - let $ = uri_string.charCodeAt(0); - if ($ === 63) { - let rest = uri_string.slice(1); - let path = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } else if ($ === 35) { - let rest = uri_string.slice(1); - let path = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - original, - pieces.query, - pieces.fragment, - ), - ); - } else { - let $1 = pop_codeunit(uri_string); - let rest = $1[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_path(uri_string, pieces) { - return parse_path_loop(uri_string, uri_string, pieces, 0); -} - -function parse_port_loop(loop$uri_string, loop$pieces, loop$port) { - while (true) { - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let port = loop$port; - let $ = uri_string.charCodeAt(0); - if ($ === 48) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10; - } else if ($ === 49) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 1; - } else if ($ === 50) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 2; - } else if ($ === 51) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 3; - } else if ($ === 52) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 4; - } else if ($ === 53) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 5; - } else if ($ === 54) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 6; - } else if ($ === 55) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 7; - } else if ($ === 56) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 8; - } else if ($ === 57) { - let rest = uri_string.slice(1); - loop$uri_string = rest; - loop$pieces = pieces; - loop$port = port * 10 + 9; - } else if ($ === 63) { - let rest = uri_string.slice(1); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } else if ($ === 35) { - let rest = uri_string.slice(1); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } else if ($ === 47) { - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_path(uri_string, pieces$1); - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - new Some(port), - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else { - return new Error(undefined); - } - } -} - -function parse_port(uri_string, pieces) { - let $ = uri_string.charCodeAt(0); - if (uri_string.startsWith(":0")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 0); - } else if (uri_string.startsWith(":1")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 1); - } else if (uri_string.startsWith(":2")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 2); - } else if (uri_string.startsWith(":3")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 3); - } else if (uri_string.startsWith(":4")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 4); - } else if (uri_string.startsWith(":5")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 5); - } else if (uri_string.startsWith(":6")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 6); - } else if (uri_string.startsWith(":7")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 7); - } else if (uri_string.startsWith(":8")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 8); - } else if (uri_string.startsWith(":9")) { - let rest = uri_string.slice(2); - return parse_port_loop(rest, pieces, 9); - } else if (uri_string === ":") { - return new Ok(pieces); - } else if (uri_string === "") { - return new Ok(pieces); - } else if ($ === 63) { - let rest = uri_string.slice(1); - return parse_query_with_question_mark(rest, pieces); - } else if (uri_string.startsWith(":?")) { - let rest = uri_string.slice(2); - return parse_query_with_question_mark(rest, pieces); - } else if ($ === 35) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else if (uri_string.startsWith(":#")) { - let rest = uri_string.slice(2); - return parse_fragment(rest, pieces); - } else if ($ === 47) { - return parse_path(uri_string, pieces); - } else if ($ === 58) { - let rest = uri_string.slice(1); - if (rest.charCodeAt(0) === 47) { - return parse_path(rest, pieces); - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} - -function parse_host_outside_of_brackets_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - let $ = uri_string.charCodeAt(0); - if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(original), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else if ($ === 58) { - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_port(uri_string, pieces$1); - } else if ($ === 47) { - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_path(uri_string, pieces$1); - } else if ($ === 63) { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } else if ($ === 35) { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } else { - let $1 = pop_codeunit(uri_string); - let rest = $1[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_host_outside_of_brackets(uri_string, pieces) { - return parse_host_outside_of_brackets_loop(uri_string, uri_string, pieces, 0); -} - -function is_valid_host_within_brackets_char(char) { - return (((((48 >= char) && (char <= 57)) || ((65 >= char) && (char <= 90))) || ((97 >= char) && (char <= 122))) || (char === 58)) || (char === 46); -} - -function parse_host_within_brackets_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - let $ = uri_string.charCodeAt(0); - if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(uri_string), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else if ($ === 93) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_port(rest, pieces); - } else { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size + 1); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_port(rest, pieces$1); - } - } else if ($ === 47) { - if (size === 0) { - return parse_path(uri_string, pieces); - } else { - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_path(uri_string, pieces$1); - } - } else if ($ === 63) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_query_with_question_mark(rest, pieces); - } else { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } - } else if ($ === 35) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else { - let rest = uri_string.slice(1); - let host = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(host), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } - } else { - let $1 = pop_codeunit(uri_string); - let char = $1[0]; - let rest = $1[1]; - let $2 = is_valid_host_within_brackets_char(char); - if ($2) { - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } else { - return parse_host_outside_of_brackets_loop( - original, - original, - pieces, - 0, - ); - } - } - } -} - -function parse_host_within_brackets(uri_string, pieces) { - return parse_host_within_brackets_loop(uri_string, uri_string, pieces, 0); -} - -function parse_host(uri_string, pieces) { - let $ = uri_string.charCodeAt(0); - if ($ === 91) { - return parse_host_within_brackets(uri_string, pieces); - } else if ($ === 58) { - let pieces$1 = new Uri( - pieces.scheme, - pieces.userinfo, - new Some(""), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_port(uri_string, pieces$1); - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(""), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else { - return parse_host_outside_of_brackets(uri_string, pieces); - } -} - -function parse_userinfo_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - let $ = uri_string.charCodeAt(0); - if ($ === 64) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_host(rest, pieces); - } else { - let rest = uri_string.slice(1); - let userinfo = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - pieces.scheme, - new Some(userinfo), - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_host(rest, pieces$1); - } - } else if (uri_string === "") { - return parse_host(original, pieces); - } else if ($ === 47) { - return parse_host(original, pieces); - } else if ($ === 63) { - return parse_host(original, pieces); - } else if ($ === 35) { - return parse_host(original, pieces); - } else { - let $1 = pop_codeunit(uri_string); - let rest = $1[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -function parse_authority_pieces(string, pieces) { - return parse_userinfo_loop(string, string, pieces, 0); -} - -function parse_authority_with_slashes(uri_string, pieces) { - if (uri_string === "//") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - new Some(""), - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ), - ); - } else if (uri_string.startsWith("//")) { - let rest = uri_string.slice(2); - return parse_authority_pieces(rest, pieces); - } else { - return parse_path(uri_string, pieces); - } -} - -function parse_scheme_loop( - loop$original, - loop$uri_string, - loop$pieces, - loop$size -) { - while (true) { - let original = loop$original; - let uri_string = loop$uri_string; - let pieces = loop$pieces; - let size = loop$size; - let $ = uri_string.charCodeAt(0); - if ($ === 47) { - if (size === 0) { - return parse_authority_with_slashes(uri_string, pieces); - } else { - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_authority_with_slashes(uri_string, pieces$1); - } - } else if ($ === 63) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_query_with_question_mark(rest, pieces); - } else { - let rest = uri_string.slice(1); - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_query_with_question_mark(rest, pieces$1); - } - } else if ($ === 35) { - if (size === 0) { - let rest = uri_string.slice(1); - return parse_fragment(rest, pieces); - } else { - let rest = uri_string.slice(1); - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_fragment(rest, pieces$1); - } - } else if ($ === 58) { - if (size === 0) { - return new Error(undefined); - } else { - let rest = uri_string.slice(1); - let scheme = codeunit_slice(original, 0, size); - let pieces$1 = new Uri( - new Some($string.lowercase(scheme)), - pieces.userinfo, - pieces.host, - pieces.port, - pieces.path, - pieces.query, - pieces.fragment, - ); - return parse_authority_with_slashes(rest, pieces$1); - } - } else if (uri_string === "") { - return new Ok( - new Uri( - pieces.scheme, - pieces.userinfo, - pieces.host, - pieces.port, - original, - pieces.query, - pieces.fragment, - ), - ); - } else { - let $1 = pop_codeunit(uri_string); - let rest = $1[1]; - loop$original = original; - loop$uri_string = rest; - loop$pieces = pieces; - loop$size = size + 1; - } - } -} - -/** - * Parses a compliant URI string into the `Uri` type. - * If the string is not a valid URI string then an error is returned. - * - * The opposite operation is `uri.to_string`. - * - * ## Examples - * - * ```gleam - * assert parse("https://example.com:1234/a/b?query=true#fragment") - * == Ok( - * Uri( - * scheme: Some("https"), - * userinfo: None, - * host: Some("example.com"), - * port: Some(1234), - * path: "/a/b", - * query: Some("query=true"), - * fragment: Some("fragment") - * ) - * ) - * ``` - */ -export function parse(uri_string) { - return parse_scheme_loop(uri_string, uri_string, empty, 0); -} - -function percent_encode_query(part) { - let _pipe = percent_encode(part); - return $string.replace(_pipe, "+", "%2B"); -} - -function query_pair(pair) { - let _pipe = toList([ - percent_encode_query(pair[0]), - "=", - percent_encode_query(pair[1]), - ]); - return $string_tree.from_strings(_pipe); -} - -/** - * Encodes a list of key value pairs as a URI query string. - * - * The opposite operation is `uri.parse_query`. - * - * ## Examples - * - * ```gleam - * assert query_to_string([#("a", "1"), #("b", "2")]) == "a=1&b=2" - * ``` - */ -export function query_to_string(query) { - let _pipe = query; - let _pipe$1 = $list.map(_pipe, query_pair); - let _pipe$2 = $list.intersperse(_pipe$1, $string_tree.from_string("&")); - let _pipe$3 = $string_tree.concat(_pipe$2); - return $string_tree.to_string(_pipe$3); -} - -function remove_dot_segments_loop(loop$input, loop$accumulator) { - while (true) { - let input = loop$input; - let accumulator = loop$accumulator; - if (input instanceof $Empty) { - return $list.reverse(accumulator); - } else { - let segment = input.head; - let rest = input.tail; - let _block; - if (segment === "") { - _block = accumulator; - } else if (segment === ".") { - _block = accumulator; - } else if (segment === "..") { - if (accumulator instanceof $Empty) { - _block = accumulator; - } else { - let accumulator$1 = accumulator.tail; - _block = accumulator$1; - } - } else { - let segment$1 = segment; - let accumulator$1 = accumulator; - _block = listPrepend(segment$1, accumulator$1); - } - let accumulator$1 = _block; - loop$input = rest; - loop$accumulator = accumulator$1; - } - } -} - -function remove_dot_segments(input) { - return remove_dot_segments_loop(input, toList([])); -} - -/** - * Splits the path section of a URI into its constituent segments. - * - * Removes empty segments and resolves dot-segments as specified in - * [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC. - * - * ## Examples - * - * ```gleam - * assert path_segments("/users/1") == ["users" ,"1"] - * ``` - */ -export function path_segments(path) { - return remove_dot_segments($string.split(path, "/")); -} - -/** - * Encodes a `Uri` value as a URI string. - * - * The opposite operation is `uri.parse`. - * - * ## Examples - * - * ```gleam - * let uri = Uri(..empty, scheme: Some("https"), host: Some("example.com")) - * assert to_string(uri) == "https://example.com" - * ``` - */ -export function to_string(uri) { - let _block; - let $ = uri.fragment; - if ($ instanceof Some) { - let fragment = $[0]; - _block = toList(["#", fragment]); - } else { - _block = toList([]); - } - let parts = _block; - let _block$1; - let $1 = uri.query; - if ($1 instanceof Some) { - let query = $1[0]; - _block$1 = listPrepend("?", listPrepend(query, parts)); - } else { - _block$1 = parts; - } - let parts$1 = _block$1; - let parts$2 = listPrepend(uri.path, parts$1); - let _block$2; - let $2 = uri.host; - let $3 = $string.starts_with(uri.path, "/"); - if ($2 instanceof Some && !$3) { - let host = $2[0]; - if (host !== "") { - _block$2 = listPrepend("/", parts$2); - } else { - _block$2 = parts$2; - } - } else { - _block$2 = parts$2; - } - let parts$3 = _block$2; - let _block$3; - let $4 = uri.host; - let $5 = uri.port; - if ($4 instanceof Some && $5 instanceof Some) { - let port = $5[0]; - _block$3 = listPrepend(":", listPrepend($int.to_string(port), parts$3)); - } else { - _block$3 = parts$3; - } - let parts$4 = _block$3; - let _block$4; - let $6 = uri.scheme; - let $7 = uri.userinfo; - let $8 = uri.host; - if ($6 instanceof Some) { - if ($7 instanceof Some) { - if ($8 instanceof Some) { - let s = $6[0]; - let u = $7[0]; - let h = $8[0]; - _block$4 = listPrepend( - s, - listPrepend( - "://", - listPrepend(u, listPrepend("@", listPrepend(h, parts$4))), - ), - ); - } else { - let s = $6[0]; - _block$4 = listPrepend(s, listPrepend(":", parts$4)); - } - } else if ($8 instanceof Some) { - let s = $6[0]; - let h = $8[0]; - _block$4 = listPrepend(s, listPrepend("://", listPrepend(h, parts$4))); - } else { - let s = $6[0]; - _block$4 = listPrepend(s, listPrepend(":", parts$4)); - } - } else if ($7 instanceof None && $8 instanceof Some) { - let h = $8[0]; - _block$4 = listPrepend("//", listPrepend(h, parts$4)); - } else { - _block$4 = parts$4; - } - let parts$5 = _block$4; - return $string.concat(parts$5); -} - -/** - * Fetches the origin of a URI. - * - * Returns the origin of a uri as defined in - * [RFC 6454](https://tools.ietf.org/html/rfc6454) - * - * The supported URI schemes are `http` and `https`. - * URLs without a scheme will return `Error`. - * - * ## Examples - * - * ```gleam - * let assert Ok(uri) = parse("https://example.com/path?foo#bar") - * assert origin(uri) == Ok("https://example.com") - * ``` - */ -export function origin(uri) { - let scheme = uri.scheme; - let host = uri.host; - let port = uri.port; - if (host instanceof Some && scheme instanceof Some) { - let $ = scheme[0]; - if ($ === "https" && isEqual(port, new Some(443))) { - let h = host[0]; - return new Ok($string.concat(toList(["https://", h]))); - } else if ($ === "http" && isEqual(port, new Some(80))) { - let h = host[0]; - return new Ok($string.concat(toList(["http://", h]))); - } else { - let s = $; - if ((s === "http") || (s === "https")) { - let h = host[0]; - if (port instanceof Some) { - let p = port[0]; - return new Ok( - $string.concat(toList([s, "://", h, ":", $int.to_string(p)])), - ); - } else { - return new Ok($string.concat(toList([s, "://", h]))); - } - } else { - return new Error(undefined); - } - } - } else { - return new Error(undefined); - } -} - -function join_segments(segments) { - return $string.join(listPrepend("", segments), "/"); -} - -function drop_last(elements) { - return $list.take(elements, $list.length(elements) - 1); -} - -/** - * Resolves a URI with respect to the given base URI. - * - * The base URI must be an absolute URI or this function will return an error. - * The algorithm for merging URIs is described in - * [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2). - */ -export function merge(base, relative) { - let $ = base.scheme; - if ($ instanceof Some) { - let $1 = base.host; - if ($1 instanceof Some) { - let $2 = relative.host; - if ($2 instanceof Some) { - let _block; - let _pipe = relative.path; - let _pipe$1 = $string.split(_pipe, "/"); - let _pipe$2 = remove_dot_segments(_pipe$1); - _block = join_segments(_pipe$2); - let path = _block; - let resolved = new Uri( - $option.or(relative.scheme, base.scheme), - new None(), - relative.host, - $option.or(relative.port, base.port), - path, - relative.query, - relative.fragment, - ); - return new Ok(resolved); - } else { - let _block; - let $4 = relative.path; - if ($4 === "") { - _block = [base.path, $option.or(relative.query, base.query)]; - } else { - let _block$1; - let $5 = $string.starts_with(relative.path, "/"); - if ($5) { - _block$1 = $string.split(relative.path, "/"); - } else { - let _pipe = base.path; - let _pipe$1 = $string.split(_pipe, "/"); - let _pipe$2 = drop_last(_pipe$1); - _block$1 = $list.append(_pipe$2, $string.split(relative.path, "/")); - } - let path_segments$1 = _block$1; - let _block$2; - let _pipe = path_segments$1; - let _pipe$1 = remove_dot_segments(_pipe); - _block$2 = join_segments(_pipe$1); - let path = _block$2; - _block = [path, relative.query]; - } - let $3 = _block; - let new_path = $3[0]; - let new_query = $3[1]; - let resolved = new Uri( - base.scheme, - new None(), - base.host, - base.port, - new_path, - new_query, - relative.fragment, - ); - return new Ok(resolved); - } - } else { - return new Error(undefined); - } - } else { - return new Error(undefined); - } -} diff --git a/ui/javascript/gleam_stdlib/gleam@bit_array.erl b/ui/javascript/gleam_stdlib/gleam@bit_array.erl deleted file mode 100644 index 8bf7379..0000000 --- a/ui/javascript/gleam_stdlib/gleam@bit_array.erl +++ /dev/null @@ -1,347 +0,0 @@ --module(gleam@bit_array). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bit_array.gleam"). --export([from_string/1, bit_size/1, byte_size/1, pad_to_bytes/1, concat/1, append/2, slice/3, is_utf8/1, to_string/1, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1, inspect/1, compare/2, starts_with/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(" BitArrays are a sequence of binary data of any length.\n"). - --file("src/gleam/bit_array.gleam", 11). -?DOC(" Converts a UTF-8 `String` type into a `BitArray`.\n"). --spec from_string(binary()) -> bitstring(). -from_string(X) -> - gleam_stdlib:identity(X). - --file("src/gleam/bit_array.gleam", 17). -?DOC(" Returns an integer which is the number of bits in the bit array.\n"). --spec bit_size(bitstring()) -> integer(). -bit_size(X) -> - erlang:bit_size(X). - --file("src/gleam/bit_array.gleam", 23). -?DOC(" Returns an integer which is the number of bytes in the bit array.\n"). --spec byte_size(bitstring()) -> integer(). -byte_size(X) -> - erlang:byte_size(X). - --file("src/gleam/bit_array.gleam", 29). -?DOC(" Pads a bit array with zeros so that it is a whole number of bytes.\n"). --spec pad_to_bytes(bitstring()) -> bitstring(). -pad_to_bytes(X) -> - gleam_stdlib:bit_array_pad_to_bytes(X). - --file("src/gleam/bit_array.gleam", 109). -?DOC( - " Creates a new bit array by joining multiple binaries.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert concat([from_string(\"butter\"), from_string(\"fly\")])\n" - " == from_string(\"butterfly\")\n" - " ```\n" -). --spec concat(list(bitstring())) -> bitstring(). -concat(Bit_arrays) -> - gleam_stdlib:bit_array_concat(Bit_arrays). - --file("src/gleam/bit_array.gleam", 40). -?DOC( - " Creates a new bit array by joining two bit arrays.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert append(to: from_string(\"butter\"), suffix: from_string(\"fly\"))\n" - " == from_string(\"butterfly\")\n" - " ```\n" -). --spec append(bitstring(), bitstring()) -> bitstring(). -append(First, Second) -> - gleam_stdlib:bit_array_concat([First, Second]). - --file("src/gleam/bit_array.gleam", 54). -?DOC( - " Extracts a sub-section of a bit array.\n" - "\n" - " The slice will start at given position and continue up to specified\n" - " length.\n" - " A negative length can be used to extract bytes at the end of a bit array.\n" - "\n" - " This function runs in constant time.\n" -). --spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | - {error, nil}. -slice(String, Position, Length) -> - gleam_stdlib:bit_array_slice(String, Position, Length). - --file("src/gleam/bit_array.gleam", 67). --spec is_utf8_loop(bitstring()) -> boolean(). -is_utf8_loop(Bits) -> - case Bits of - <<>> -> - true; - - <<_/utf8, Rest/binary>> -> - is_utf8_loop(Rest); - - _ -> - false - end. - --file("src/gleam/bit_array.gleam", 62). -?DOC(" Tests to see whether a bit array is valid UTF-8.\n"). --spec is_utf8(bitstring()) -> boolean(). -is_utf8(Bits) -> - is_utf8_loop(Bits). - --file("src/gleam/bit_array.gleam", 88). -?DOC( - " Converts a bit array to a string.\n" - "\n" - " Returns an error if the bit array is invalid UTF-8 data.\n" -). --spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. -to_string(Bits) -> - case is_utf8(Bits) of - true -> - {ok, gleam_stdlib:identity(Bits)}; - - false -> - {error, nil} - end. - --file("src/gleam/bit_array.gleam", 118). -?DOC( - " Encodes a BitArray into a base 64 encoded string.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base64_encode(bitstring(), boolean()) -> binary(). -base64_encode(Input, Padding) -> - gleam_stdlib:base64_encode(Input, Padding). - --file("src/gleam/bit_array.gleam", 122). -?DOC(" Decodes a base 64 encoded string into a `BitArray`.\n"). --spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base64_decode(Encoded) -> - Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of - 0 -> - Encoded; - - N -> - gleam@string:append( - Encoded, - gleam@string:repeat(<<"="/utf8>>, 4 - N) - ) - end, - gleam_stdlib:base64_decode(Padded). - --file("src/gleam/bit_array.gleam", 140). -?DOC( - " Encodes a `BitArray` into a base 64 encoded string with URL and filename\n" - " safe alphabet.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base64_url_encode(bitstring(), boolean()) -> binary(). -base64_url_encode(Input, Padding) -> - _pipe = Input, - _pipe@1 = gleam_stdlib:base64_encode(_pipe, Padding), - _pipe@2 = gleam@string:replace(_pipe@1, <<"+"/utf8>>, <<"-"/utf8>>), - gleam@string:replace(_pipe@2, <<"/"/utf8>>, <<"_"/utf8>>). - --file("src/gleam/bit_array.gleam", 150). -?DOC( - " Decodes a base 64 encoded string with URL and filename safe alphabet into a\n" - " `BitArray`.\n" -). --spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base64_url_decode(Encoded) -> - _pipe = Encoded, - _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>), - _pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>), - base64_decode(_pipe@2). - --file("src/gleam/bit_array.gleam", 164). -?DOC( - " Encodes a `BitArray` into a base 16 encoded string.\n" - "\n" - " If the bit array does not contain a whole number of bytes then it is padded\n" - " with zero bits prior to being encoded.\n" -). --spec base16_encode(bitstring()) -> binary(). -base16_encode(Input) -> - gleam_stdlib:base16_encode(Input). - --file("src/gleam/bit_array.gleam", 170). -?DOC(" Decodes a base 16 encoded string into a `BitArray`.\n"). --spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}. -base16_decode(Input) -> - gleam_stdlib:base16_decode(Input). - --file("src/gleam/bit_array.gleam", 191). --spec inspect_loop(bitstring(), binary()) -> binary(). -inspect_loop(Input, Accumulator) -> - case Input of - <<>> -> - Accumulator; - - <> -> - <<<>/binary, - ":size(1)"/utf8>>; - - <> -> - <<<>/binary, - ":size(2)"/utf8>>; - - <> -> - <<<>/binary, - ":size(3)"/utf8>>; - - <> -> - <<<>/binary, - ":size(4)"/utf8>>; - - <> -> - <<<>/binary, - ":size(5)"/utf8>>; - - <> -> - <<<>/binary, - ":size(6)"/utf8>>; - - <> -> - <<<>/binary, - ":size(7)"/utf8>>; - - <> -> - Suffix = case Rest of - <<>> -> - <<""/utf8>>; - - _ -> - <<", "/utf8>> - end, - Accumulator@1 = <<<>/binary, - Suffix/binary>>, - inspect_loop(Rest, Accumulator@1); - - _ -> - Accumulator - end. - --file("src/gleam/bit_array.gleam", 187). -?DOC( - " Converts a bit array to a string containing the decimal value of each byte.\n" - "\n" - " Use this over `string.inspect` when you have a bit array you want printed\n" - " in the array syntax even if it is valid UTF-8.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert inspect(<<0, 20, 0x20, 255>>) == \"<<0, 20, 32, 255>>\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert inspect(<<100, 5:3>>) == \"<<100, 5:size(3)>>\"\n" - " ```\n" -). --spec inspect(bitstring()) -> binary(). -inspect(Input) -> - <<(inspect_loop(Input, <<"<<"/utf8>>))/binary, ">>"/utf8>>. - --file("src/gleam/bit_array.gleam", 233). -?DOC( - " Compare two bit arrays as sequences of bytes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert compare(<<1>>, <<2>>) == Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " assert compare(<<\"AB\":utf8>>, <<\"AA\":utf8>>) == Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " assert compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>) == Eq\n" - " ```\n" -). --spec compare(bitstring(), bitstring()) -> gleam@order:order(). -compare(A, B) -> - case {A, B} of - {<>, - <>} -> - case {First_byte, Second_byte} of - {F, S} when F > S -> - gt; - - {F@1, S@1} when F@1 < S@1 -> - lt; - - {_, _} -> - compare(First_rest, Second_rest) - end; - - {<<>>, <<>>} -> - eq; - - {_, <<>>} -> - gt; - - {<<>>, _} -> - lt; - - {First, Second} -> - case {gleam_stdlib:bit_array_to_int_and_size(First), - gleam_stdlib:bit_array_to_int_and_size(Second)} of - {{A@1, _}, {B@1, _}} when A@1 > B@1 -> - gt; - - {{A@2, _}, {B@2, _}} when A@2 < B@2 -> - lt; - - {{_, Size_a}, {_, Size_b}} when Size_a > Size_b -> - gt; - - {{_, Size_a@1}, {_, Size_b@1}} when Size_a@1 < Size_b@1 -> - lt; - - {_, _} -> - eq - end - end. - --file("src/gleam/bit_array.gleam", 273). -?DOC( - " Checks whether the first `BitArray` starts with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert starts_with(<<1, 2, 3, 4>>, <<1, 2>>)\n" - " ```\n" -). --spec starts_with(bitstring(), bitstring()) -> boolean(). -starts_with(Bits, Prefix) -> - Prefix_size = erlang:bit_size(Prefix), - case Bits of - <> when Pref =:= Prefix -> - true; - - _ -> - false - end. diff --git a/ui/javascript/gleam_stdlib/gleam@bool.erl b/ui/javascript/gleam_stdlib/gleam@bool.erl deleted file mode 100644 index edb3be8..0000000 --- a/ui/javascript/gleam_stdlib/gleam@bool.erl +++ /dev/null @@ -1,334 +0,0 @@ --module(gleam@bool). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bool.gleam"). --export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, to_string/1, guard/3, lazy_guard/3]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " A type with two possible values, `True` and `False`. Used to indicate whether\n" - " things are... true or false!\n" - "\n" - " It is often clearer and offers more type safety to define a custom type\n" - " than to use `Bool`. For example, rather than having a `is_teacher: Bool`\n" - " field consider having a `role: SchoolRole` field where `SchoolRole` is a custom\n" - " type that can be either `Student` or `Teacher`.\n" -). - --file("src/gleam/bool.gleam", 32). -?DOC( - " Returns the and of two bools, but it evaluates both arguments.\n" - "\n" - " It's the function equivalent of the `&&` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert and(True, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !and(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !and(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !and(False, False)\n" - " ```\n" -). --spec 'and'(boolean(), boolean()) -> boolean(). -'and'(A, B) -> - A andalso B. - --file("src/gleam/bool.gleam", 59). -?DOC( - " Returns the or of two bools, but it evaluates both arguments.\n" - "\n" - " It's the function equivalent of the `||` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert or(True, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(True, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !or(False, False)\n" - " ```\n" -). --spec 'or'(boolean(), boolean()) -> boolean(). -'or'(A, B) -> - A orelse B. - --file("src/gleam/bool.gleam", 77). -?DOC( - " Returns the opposite bool value.\n" - "\n" - " This is the same as the `!` or `not` operators in some other languages.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !negate(True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert negate(False)\n" - " ```\n" -). --spec negate(boolean()) -> boolean(). -negate(Bool) -> - not Bool. - --file("src/gleam/bool.gleam", 101). -?DOC( - " Returns the nor of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert nor(False, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !nor(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !nor(True, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !nor(True, True)\n" - " ```\n" -). --spec nor(boolean(), boolean()) -> boolean(). -nor(A, B) -> - not (A orelse B). - --file("src/gleam/bool.gleam", 125). -?DOC( - " Returns the nand of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert nand(False, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert nand(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert nand(True, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !nand(True, True)\n" - " ```\n" -). --spec nand(boolean(), boolean()) -> boolean(). -nand(A, B) -> - not (A andalso B). - --file("src/gleam/bool.gleam", 149). -?DOC( - " Returns the exclusive or of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !exclusive_or(False, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert exclusive_or(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert exclusive_or(True, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !exclusive_or(True, True)\n" - " ```\n" -). --spec exclusive_or(boolean(), boolean()) -> boolean(). -exclusive_or(A, B) -> - A /= B. - --file("src/gleam/bool.gleam", 173). -?DOC( - " Returns the exclusive nor of two bools.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert exclusive_nor(False, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !exclusive_nor(False, True)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !exclusive_nor(True, False)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert exclusive_nor(True, True)\n" - " ```\n" -). --spec exclusive_nor(boolean(), boolean()) -> boolean(). -exclusive_nor(A, B) -> - A =:= B. - --file("src/gleam/bool.gleam", 189). -?DOC( - " Returns a string representation of the given bool.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_string(True) == \"True\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_string(False) == \"False\"\n" - " ```\n" -). --spec to_string(boolean()) -> binary(). -to_string(Bool) -> - case Bool of - false -> - <<"False"/utf8>>; - - true -> - <<"True"/utf8>> - end. - --file("src/gleam/bool.gleam", 248). -?DOC( - " Run a callback function if the given bool is `False`, otherwise return a\n" - " default value.\n" - "\n" - " With a `use` expression this function can simulate the early-return pattern\n" - " found in some other programming languages.\n" - "\n" - " In a procedural language:\n" - "\n" - " ```js\n" - " if (predicate) return value;\n" - " // ...\n" - " ```\n" - "\n" - " In Gleam with a `use` expression:\n" - "\n" - " ```gleam\n" - " use <- guard(when: predicate, return: value)\n" - " // ...\n" - " ```\n" - "\n" - " Like everything in Gleam `use` is an expression, so it short circuits the\n" - " current block, not the entire function. As a result you can assign the value\n" - " to a variable:\n" - "\n" - " ```gleam\n" - " let x = {\n" - " use <- guard(when: predicate, return: value)\n" - " // ...\n" - " }\n" - " ```\n" - "\n" - " Note that unlike in procedural languages the `return` value is evaluated\n" - " even when the predicate is `False`, so it is advisable not to perform\n" - " expensive computation nor side-effects there.\n" - "\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let name = \"\"\n" - " use <- guard(when: name == \"\", return: \"Welcome!\")\n" - " \"Hello, \" <> name\n" - " // -> \"Welcome!\"\n" - " ```\n" - "\n" - " ```gleam\n" - " let name = \"Kamaka\"\n" - " use <- guard(when: name == \"\", return: \"Welcome!\")\n" - " \"Hello, \" <> name\n" - " // -> \"Hello, Kamaka\"\n" - " ```\n" -). --spec guard(boolean(), BTP, fun(() -> BTP)) -> BTP. -guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence; - - false -> - Alternative() - end. - --file("src/gleam/bool.gleam", 289). -?DOC( - " Runs a callback function if the given bool is `True`, otherwise runs an\n" - " alternative callback function.\n" - "\n" - " Useful when further computation should be delayed regardless of the given\n" - " bool's value.\n" - "\n" - " See [`guard`](#guard) for more info.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let name = \"Kamaka\"\n" - " let inquiry = fn() { \"How may we address you?\" }\n" - " use <- lazy_guard(when: name == \"\", return: inquiry)\n" - " \"Hello, \" <> name\n" - " // -> \"Hello, Kamaka\"\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " let name = \"\"\n" - " let greeting = fn() { \"Hello, \" <> name }\n" - " use <- lazy_guard(when: name == \"\", otherwise: greeting)\n" - " let number = int.random(99)\n" - " let name = \"User \" <> int.to_string(number)\n" - " \"Welcome, \" <> name\n" - " // -> \"Welcome, User 54\"\n" - " ```\n" -). --spec lazy_guard(boolean(), fun(() -> BTQ), fun(() -> BTQ)) -> BTQ. -lazy_guard(Requirement, Consequence, Alternative) -> - case Requirement of - true -> - Consequence(); - - false -> - Alternative() - end. diff --git a/ui/javascript/gleam_stdlib/gleam@bytes_tree.erl b/ui/javascript/gleam_stdlib/gleam@bytes_tree.erl deleted file mode 100644 index dc5cbae..0000000 --- a/ui/javascript/gleam_stdlib/gleam@bytes_tree.erl +++ /dev/null @@ -1,211 +0,0 @@ --module(gleam@bytes_tree). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/bytes_tree.gleam"). --export([concat/1, new/0, from_bit_array/1, append_tree/2, prepend/2, append/2, prepend_tree/2, from_string/1, prepend_string/2, append_string/2, concat_bit_arrays/1, from_string_tree/1, to_bit_array/1, byte_size/1]). --export_type([bytes_tree/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " `BytesTree` is a type used for efficiently building binary content to be\n" - " written to a file or a socket. Internally it is represented as a tree so to\n" - " append or prepend to a bytes tree is a constant time operation that\n" - " allocates a new node in the tree without copying any of the content. When\n" - " writing to an output stream the tree is traversed and the content is sent\n" - " directly rather than copying it into a single buffer beforehand.\n" - "\n" - " If we append one bit array to another the bit arrays must be copied to a\n" - " new location in memory so that they can sit together. This behaviour\n" - " enables efficient reading of the data but copying can be expensive,\n" - " especially if we want to join many bit arrays together.\n" - "\n" - " BytesTree is different in that it can be joined together in constant\n" - " time using minimal memory, and then can be efficiently converted to a\n" - " bit array using the `to_bit_array` function.\n" - "\n" - " Byte trees are always byte aligned, so that a number of bits that is not\n" - " divisible by 8 will be padded with 0s.\n" - "\n" - " On Erlang this type is compatible with Erlang's iolists.\n" -). - --opaque bytes_tree() :: {bytes, bitstring()} | - {text, gleam@string_tree:string_tree()} | - {many, list(bytes_tree())}. - --file("src/gleam/bytes_tree.gleam", 98). -?DOC( - " Joins a list of bytes trees into a single one.\n" - "\n" - " Runs in constant time.\n" -). --spec concat(list(bytes_tree())) -> bytes_tree(). -concat(Trees) -> - gleam_stdlib:identity(Trees). - --file("src/gleam/bytes_tree.gleam", 35). -?DOC( - " Create an empty `BytesTree`. Useful as the start of a pipe chaining many\n" - " trees together.\n" -). --spec new() -> bytes_tree(). -new() -> - gleam_stdlib:identity([]). - --file("src/gleam/bytes_tree.gleam", 136). -?DOC( - " Creates a new bytes tree from a bit array.\n" - "\n" - " Runs in constant time.\n" -). --spec from_bit_array(bitstring()) -> bytes_tree(). -from_bit_array(Bits) -> - _pipe = Bits, - _pipe@1 = gleam_stdlib:bit_array_pad_to_bytes(_pipe), - gleam_stdlib:wrap_list(_pipe@1). - --file("src/gleam/bytes_tree.gleam", 68). -?DOC( - " Appends a bytes tree onto the end of another.\n" - "\n" - " Runs in constant time.\n" -). --spec append_tree(bytes_tree(), bytes_tree()) -> bytes_tree(). -append_tree(First, Second) -> - gleam_stdlib:iodata_append(First, Second). - --file("src/gleam/bytes_tree.gleam", 43). -?DOC( - " Prepends a bit array to the start of a bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend(bytes_tree(), bitstring()) -> bytes_tree(). -prepend(Second, First) -> - gleam_stdlib:iodata_append(from_bit_array(First), Second). - --file("src/gleam/bytes_tree.gleam", 51). -?DOC( - " Appends a bit array to the end of a bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec append(bytes_tree(), bitstring()) -> bytes_tree(). -append(First, Second) -> - gleam_stdlib:iodata_append(First, from_bit_array(Second)). - --file("src/gleam/bytes_tree.gleam", 59). -?DOC( - " Prepends a bytes tree onto the start of another.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend_tree(bytes_tree(), bytes_tree()) -> bytes_tree(). -prepend_tree(Second, First) -> - gleam_stdlib:iodata_append(First, Second). - --file("src/gleam/bytes_tree.gleam", 118). -?DOC( - " Creates a new bytes tree from a string.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time otherwise.\n" -). --spec from_string(binary()) -> bytes_tree(). -from_string(String) -> - gleam_stdlib:wrap_list(String). - --file("src/gleam/bytes_tree.gleam", 80). -?DOC( - " Prepends a string onto the start of a bytes tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time with the length of the string otherwise.\n" -). --spec prepend_string(bytes_tree(), binary()) -> bytes_tree(). -prepend_string(Second, First) -> - gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). - --file("src/gleam/bytes_tree.gleam", 89). -?DOC( - " Appends a string onto the end of a bytes tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time with the length of the string otherwise.\n" -). --spec append_string(bytes_tree(), binary()) -> bytes_tree(). -append_string(First, Second) -> - gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). - --file("src/gleam/bytes_tree.gleam", 106). -?DOC( - " Joins a list of bit arrays into a single bytes tree.\n" - "\n" - " Runs in constant time.\n" -). --spec concat_bit_arrays(list(bitstring())) -> bytes_tree(). -concat_bit_arrays(Bits) -> - _pipe = Bits, - _pipe@1 = gleam@list:map(_pipe, fun from_bit_array/1), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/bytes_tree.gleam", 128). -?DOC( - " Creates a new bytes tree from a string tree.\n" - "\n" - " Runs in constant time when running on Erlang.\n" - " Runs in linear time otherwise.\n" -). --spec from_string_tree(gleam@string_tree:string_tree()) -> bytes_tree(). -from_string_tree(Tree) -> - gleam_stdlib:wrap_list(Tree). - --file("src/gleam/bytes_tree.gleam", 162). --spec to_list(list(list(bytes_tree())), list(bitstring())) -> list(bitstring()). -to_list(Stack, Acc) -> - case Stack of - [] -> - Acc; - - [[] | Remaining_stack] -> - to_list(Remaining_stack, Acc); - - [[{bytes, Bits} | Rest] | Remaining_stack@1] -> - to_list([Rest | Remaining_stack@1], [Bits | Acc]); - - [[{text, Tree} | Rest@1] | Remaining_stack@2] -> - Bits@1 = gleam_stdlib:identity(unicode:characters_to_binary(Tree)), - to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]); - - [[{many, Trees} | Rest@2] | Remaining_stack@3] -> - to_list([Trees, Rest@2 | Remaining_stack@3], Acc) - end. - --file("src/gleam/bytes_tree.gleam", 155). -?DOC( - " Turns a bytes tree into a bit array.\n" - "\n" - " Runs in linear time.\n" - "\n" - " When running on Erlang this function is implemented natively by the\n" - " virtual machine and is highly optimised.\n" -). --spec to_bit_array(bytes_tree()) -> bitstring(). -to_bit_array(Tree) -> - erlang:list_to_bitstring(Tree). - --file("src/gleam/bytes_tree.gleam", 186). -?DOC( - " Returns the size of the bytes tree's content in bytes.\n" - "\n" - " Runs in linear time.\n" -). --spec byte_size(bytes_tree()) -> integer(). -byte_size(Tree) -> - erlang:iolist_size(Tree). diff --git a/ui/javascript/gleam_stdlib/gleam@dict.erl b/ui/javascript/gleam_stdlib/gleam@dict.erl deleted file mode 100644 index cef861c..0000000 --- a/ui/javascript/gleam_stdlib/gleam@dict.erl +++ /dev/null @@ -1,513 +0,0 @@ --module(gleam@dict). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dict.gleam"). --export([size/1, is_empty/1, fold/3, to_list/1, new/0, from_list/1, has_key/2, get/2, insert/3, map_values/2, keys/1, values/1, filter/2, take/2, combine/3, merge/2, delete/2, drop/2, upsert/3, each/2, group/2]). --export_type([dict/2, transient_dict/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type dict(JL, JM) :: any() | {gleam_phantom, JL, JM}. - --type transient_dict(JN, JO) :: any() | {gleam_phantom, JN, JO}. - --file("src/gleam/dict.gleam", 53). -?DOC( - " Determines the number of key-value pairs in the dict.\n" - " This function runs in constant time and does not need to iterate the dict.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> size == 0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert new() |> insert(\"key\", \"value\") |> size == 1\n" - " ```\n" -). --spec size(dict(any(), any())) -> integer(). -size(Dict) -> - maps:size(Dict). - --file("src/gleam/dict.gleam", 67). -?DOC( - " Determines whether or not the dict is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> is_empty\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !{ new() |> insert(\"b\", 1) |> is_empty }\n" - " ```\n" -). --spec is_empty(dict(any(), any())) -> boolean(). -is_empty(Dict) -> - maps:size(Dict) =:= 0. - --file("src/gleam/dict.gleam", 469). -?DOC( - " Combines all entries into a single value by calling a given function on each\n" - " one.\n" - "\n" - " Dicts are not ordered so the values are not returned in any specific order. Do\n" - " not write code that relies on the order entries are used by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n" - " assert fold(dict, 0, fn(accumulator, key, value) { accumulator + value })\n" - " == 13\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/string\n" - "\n" - " let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n" - " assert\n" - " fold(dict, \"\", fn(accumulator, key, value) {\n" - " string.append(accumulator, key)\n" - " })\n" - " == \"abc\"\n" - " ```\n" -). --spec fold(dict(QN, QO), QR, fun((QR, QN, QO) -> QR)) -> QR. -fold(Dict, Initial, Fun) -> - Fun@1 = fun(Key, Value, Acc) -> Fun(Acc, Key, Value) end, - maps:fold(Fun@1, Initial, Dict). - --file("src/gleam/dict.gleam", 97). -?DOC( - " Converts the dict to a list of 2-element tuples `#(key, value)`, one for\n" - " each key-value pair in the dict.\n" - "\n" - " The tuples in the list have no specific order.\n" - "\n" - " ## Examples\n" - "\n" - " Calling `to_list` on an empty `dict` returns an empty list.\n" - "\n" - " ```gleam\n" - " assert new() |> to_list == []\n" - " ```\n" - "\n" - " The ordering of elements in the resulting list is an implementation detail\n" - " that should not be relied upon.\n" - "\n" - " ```gleam\n" - " assert new()\n" - " |> insert(\"b\", 1)\n" - " |> insert(\"a\", 0)\n" - " |> insert(\"c\", 2)\n" - " |> to_list\n" - " == [#(\"a\", 0), #(\"b\", 1), #(\"c\", 2)]\n" - " ```\n" -). --spec to_list(dict(KJ, KK)) -> list({KJ, KK}). -to_list(Dict) -> - maps:to_list(Dict). - --file("src/gleam/dict.gleam", 146). -?DOC(" Creates a fresh dict that contains no values.\n"). --spec new() -> dict(any(), any()). -new() -> - maps:new(). - --file("src/gleam/dict.gleam", 111). --spec from_list_loop(transient_dict(KT, KU), list({KT, KU})) -> dict(KT, KU). -from_list_loop(Transient, List) -> - case List of - [] -> - gleam_stdlib:identity(Transient); - - [{Key, Value} | Rest] -> - from_list_loop(maps:put(Key, Value, Transient), Rest) - end. - --file("src/gleam/dict.gleam", 107). -?DOC( - " Converts a list of 2-element tuples `#(key, value)` to a dict.\n" - "\n" - " If two tuples have the same key the last one in the list will be the one\n" - " that is present in the dict.\n" -). --spec from_list(list({KO, KP})) -> dict(KO, KP). -from_list(List) -> - maps:from_list(List). - --file("src/gleam/dict.gleam", 135). -?DOC( - " Determines whether or not a value is present in the dict for a given key.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> insert(\"a\", 0) |> has_key(\"a\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !{ new() |> insert(\"a\", 0) |> has_key(\"b\") }\n" - " ```\n" -). --spec has_key(dict(LA, any()), LA) -> boolean(). -has_key(Dict, Key) -> - maps:is_key(Key, Dict). - --file("src/gleam/dict.gleam", 165). -?DOC( - " Fetches a value from a dict for a given key.\n" - "\n" - " The dict may not have a value for the key, so the value is wrapped in a\n" - " `Result`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> insert(\"a\", 0) |> get(\"a\") == Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert new() |> insert(\"a\", 0) |> get(\"b\") == Error(Nil)\n" - " ```\n" -). --spec get(dict(LM, LN), LM) -> {ok, LN} | {error, nil}. -get(From, Get) -> - gleam_stdlib:map_get(From, Get). - --file("src/gleam/dict.gleam", 183). -?DOC( - " Inserts a value into the dict with the given key.\n" - "\n" - " If the dict already has a value for the given key then the value is\n" - " replaced with the new value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> insert(\"a\", 0) == from_list([#(\"a\", 0)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert new() |> insert(\"a\", 0) |> insert(\"a\", 5) == from_list([#(\"a\", 5)])\n" - " ```\n" -). --spec insert(dict(LS, LT), LS, LT) -> dict(LS, LT). -insert(Dict, Key, Value) -> - maps:put(Key, Value, Dict). - --file("src/gleam/dict.gleam", 210). -?DOC( - " Updates all values in a given dict by calling a given function on each key\n" - " and value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(3, 3), #(2, 4)])\n" - " |> map_values(fn(key, value) { key * value })\n" - " == from_list([#(3, 9), #(2, 8)])\n" - " ```\n" -). --spec map_values(dict(MK, ML), fun((MK, ML) -> MO)) -> dict(MK, MO). -map_values(Dict, Fun) -> - maps:map(Fun, Dict). - --file("src/gleam/dict.gleam", 230). -?DOC( - " Gets a list of all keys in a given dict.\n" - "\n" - " Dicts are not ordered so the keys are not returned in any specific order. Do\n" - " not write code that relies on the order keys are returned by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> keys == [\"a\", \"b\"]\n" - " ```\n" -). --spec keys(dict(MY, any())) -> list(MY). -keys(Dict) -> - maps:keys(Dict). - --file("src/gleam/dict.gleam", 247). -?DOC( - " Gets a list of all values in a given dict.\n" - "\n" - " Dicts are not ordered so the values are not returned in any specific order. Do\n" - " not write code that relies on the order values are returned by this function\n" - " as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> values == [0, 1]\n" - " ```\n" -). --spec values(dict(any(), NE)) -> list(NE). -values(Dict) -> - maps:values(Dict). - --file("src/gleam/dict.gleam", 268). -?DOC( - " Creates a new dict from a given dict, minus any entries that a given function\n" - " returns `False` for.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> filter(fn(key, value) { value != 0 })\n" - " == from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> filter(fn(key, value) { True })\n" - " == from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec filter(dict(NI, NJ), fun((NI, NJ) -> boolean())) -> dict(NI, NJ). -filter(Dict, Predicate) -> - maps:filter(Predicate, Dict). - --file("src/gleam/dict.gleam", 313). --spec do_take_loop(dict(OI, OJ), list(OI), transient_dict(OI, OJ)) -> dict(OI, OJ). -do_take_loop(Dict, Desired_keys, Acc) -> - case Desired_keys of - [] -> - gleam_stdlib:identity(Acc); - - [Key | Rest] -> - case gleam_stdlib:map_get(Dict, Key) of - {ok, Value} -> - do_take_loop(Dict, Rest, maps:put(Key, Value, Acc)); - - {error, _} -> - do_take_loop(Dict, Rest, Acc) - end - end. - --file("src/gleam/dict.gleam", 304). -?DOC( - " Creates a new dict from a given dict, only including any entries for which the\n" - " keys are in a given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> take([\"b\"])\n" - " == from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " |> take([\"a\", \"b\", \"c\"])\n" - " == from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec take(dict(NU, NV), list(NU)) -> dict(NU, NV). -take(Dict, Desired_keys) -> - maps:with(Desired_keys, Dict). - --file("src/gleam/dict.gleam", 525). -?DOC( - " Creates a new dict from a pair of given dicts by combining their entries.\n" - "\n" - " If there are entries with the same keys in both dicts the given function is\n" - " used to determine the new value to use in the resulting dict.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " let b = from_list([#(\"a\", 2), #(\"c\", 3)])\n" - " assert combine(a, b, fn(one, other) { one + other })\n" - " == from_list([#(\"a\", 2), #(\"b\", 1), #(\"c\", 3)])\n" - " ```\n" -). --spec combine(dict(RC, RD), dict(RC, RD), fun((RD, RD) -> RD)) -> dict(RC, RD). -combine(Dict, Other, Fun) -> - maps:merge_with(fun(_, L, R) -> Fun(L, R) end, Dict, Other). - --file("src/gleam/dict.gleam", 342). -?DOC( - " Creates a new dict from a pair of given dicts by combining their entries.\n" - "\n" - " If there are entries with the same keys in both dicts the entry from the\n" - " second dict takes precedence.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " let b = from_list([#(\"b\", 2), #(\"c\", 3)])\n" - " assert merge(a, b) == from_list([#(\"a\", 0), #(\"b\", 2), #(\"c\", 3)])\n" - " ```\n" -). --spec merge(dict(OR, OS), dict(OR, OS)) -> dict(OR, OS). -merge(Dict, New_entries) -> - maps:merge(Dict, New_entries). - --file("src/gleam/dict.gleam", 361). -?DOC( - " Creates a new dict from a given dict with all the same entries except for the\n" - " one with a given key, if it exists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"a\")\n" - " == from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"c\")\n" - " == from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" -). --spec delete(dict(OZ, PA), OZ) -> dict(OZ, PA). -delete(Dict, Key) -> - _pipe = gleam_stdlib:identity(Dict), - _pipe@1 = maps:remove(Key, _pipe), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/dict.gleam", 398). --spec drop_loop(transient_dict(PZ, QA), list(PZ)) -> dict(PZ, QA). -drop_loop(Transient, Disallowed_keys) -> - case Disallowed_keys of - [] -> - gleam_stdlib:identity(Transient); - - [Key | Rest] -> - drop_loop(maps:remove(Key, Transient), Rest) - end. - --file("src/gleam/dict.gleam", 389). -?DOC( - " Creates a new dict from a given dict with all the same entries except any with\n" - " keys found in a given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\"])\n" - " == from_list([#(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"c\"])\n" - " == from_list([#(\"a\", 0), #(\"b\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\", \"b\", \"c\"])\n" - " == from_list([])\n" - " ```\n" -). --spec drop(dict(PL, PM), list(PL)) -> dict(PL, PM). -drop(Dict, Disallowed_keys) -> - maps:without(Disallowed_keys, Dict). - --file("src/gleam/dict.gleam", 431). -?DOC( - " Creates a new dict with one entry inserted or updated using a given function.\n" - "\n" - " If there was not an entry in the dict for the given key then the function\n" - " gets `None` as its argument, otherwise it gets `Some(value)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let dict = from_list([#(\"a\", 0)])\n" - " let increment = fn(x) {\n" - " case x {\n" - " Some(i) -> i + 1\n" - " None -> 0\n" - " }\n" - " }\n" - "\n" - " assert upsert(dict, \"a\", increment) == from_list([#(\"a\", 1)])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert upsert(dict, \"b\", increment) == from_list([#(\"a\", 0), #(\"b\", 0)])\n" - " ```\n" -). --spec upsert(dict(QG, QH), QG, fun((gleam@option:option(QH)) -> QH)) -> dict(QG, QH). -upsert(Dict, Key, Fun) -> - case gleam_stdlib:map_get(Dict, Key) of - {ok, Value} -> - insert(Dict, Key, Fun({some, Value})); - - {error, _} -> - insert(Dict, Key, Fun(none)) - end. - --file("src/gleam/dict.gleam", 504). -?DOC( - " Calls a function for each key and value in a dict, discarding the return\n" - " value.\n" - "\n" - " Useful for producing a side effect for every item of a dict.\n" - "\n" - " ```gleam\n" - " import gleam/io\n" - "\n" - " let dict = from_list([#(\"a\", \"apple\"), #(\"b\", \"banana\"), #(\"c\", \"cherry\")])\n" - "\n" - " assert\n" - " each(dict, fn(k, v) {\n" - " io.println(k <> \" => \" <> v)\n" - " })\n" - " == Nil\n" - " // a => apple\n" - " // b => banana\n" - " // c => cherry\n" - " ```\n" - "\n" - " The order of elements in the iteration is an implementation detail that\n" - " should not be relied upon.\n" -). --spec each(dict(QX, QY), fun((QX, QY) -> any())) -> nil. -each(Dict, Fun) -> - fold( - Dict, - nil, - fun(Nil, K, V) -> - Fun(K, V), - Nil - end - ). - --file("src/gleam/dict.gleam", 566). --spec group_loop(transient_dict(SE, list(SF)), fun((SF) -> SE), list(SF)) -> dict(SE, list(SF)). -group_loop(Transient, To_key, List) -> - case List of - [] -> - gleam_stdlib:identity(Transient); - - [Value | Rest] -> - Key = To_key(Value), - Update = fun(Existing) -> [Value | Existing] end, - _pipe = Transient, - _pipe@1 = maps:update_with(Key, Update, [Value], _pipe), - group_loop(_pipe@1, To_key, Rest) - end. - --file("src/gleam/dict.gleam", 562). -?DOC(false). --spec group(fun((RY) -> RZ), list(RY)) -> dict(RZ, list(RY)). -group(Key, List) -> - group_loop(gleam_stdlib:identity(maps:new()), Key, List). diff --git a/ui/javascript/gleam_stdlib/gleam@dynamic.erl b/ui/javascript/gleam_stdlib/gleam@dynamic.erl deleted file mode 100644 index 5c260ef..0000000 --- a/ui/javascript/gleam_stdlib/gleam@dynamic.erl +++ /dev/null @@ -1,105 +0,0 @@ --module(gleam@dynamic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dynamic.gleam"). --export([classify/1, bool/1, string/1, float/1, int/1, bit_array/1, list/1, array/1, properties/1, nil/0]). --export_type([dynamic_/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type dynamic_() :: any(). - --file("src/gleam/dynamic.gleam", 29). -?DOC( - " Return a string indicating the type of the dynamic value.\n" - "\n" - " This function may be useful for constructing error messages or logs. If you\n" - " want to turn dynamic data into well typed data then you want the\n" - " `gleam/dynamic/decode` module.\n" - "\n" - " ```gleam\n" - " assert classify(string(\"Hello\")) == \"String\"\n" - " ```\n" -). --spec classify(dynamic_()) -> binary(). -classify(Data) -> - gleam_stdlib:classify_dynamic(Data). - --file("src/gleam/dynamic.gleam", 35). -?DOC(" Create a dynamic value from a bool.\n"). --spec bool(boolean()) -> dynamic_(). -bool(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 43). -?DOC( - " Create a dynamic value from a string.\n" - "\n" - " On Erlang this will be a binary string rather than a character list.\n" -). --spec string(binary()) -> dynamic_(). -string(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 49). -?DOC(" Create a dynamic value from a float.\n"). --spec float(float()) -> dynamic_(). -float(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 55). -?DOC(" Create a dynamic value from an int.\n"). --spec int(integer()) -> dynamic_(). -int(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 61). -?DOC(" Create a dynamic value from a bit array.\n"). --spec bit_array(bitstring()) -> dynamic_(). -bit_array(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 67). -?DOC(" Create a dynamic value from a list.\n"). --spec list(list(dynamic_())) -> dynamic_(). -list(A) -> - gleam_stdlib:identity(A). - --file("src/gleam/dynamic.gleam", 76). -?DOC( - " Create a dynamic value from a list, converting it to a sequential runtime\n" - " format rather than the regular list format.\n" - "\n" - " On Erlang this will be a tuple, on JavaScript this will be an array.\n" -). --spec array(list(dynamic_())) -> dynamic_(). -array(A) -> - erlang:list_to_tuple(A). - --file("src/gleam/dynamic.gleam", 84). -?DOC( - " Create a dynamic value made of an unordered series of keys and values, where\n" - " the keys are unique.\n" - "\n" - " On Erlang this will be a map, on JavaScript this will be a Gleam dict\n" - " object.\n" -). --spec properties(list({dynamic_(), dynamic_()})) -> dynamic_(). -properties(Entries) -> - gleam_stdlib:identity(maps:from_list(Entries)). - --file("src/gleam/dynamic.gleam", 93). -?DOC( - " A dynamic value representing nothing.\n" - "\n" - " On Erlang this will be the atom `nil`, on JavaScript this will be\n" - " `undefined`.\n" -). --spec nil() -> dynamic_(). -nil() -> - gleam_stdlib:identity(nil). diff --git a/ui/javascript/gleam_stdlib/gleam@dynamic@decode.erl b/ui/javascript/gleam_stdlib/gleam@dynamic@decode.erl deleted file mode 100644 index 7ab6d32..0000000 --- a/ui/javascript/gleam_stdlib/gleam@dynamic@decode.erl +++ /dev/null @@ -1,1121 +0,0 @@ --module(gleam@dynamic@decode). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/dynamic/decode.gleam"). --export([decode_dynamic/1, run/2, decode_float/1, map/2, decode_int/1, decode_bit_array/1, decode_string/1, one_of/2, list/1, subfield/3, at/2, success/1, decode_error/2, field/3, optional_field/4, optionally_at/3, decode_bool/1, dict/2, optional/1, map_errors/2, collapse_errors/2, then/2, failure/2, new_primitive_decoder/2, recursive/1]). --export_type([decode_error/0, decoder/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " The `Dynamic` type is used to represent dynamically typed data. That is, data\n" - " that we don't know the precise type of yet, so we need to introspect the data to\n" - " see if it is of the desired type before we can use it. Typically data like this\n" - " would come from user input or from untyped languages such as Erlang or JavaScript.\n" - "\n" - " This module provides the `Decoder` type and associated functions, which provides\n" - " a type-safe and composable way to convert dynamic data into some desired type,\n" - " or into errors if the data doesn't have the desired structure.\n" - "\n" - " The `Decoder` type is generic and has 1 type parameter, which is the type that\n" - " it attempts to decode. A `Decoder(String)` can be used to decode strings, and a\n" - " `Decoder(Option(Int))` can be used to decode `Option(Int)`s\n" - "\n" - " Decoders work using _runtime reflection_ and the data structures of the target\n" - " platform. Differences between Erlang and JavaScript data structures may impact\n" - " your decoders, so it is important to test your decoders on all supported\n" - " platforms.\n" - "\n" - " The decoding technique used by this module was inspired by Juraj Petráš'\n" - " [Toy](https://github.com/Hackder/toy), Go's `encoding/json`, and Elm's\n" - " `Json.Decode`. Thank you to them!\n" - "\n" - " # Generating decoders\n" - "\n" - " The language server has the \"generate dynamic decoder\" code action, which\n" - " will generate a decoder function when run on a custom type definition.\n" - " This generated decoder function can be a convenient shortcut when creating\n" - " your own decoders, and you can edit the generated function to suit your needs.\n" - "\n" - " # Examples\n" - "\n" - " Dynamic data may come from various sources and so many different syntaxes could\n" - " be used to describe or construct them. In these examples a pseudocode\n" - " syntax is used to describe the data.\n" - "\n" - " ## Simple types\n" - "\n" - " This module defines decoders for simple data types such as [`string`](#string),\n" - " [`int`](#int), [`float`](#float), [`bit_array`](#bit_array), and [`bool`](#bool).\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // \"Hello, Joe!\"\n" - "\n" - " let result = decode.run(data, decode.string)\n" - " assert result == Ok(\"Hello, Joe!\")\n" - " ```\n" - "\n" - " ## Lists\n" - "\n" - " The [`list`](#list) decoder decodes `List`s. To use it you must construct it by\n" - " passing in another decoder into the `list` function, which is the decoder that\n" - " is to be used for the elements of the list, type checking both the list and its\n" - " elements.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // [1, 2, 3, 4]\n" - "\n" - " let result = decode.run(data, decode.list(decode.int))\n" - " assert result == Ok([1, 2, 3, 4])\n" - " ```\n" - "\n" - " On Erlang this decoder can decode from lists, and on JavaScript it can\n" - " decode from lists as well as JavaScript arrays.\n" - "\n" - " ## Options\n" - "\n" - " The [`optional`](#optional) decoder is used to decode values that may or may not\n" - " be present. In other environments these might be called \"nullable\" values.\n" - "\n" - " Like the `list` decoder, the `optional` decoder takes another decoder,\n" - " which is used to decode the value if it is present.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // 12.45\n" - "\n" - " let result = decode.run(data, decode.optional(decode.float))\n" - " assert result == Ok(option.Some(12.45))\n" - " ```\n" - " ```gleam\n" - " // Data:\n" - " // null\n" - "\n" - " let result = decode.run(data, decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" - "\n" - " This decoder knows how to handle multiple different runtime representations of\n" - " absent values, including `Nil`, `None`, `null`, and `undefined`.\n" - "\n" - " ## Dicts\n" - "\n" - " The [`dict`](#dict) decoder decodes `Dicts` and contains two other decoders, one\n" - " for the keys, one for the values.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // { \"Lucy\" -> 10, \"Nubi\" -> 20 }\n" - "\n" - " let result = decode.run(data, decode.dict(decode.string, decode.int))\n" - " assert result == Ok(dict.from_list([\n" - " #(\"Lucy\", 10),\n" - " #(\"Nubi\", 20),\n" - " ]))\n" - " ```\n" - "\n" - " ## Indexing objects\n" - "\n" - " The [`at`](#at) decoder can be used to decode a value that is nested within\n" - " key-value containers such as Gleam dicts, Erlang maps, or JavaScript objects.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // { \"one\" -> { \"two\" -> 123 } }\n" - "\n" - " let result = decode.run(data, decode.at([\"one\", \"two\"], decode.int))\n" - " assert result == Ok(123)\n" - " ```\n" - "\n" - " ## Indexing arrays\n" - "\n" - " If you use ints as keys then the [`at`](#at) decoder can be used to index into\n" - " array-like containers such as Gleam or Erlang tuples, or JavaScript arrays.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // [\"one\", \"two\", \"three\"]\n" - "\n" - " let result = decode.run(data, decode.at([1], decode.string))\n" - " assert result == Ok(\"two\")\n" - " ```\n" - "\n" - " ## Records\n" - "\n" - " Decoding records from dynamic data is more complex and requires combining a\n" - " decoder for each field and a special constructor that builds your records with\n" - " the decoded field values.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // {\n" - " // \"score\" -> 180,\n" - " // \"name\" -> \"Mel Smith\",\n" - " // \"is-admin\" -> false,\n" - " // \"enrolled\" -> true,\n" - " // \"colour\" -> \"Red\",\n" - " // }\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use score <- decode.field(\"score\", decode.int)\n" - " use colour <- decode.field(\"colour\", decode.string)\n" - " use enrolled <- decode.field(\"enrolled\", decode.bool)\n" - " decode.success(Player(name:, score:, colour:, enrolled:))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(Player(\"Mel Smith\", 180, \"Red\", True))\n" - " ```\n" - "\n" - " ## Enum variants\n" - "\n" - " Imagine you have a custom type where all the variants do not contain any values.\n" - "\n" - " ```gleam\n" - " pub type PocketMonsterType {\n" - " Fire\n" - " Water\n" - " Grass\n" - " Electric\n" - " }\n" - " ```\n" - "\n" - " You might choose to encode these variants as strings, `\"fire\"` for `Fire`,\n" - " `\"water\"` for `Water`, and so on. To decode them you'll need to decode the dynamic\n" - " data as a string, but then you'll need to decode it further still as not all\n" - " strings are valid values for the enum. This can be done with the `then`\n" - " function, which enables running a second decoder after the first one\n" - " succeeds.\n" - "\n" - " ```gleam\n" - " let decoder = {\n" - " use decoded_string <- decode.then(decode.string)\n" - " case decoded_string {\n" - " // Return succeeding decoders for valid strings\n" - " \"fire\" -> decode.success(Fire)\n" - " \"water\" -> decode.success(Water)\n" - " \"grass\" -> decode.success(Grass)\n" - " \"electric\" -> decode.success(Electric)\n" - " // Return a failing decoder for any other strings\n" - " _ -> decode.failure(Fire, expected: \"PocketMonsterType\")\n" - " }\n" - " }\n" - "\n" - " let result = decode.run(dynamic.string(\"water\"), decoder)\n" - " assert result == Ok(Water)\n" - "\n" - " let result = decode.run(dynamic.string(\"wobble\"), decoder)\n" - " assert result == Error([DecodeError(\"PocketMonsterType\", \"String\", [])])\n" - " ```\n" - "\n" - " ## Record variants\n" - "\n" - " Decoding type variants that contain other values is done by combining the\n" - " techniques from the \"enum variants\" and \"records\" examples. Imagine you have\n" - " this custom type that you want to decode:\n" - "\n" - " ```gleam\n" - " pub type PocketMonsterPerson {\n" - " Trainer(name: String, badge_count: Int)\n" - " GymLeader(name: String, speciality: PocketMonsterType)\n" - " }\n" - " ```\n" - " And you would like to be able to decode these from dynamic data like this:\n" - " ```erlang\n" - " {\n" - " \"type\" -> \"trainer\",\n" - " \"name\" -> \"Ash\",\n" - " \"badge-count\" -> 1,\n" - " }\n" - " ```\n" - " ```erlang\n" - " {\n" - " \"type\" -> \"gym-leader\",\n" - " \"name\" -> \"Misty\",\n" - " \"speciality\" -> \"water\",\n" - " }\n" - " ```\n" - "\n" - " Notice how both documents have a `\"type\"` field, which is used to indicate which\n" - " variant the data is for.\n" - "\n" - " First, define decoders for each of the variants:\n" - "\n" - " ```gleam\n" - " let trainer_decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use badge_count <- decode.field(\"badge-count\", decode.int)\n" - " decode.success(Trainer(name, badge_count))\n" - " }\n" - "\n" - " let gym_leader_decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use speciality <- decode.field(\"speciality\", pocket_monster_type_decoder)\n" - " decode.success(GymLeader(name, speciality))\n" - " }\n" - " ```\n" - "\n" - " A third decoder can be used to extract and decode the `\"type\"` field, and the\n" - " expression can evaluate to whichever decoder is suitable for the document.\n" - "\n" - " ```gleam\n" - " // Data:\n" - " // {\n" - " // \"type\" -> \"gym-leader\",\n" - " // \"name\" -> \"Misty\",\n" - " // \"speciality\" -> \"water\",\n" - " // }\n" - "\n" - " let decoder = {\n" - " use tag <- decode.field(\"type\", decode.string)\n" - " case tag {\n" - " \"gym-leader\" -> gym_leader_decoder\n" - " _ -> trainer_decoder\n" - " }\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(GymLeader(\"Misty\", Water))\n" - " ```\n" -). - --type decode_error() :: {decode_error, binary(), binary(), list(binary())}. - --opaque decoder(BVN) :: {decoder, - fun((gleam@dynamic:dynamic_()) -> {BVN, list(decode_error())})}. - --file("src/gleam/dynamic/decode.gleam", 742). --spec decode_dynamic(gleam@dynamic:dynamic_()) -> {gleam@dynamic:dynamic_(), - list(decode_error())}. -decode_dynamic(Data) -> - {Data, []}. - --file("src/gleam/dynamic/decode.gleam", 364). -?DOC( - " Run a decoder on a `Dynamic` value, decoding the value if it is of the\n" - " desired type, or returning errors.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", decode.string)\n" - " use email <- decode.field(\"email\", decode.string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " decode.run(data, decoder)\n" - " ```\n" -). --spec run(gleam@dynamic:dynamic_(), decoder(BVV)) -> {ok, BVV} | - {error, list(decode_error())}. -run(Data, Decoder) -> - {Maybe_invalid_data, Errors} = (erlang:element(2, Decoder))(Data), - case Errors of - [] -> - {ok, Maybe_invalid_data}; - - [_ | _] -> - {error, Errors} - end. - --file("src/gleam/dynamic/decode.gleam", 617). --spec run_dynamic_function( - gleam@dynamic:dynamic_(), - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, BXQ} | {error, BXQ}) -) -> {BXQ, list(decode_error())}. -run_dynamic_function(Data, Name, F) -> - case F(Data) of - {ok, Data@1} -> - {Data@1, []}; - - {error, Placeholder} -> - {Placeholder, - [{decode_error, Name, gleam_stdlib:classify_dynamic(Data), []}]} - end. - --file("src/gleam/dynamic/decode.gleam", 723). --spec decode_float(gleam@dynamic:dynamic_()) -> {float(), list(decode_error())}. -decode_float(Data) -> - run_dynamic_function(Data, <<"Float"/utf8>>, fun gleam_stdlib:float/1). - --file("src/gleam/dynamic/decode.gleam", 902). -?DOC( - " Apply a transformation function to any value decoded by the decoder.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.int |> decode.map(int.to_string)\n" - " let result = decode.run(dynamic.int(1000), decoder)\n" - " assert result == Ok(\"1000\")\n" - " ```\n" -). --spec map(decoder(BZT), fun((BZT) -> BZV)) -> decoder(BZV). -map(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Transformer(Data), Errors} - end}. - --file("src/gleam/dynamic/decode.gleam", 697). --spec decode_int(gleam@dynamic:dynamic_()) -> {integer(), list(decode_error())}. -decode_int(Data) -> - run_dynamic_function(Data, <<"Int"/utf8>>, fun gleam_stdlib:int/1). - --file("src/gleam/dynamic/decode.gleam", 757). --spec decode_bit_array(gleam@dynamic:dynamic_()) -> {bitstring(), - list(decode_error())}. -decode_bit_array(Data) -> - run_dynamic_function( - Data, - <<"BitArray"/utf8>>, - fun gleam_stdlib:bit_array/1 - ). - --file("src/gleam/dynamic/decode.gleam", 646). --spec dynamic_string(gleam@dynamic:dynamic_()) -> {ok, binary()} | - {error, binary()}. -dynamic_string(Data) -> - case gleam_stdlib:bit_array(Data) of - {ok, Data@1} -> - case gleam@bit_array:to_string(Data@1) of - {ok, String} -> - {ok, String}; - - {error, _} -> - {error, <<""/utf8>>} - end; - - {error, _} -> - {error, <<""/utf8>>} - end. - --file("src/gleam/dynamic/decode.gleam", 641). --spec decode_string(gleam@dynamic:dynamic_()) -> {binary(), - list(decode_error())}. -decode_string(Data) -> - run_dynamic_function(Data, <<"String"/utf8>>, fun dynamic_string/1). - --file("src/gleam/dynamic/decode.gleam", 991). --spec run_decoders( - gleam@dynamic:dynamic_(), - {CAP, list(decode_error())}, - list(decoder(CAP)) -) -> {CAP, list(decode_error())}. -run_decoders(Data, Failure, Decoders) -> - case Decoders of - [] -> - Failure; - - [Decoder | Decoders@1] -> - {_, Errors} = Layer = (erlang:element(2, Decoder))(Data), - case Errors of - [] -> - Layer; - - [_ | _] -> - run_decoders(Data, Failure, Decoders@1) - end - end. - --file("src/gleam/dynamic/decode.gleam", 978). -?DOC( - " Create a new decoder from several other decoders. Each of the inner\n" - " decoders is run in turn, and the value from the first to succeed is used.\n" - "\n" - " If no decoder succeeds then the errors from the first decoder are used.\n" - " If you wish for different errors then you may wish to use the\n" - " `collapse_errors` or `map_errors` functions.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.one_of(decode.string, or: [\n" - " decode.int |> decode.map(int.to_string),\n" - " decode.float |> decode.map(float.to_string),\n" - " ])\n" - " assert decode.run(dynamic.int(1000), decoder) == Ok(\"1000\")\n" - " ```\n" -). --spec one_of(decoder(CAK), list(decoder(CAK))) -> decoder(CAK). -one_of(First, Alternatives) -> - {decoder, - fun(Dynamic_data) -> - {_, Errors} = Layer = (erlang:element(2, First))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - run_decoders(Dynamic_data, Layer, Alternatives) - end - end}. - --file("src/gleam/dynamic/decode.gleam", 457). --spec path_segment_to_string(gleam@dynamic:dynamic_()) -> binary(). -path_segment_to_string(Key) -> - Decoder = one_of( - {decoder, fun decode_string/1}, - [begin - _pipe = {decoder, fun decode_int/1}, - map(_pipe, fun erlang:integer_to_binary/1) - end, - begin - _pipe@1 = {decoder, fun decode_float/1}, - map(_pipe@1, fun gleam_stdlib:float_to_string/1) - end] - ), - case run(Key, Decoder) of - {ok, Key@1} -> - Key@1; - - {error, _} -> - <<<<"<"/utf8, (gleam_stdlib:classify_dynamic(Key))/binary>>/binary, - ">"/utf8>> - end. - --file("src/gleam/dynamic/decode.gleam", 445). --spec push_path({BWR, list(decode_error())}, list(any())) -> {BWR, - list(decode_error())}. -push_path(Layer, Path) -> - Path@1 = gleam@list:map(Path, fun(Key) -> _pipe = Key, - _pipe@1 = gleam_stdlib:identity(_pipe), - path_segment_to_string(_pipe@1) end), - Errors = gleam@list:map( - erlang:element(2, Layer), - fun(Error) -> - {decode_error, - erlang:element(2, Error), - erlang:element(3, Error), - lists:append(Path@1, erlang:element(4, Error))} - end - ), - {erlang:element(1, Layer), Errors}. - --file("src/gleam/dynamic/decode.gleam", 779). -?DOC( - " A decoder that decodes lists where all elements are decoded with a given\n" - " decoder.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let result =\n" - " [1, 2, 3]\n" - " |> list.map(dynamic.int)\n" - " |> dynamic.list\n" - " |> decode.run(decode.list(of: decode.int))\n" - " assert result == Ok([1, 2, 3])\n" - " ```\n" -). --spec list(decoder(BYI)) -> decoder(list(BYI)). -list(Inner) -> - {decoder, - fun(Data) -> - gleam_stdlib:list( - Data, - erlang:element(2, Inner), - fun(P, K) -> push_path(P, [K]) end, - 0, - [] - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 409). --spec index( - list(BWF), - list(BWF), - fun((gleam@dynamic:dynamic_()) -> {BWI, list(decode_error())}), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_(), list(BWF)) -> {BWI, list(decode_error())}) -) -> {BWI, list(decode_error())}. -index(Path, Position, Inner, Data, Handle_miss) -> - case Path of - [] -> - _pipe = Data, - _pipe@1 = Inner(_pipe), - push_path(_pipe@1, lists:reverse(Position)); - - [Key | Path@1] -> - case gleam_stdlib:index(Data, Key) of - {ok, {some, Data@1}} -> - index(Path@1, [Key | Position], Inner, Data@1, Handle_miss); - - {ok, none} -> - Handle_miss(Data, [Key | Position]); - - {error, Kind} -> - {Default, _} = Inner(Data), - _pipe@2 = {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]}, - push_path(_pipe@2, lists:reverse(Position)) - end - end. - --file("src/gleam/dynamic/decode.gleam", 332). -?DOC( - " The same as [`field`](#field), except taking a path to the value rather\n" - " than a field name.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"data\"), dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ])\n" - " ])\n" - "\n" - " let decoder = {\n" - " use name <- decode.subfield([\"data\", \"name\"], decode.string)\n" - " use email <- decode.subfield([\"data\", \"email\"], decode.string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" -). --spec subfield(list(any()), decoder(BVQ), fun((BVQ) -> decoder(BVS))) -> decoder(BVS). -subfield(Field_path, Field_decoder, Next) -> - {decoder, - fun(Data) -> - {Out, Errors1} = index( - Field_path, - [], - erlang:element(2, Field_decoder), - Data, - fun(Data@1, Position) -> - {Default, _} = (erlang:element(2, Field_decoder))(Data@1), - _pipe = {Default, - [{decode_error, - <<"Field"/utf8>>, - <<"Nothing"/utf8>>, - []}]}, - push_path(_pipe, lists:reverse(Position)) - end - ), - {Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data), - {Out@1, lists:append(Errors1, Errors2)} - end}. - --file("src/gleam/dynamic/decode.gleam", 399). -?DOC( - " A decoder that decodes a value that is nested within other values. For\n" - " example, decoding a value that is within some deeply nested JSON objects.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.at([\"one\", \"two\"], decode.int)\n" - "\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.properties([\n" - " #(dynamic.string(\"two\"), dynamic.int(1000)),\n" - " ]),\n" - " ])\n" - "\n" - " assert decode.run(data, decoder) == Ok(1000)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert dynamic.nil()\n" - " |> decode.run(decode.optional(decode.int))\n" - " == Ok(option.None)\n" - " ```\n" -). --spec at(list(any()), decoder(BWC)) -> decoder(BWC). -at(Path, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(Data@1, Position) -> - {Default, _} = (erlang:element(2, Inner))(Data@1), - _pipe = {Default, - [{decode_error, - <<"Field"/utf8>>, - <<"Nothing"/utf8>>, - []}]}, - push_path(_pipe, lists:reverse(Position)) - end - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 489). -?DOC( - " Finalise a decoder having successfully extracted a value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ])\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.field(\"email\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" -). --spec success(BWW) -> decoder(BWW). -success(Data) -> - {decoder, fun(_) -> {Data, []} end}. - --file("src/gleam/dynamic/decode.gleam", 495). -?DOC(" Construct a decode error for some unexpected dynamic data.\n"). --spec decode_error(binary(), gleam@dynamic:dynamic_()) -> list(decode_error()). -decode_error(Expected, Found) -> - [{decode_error, Expected, gleam_stdlib:classify_dynamic(Found), []}]. - --file("src/gleam/dynamic/decode.gleam", 534). -?DOC( - " Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n" - " of the desired type, or returning errors. An error is returned if there is\n" - " no field for the specified key.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"email\"), dynamic.string(\"lucy@example.com\")),\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ])\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.field(\"email\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"lucy@example.com\"))\n" - " ```\n" - "\n" - " If you wish to decode a value that is more deeply nested within the dynamic\n" - " data, see [`subfield`](#subfield) and [`at`](#at).\n" - "\n" - " If you wish to return a default in the event that a field is not present,\n" - " see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at).\n" -). --spec field(any(), decoder(BXA), fun((BXA) -> decoder(BXC))) -> decoder(BXC). -field(Field_name, Field_decoder, Next) -> - subfield([Field_name], Field_decoder, Next). - --file("src/gleam/dynamic/decode.gleam", 567). -?DOC( - " Run a decoder on a field of a `Dynamic` value, decoding the value if it is\n" - " of the desired type, or returning errors. The given default value is\n" - " returned if there is no field for the specified key.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"name\"), dynamic.string(\"Lucy\")),\n" - " ])\n" - "\n" - " let decoder = {\n" - " use name <- decode.field(\"name\", string)\n" - " use email <- decode.optional_field(\"email\", \"n/a\", string)\n" - " decode.success(SignUp(name: name, email: email))\n" - " }\n" - "\n" - " let result = decode.run(data, decoder)\n" - " assert result == Ok(SignUp(name: \"Lucy\", email: \"n/a\"))\n" - " ```\n" -). --spec optional_field(any(), BXG, decoder(BXG), fun((BXG) -> decoder(BXI))) -> decoder(BXI). -optional_field(Key, Default, Field_decoder, Next) -> - {decoder, - fun(Data) -> - {Out, Errors1} = begin - _pipe = case gleam_stdlib:index(Data, Key) of - {ok, {some, Data@1}} -> - (erlang:element(2, Field_decoder))(Data@1); - - {ok, none} -> - {Default, []}; - - {error, Kind} -> - {Default, - [{decode_error, - Kind, - gleam_stdlib:classify_dynamic(Data), - []}]} - end, - push_path(_pipe, [Key]) - end, - {Out@1, Errors2} = (erlang:element(2, Next(Out)))(Data), - {Out@1, lists:append(Errors1, Errors2)} - end}. - --file("src/gleam/dynamic/decode.gleam", 607). -?DOC( - " A decoder that decodes a value that is nested within other values. For\n" - " example, decoding a value that is within some deeply nested JSON objects.\n" - "\n" - " This function will index into dictionaries with any key type, and if the key is\n" - " an int then it'll also index into Erlang tuples and JavaScript arrays, and\n" - " the first eight elements of Gleam lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.optionally_at([\"one\", \"two\"], 100, decode.int)\n" - "\n" - " let data = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.properties([])),\n" - " ])\n" - "\n" - " assert decode.run(data, decoder) == Ok(100)\n" - " ```\n" -). --spec optionally_at(list(any()), BXN, decoder(BXN)) -> decoder(BXN). -optionally_at(Path, Default, Inner) -> - {decoder, - fun(Data) -> - index( - Path, - [], - erlang:element(2, Inner), - Data, - fun(_, _) -> {Default, []} end - ) - end}. - --file("src/gleam/dynamic/decode.gleam", 668). --spec decode_bool(gleam@dynamic:dynamic_()) -> {boolean(), list(decode_error())}. -decode_bool(Data) -> - case gleam_stdlib:identity(true) =:= Data of - true -> - {true, []}; - - false -> - case gleam_stdlib:identity(false) =:= Data of - true -> - {false, []}; - - false -> - {false, decode_error(<<"Bool"/utf8>>, Data)} - end - end. - --file("src/gleam/dynamic/decode.gleam", 831). --spec fold_dict( - {gleam@dict:dict(BZB, BZC), list(decode_error())}, - gleam@dynamic:dynamic_(), - gleam@dynamic:dynamic_(), - fun((gleam@dynamic:dynamic_()) -> {BZB, list(decode_error())}), - fun((gleam@dynamic:dynamic_()) -> {BZC, list(decode_error())}) -) -> {gleam@dict:dict(BZB, BZC), list(decode_error())}. -fold_dict(Acc, Key, Value, Key_decoder, Value_decoder) -> - case Key_decoder(Key) of - {Key_decoded, []} -> - case Value_decoder(Value) of - {Value@1, []} -> - Dict = gleam@dict:insert( - erlang:element(1, Acc), - Key_decoded, - Value@1 - ), - {Dict, erlang:element(2, Acc)}; - - {_, Errors} -> - Key_identifier = path_segment_to_string(Key), - push_path({maps:new(), Errors}, [Key_identifier]) - end; - - {_, Errors@1} -> - push_path({maps:new(), Errors@1}, [<<"keys"/utf8>>]) - end. - --file("src/gleam/dynamic/decode.gleam", 811). -?DOC( - " A decoder that decodes dicts where all keys and values are decoded with\n" - " given decoders.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let values = dynamic.properties([\n" - " #(dynamic.string(\"one\"), dynamic.int(1)),\n" - " #(dynamic.string(\"two\"), dynamic.int(2)),\n" - " ])\n" - "\n" - " let result =\n" - " decode.run(values, decode.dict(decode.string, decode.int))\n" - " assert result == Ok(values)\n" - " ```\n" -). --spec dict(decoder(BYU), decoder(BYW)) -> decoder(gleam@dict:dict(BYU, BYW)). -dict(Key, Value) -> - {decoder, fun(Data) -> case gleam_stdlib:dict(Data) of - {error, _} -> - {maps:new(), decode_error(<<"Dict"/utf8>>, Data)}; - - {ok, Dict} -> - gleam@dict:fold( - Dict, - {maps:new(), []}, - fun(A, K, V) -> case erlang:element(2, A) of - [] -> - fold_dict( - A, - K, - V, - erlang:element(2, Key), - erlang:element(2, Value) - ); - - [_ | _] -> - A - end end - ) - end end}. - --file("src/gleam/dynamic/decode.gleam", 880). -?DOC( - " A decoder that decodes nullable values of a type decoded by with a given\n" - " decoder.\n" - "\n" - " This function can handle common representations of null on all runtimes, such as\n" - " `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on\n" - " JavaScript.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.int(100), decode.optional(decode.int))\n" - " assert result == Ok(option.Some(100))\n" - " ```\n" - "\n" - " ```gleam\n" - " let result = decode.run(dynamic.nil(), decode.optional(decode.int))\n" - " assert result == Ok(option.None)\n" - " ```\n" -). --spec optional(decoder(BZP)) -> decoder(gleam@option:option(BZP)). -optional(Inner) -> - {decoder, fun(Data) -> case gleam_stdlib:is_null(Data) of - true -> - {none, []}; - - false -> - {Data@1, Errors} = (erlang:element(2, Inner))(Data), - {{some, Data@1}, Errors} - end end}. - --file("src/gleam/dynamic/decode.gleam", 911). -?DOC(" Apply a transformation function to any errors returned by the decoder.\n"). --spec map_errors( - decoder(BZX), - fun((list(decode_error())) -> list(decode_error())) -) -> decoder(BZX). -map_errors(Decoder, Transformer) -> - {decoder, - fun(D) -> - {Data, Errors} = (erlang:element(2, Decoder))(D), - {Data, Transformer(Errors)} - end}. - --file("src/gleam/dynamic/decode.gleam", 935). -?DOC( - " Replace all errors produced by a decoder with one single error for a named\n" - " expected type.\n" - "\n" - " This function may be useful if you wish to simplify errors before\n" - " presenting them to a user, particularly when using the `one_of` function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let decoder = decode.string |> decode.collapse_errors(\"MyThing\")\n" - " let result = decode.run(dynamic.int(1000), decoder)\n" - " assert result == Error([DecodeError(\"MyThing\", \"Int\", [])])\n" - " ```\n" -). --spec collapse_errors(decoder(CAC), binary()) -> decoder(CAC). -collapse_errors(Decoder, Name) -> - {decoder, - fun(Dynamic_data) -> - {Data, Errors} = Layer = (erlang:element(2, Decoder))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - {Data, decode_error(Name, Dynamic_data)} - end - end}. - --file("src/gleam/dynamic/decode.gleam", 949). -?DOC( - " Create a new decoder based upon the value of a previous decoder.\n" - "\n" - " This may be useful to run one previous decoder to use in further decoding.\n" -). --spec then(decoder(CAF), fun((CAF) -> decoder(CAH))) -> decoder(CAH). -then(Decoder, Next) -> - {decoder, - fun(Dynamic_data) -> - {Data, Errors} = (erlang:element(2, Decoder))(Dynamic_data), - Decoder@1 = Next(Data), - {Data@1, _} = Layer = (erlang:element(2, Decoder@1))(Dynamic_data), - case Errors of - [] -> - Layer; - - [_ | _] -> - {Data@1, Errors} - end - end}. - --file("src/gleam/dynamic/decode.gleam", 1024). -?DOC( - " Define a decoder that always fails.\n" - "\n" - " The first parameter is a \"placeholder\" value, which is some default value that the\n" - " decoder uses internally in place of the value that would have been produced\n" - " if the decoder was successful. It doesn't matter what this value is, it is\n" - " never returned by the decoder or shown to the user, so pick some arbitrary\n" - " value. If it is an int you might pick `0`, if it is a list you might pick\n" - " `[]`.\n" - "\n" - " The second parameter is the name of the type that has failed to decode.\n" - "\n" - " ```gleam\n" - " decode.failure(User(name: \"\", score: 0, tags: []), expected: \"User\")\n" - " ```\n" -). --spec failure(CAU, binary()) -> decoder(CAU). -failure(Placeholder, Name) -> - {decoder, fun(D) -> {Placeholder, decode_error(Name, D)} end}. - --file("src/gleam/dynamic/decode.gleam", 1065). -?DOC( - " Create a decoder for a new data type from a decoding function.\n" - "\n" - " This function is used for new primitive types. For example, you might\n" - " define a decoder for Erlang's pid type.\n" - "\n" - " A default \"placeholder\" value is also required to make a decoder. When this\n" - " decoder is used as part of a larger decoder this placeholder value is used\n" - " so that the rest of the decoder can continue to run and\n" - " collect all decoding errors. It doesn't matter what this value is, it is\n" - " never returned by the decoder or shown to the user, so pick some arbitrary\n" - " value. If it is an int you might pick `0`, if it is a list you might pick\n" - " `[]`.\n" - "\n" - " If you were to make a decoder for the `Int` type (rather than using the\n" - " built-in `Int` decoder) you would define it like so:\n" - "\n" - " ```gleam\n" - " pub fn int_decoder() -> decode.Decoder(Int) {\n" - " let default = \"\"\n" - " decode.new_primitive_decoder(\"Int\", int_from_dynamic)\n" - " }\n" - "\n" - " @external(erlang, \"my_module\", \"int_from_dynamic\")\n" - " fn int_from_dynamic(data: Int) -> Result(Int, Int)\n" - " ```\n" - "\n" - " ```erlang\n" - " -module(my_module).\n" - " -export([int_from_dynamic/1]).\n" - "\n" - " int_from_dynamic(Data) ->\n" - " case is_integer(Data) of\n" - " true -> {ok, Data};\n" - " false -> {error, 0}\n" - " end.\n" - " ```\n" -). --spec new_primitive_decoder( - binary(), - fun((gleam@dynamic:dynamic_()) -> {ok, CAW} | {error, CAW}) -) -> decoder(CAW). -new_primitive_decoder(Name, Decoding_function) -> - {decoder, fun(D) -> case Decoding_function(D) of - {ok, T} -> - {T, []}; - - {error, Placeholder} -> - {Placeholder, - [{decode_error, - Name, - gleam_stdlib:classify_dynamic(D), - []}]} - end end}. - --file("src/gleam/dynamic/decode.gleam", 1102). -?DOC( - " Create a decoder that can refer to itself, useful for decoding deeply\n" - " nested data.\n" - "\n" - " Attempting to create a recursive decoder without this function could result\n" - " in an infinite loop. If you are using `field` or other `use`able functions\n" - " then you may not need to use this function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " type Nested {\n" - " Nested(List(Nested))\n" - " Value(String)\n" - " }\n" - "\n" - " fn nested_decoder() -> decode.Decoder(Nested) {\n" - " use <- decode.recursive\n" - " decode.one_of(decode.string |> decode.map(Value), [\n" - " decode.list(nested_decoder()) |> decode.map(Nested),\n" - " ])\n" - " }\n" - " ```\n" -). --spec recursive(fun(() -> decoder(CBA))) -> decoder(CBA). -recursive(Inner) -> - {decoder, - fun(Data) -> - Decoder = Inner(), - (erlang:element(2, Decoder))(Data) - end}. diff --git a/ui/javascript/gleam_stdlib/gleam@float.erl b/ui/javascript/gleam_stdlib/gleam@float.erl deleted file mode 100644 index e420d17..0000000 --- a/ui/javascript/gleam_stdlib/gleam@float.erl +++ /dev/null @@ -1,711 +0,0 @@ --module(gleam@float). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/float.gleam"). --export([parse/1, to_string/1, max/2, min/2, clamp/3, compare/2, absolute_value/1, loosely_compare/3, loosely_equals/3, ceiling/1, floor/1, negate/1, round/1, truncate/1, to_precision/2, power/2, square_root/1, sum/1, product/1, random/0, modulo/2, divide/2, add/2, multiply/2, subtract/2, logarithm/1, exponential/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Functions for working with floats.\n" - "\n" - " ## Float representation\n" - "\n" - " Floats are represented as 64 bit floating point numbers on both the Erlang\n" - " and JavaScript runtimes. The floating point behaviour is native to their\n" - " respective runtimes, so their exact behaviour will be slightly different on\n" - " the two runtimes.\n" - "\n" - " ### Infinity and NaN\n" - "\n" - " Under the JavaScript runtime, exceeding the maximum (or minimum)\n" - " representable value for a floating point value will result in Infinity (or\n" - " -Infinity). Should you try to divide two infinities you will get NaN as a\n" - " result.\n" - "\n" - " When running on BEAM, exceeding the maximum (or minimum) representable\n" - " value for a floating point value will raise an error.\n" - "\n" - " ## Division by zero\n" - "\n" - " Gleam runs on the Erlang virtual machine, which does not follow the IEEE\n" - " 754 standard for floating point arithmetic and does not have an `Infinity`\n" - " value. In Erlang division by zero results in a crash, however Gleam does\n" - " not have partial functions and operators in core so instead division by zero\n" - " returns zero, a behaviour taken from Pony, Coq, and Lean.\n" - "\n" - " This may seem unexpected at first, but it is no less mathematically valid\n" - " than crashing or returning a special value. Division by zero is undefined\n" - " in mathematics.\n" -). - --file("src/gleam/float.gleam", 49). -?DOC( - " Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was\n" - " not possible.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert parse(\"2.3\") == Ok(2.3)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert parse(\"ABC\") == Error(Nil)\n" - " ```\n" -). --spec parse(binary()) -> {ok, float()} | {error, nil}. -parse(String) -> - gleam_stdlib:parse_float(String). - --file("src/gleam/float.gleam", 61). -?DOC( - " Returns the string representation of the provided `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_string(2.3) == \"2.3\"\n" - " ```\n" -). --spec to_string(float()) -> binary(). -to_string(X) -> - gleam_stdlib:float_to_string(X). - --file("src/gleam/float.gleam", 192). -?DOC( - " Compares two `Float`s, returning the larger of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert max(2.0, 2.3) == 2.3\n" - " ```\n" -). --spec max(float(), float()) -> float(). -max(A, B) -> - case A > B of - true -> - A; - - false -> - B - end. - --file("src/gleam/float.gleam", 177). -?DOC( - " Compares two `Float`s, returning the smaller of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert min(2.0, 2.3) == 2.0\n" - " ```\n" -). --spec min(float(), float()) -> float(). -min(A, B) -> - case A < B of - true -> - A; - - false -> - B - end. - --file("src/gleam/float.gleam", 80). -?DOC( - " Restricts a float between two bounds.\n" - "\n" - " Note: If the `min` argument is larger than the `max` argument then they\n" - " will be swapped, so the minimum bound is always lower than the maximum\n" - " bound.\n" - "\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert clamp(1.2, min: 1.4, max: 1.6) == 1.4\n" - " ```\n" - "\n" - " ```gleam\n" - " assert clamp(1.2, min: 1.4, max: 0.6) == 1.2\n" - " ```\n" -). --spec clamp(float(), float(), float()) -> float(). -clamp(X, Min_bound, Max_bound) -> - case Min_bound >= Max_bound of - true -> - _pipe = X, - _pipe@1 = min(_pipe, Min_bound), - max(_pipe@1, Max_bound); - - false -> - _pipe@2 = X, - _pipe@3 = min(_pipe@2, Max_bound), - max(_pipe@3, Min_bound) - end. - --file("src/gleam/float.gleam", 100). -?DOC( - " Compares two `Float`s, returning an `Order`:\n" - " `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert compare(2.0, 2.3) == Lt\n" - " ```\n" - "\n" - " To handle\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems)\n" - " you may use [`loosely_compare`](#loosely_compare) instead.\n" -). --spec compare(float(), float()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - false -> - case A < B of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/float.gleam", 302). -?DOC( - " Returns the absolute value of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert absolute_value(-12.5) == 12.5\n" - " ```\n" - "\n" - " ```gleam\n" - " assert absolute_value(10.2) == 10.2\n" - " ```\n" -). --spec absolute_value(float()) -> float(). -absolute_value(X) -> - case X >= +0.0 of - true -> - X; - - false -> - +0.0 - X - end. - --file("src/gleam/float.gleam", 129). -?DOC( - " Compares two `Float`s within a tolerance, returning an `Order`:\n" - " `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n" - "\n" - " This function allows Float comparison while handling\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n" - "\n" - " Notice: For `Float`s the tolerance won't be exact:\n" - " `5.3 - 5.0` is not exactly `0.3`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert loosely_compare(5.0, with: 5.3, tolerating: 0.5) == Eq\n" - " ```\n" - "\n" - " If you want to check only for equality you may use\n" - " [`loosely_equals`](#loosely_equals) instead.\n" -). --spec loosely_compare(float(), float(), float()) -> gleam@order:order(). -loosely_compare(A, B, Tolerance) -> - Difference = absolute_value(A - B), - case Difference =< Tolerance of - true -> - eq; - - false -> - compare(A, B) - end. - --file("src/gleam/float.gleam", 160). -?DOC( - " Checks for equality of two `Float`s within a tolerance,\n" - " returning a `Bool`.\n" - "\n" - " This function allows Float comparison while handling\n" - " [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n" - "\n" - " Notice: For `Float`s the tolerance won't be exact:\n" - " `5.3 - 5.0` is not exactly `0.3`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert loosely_equals(5.0, with: 5.3, tolerating: 0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !loosely_equals(5.0, with: 5.1, tolerating: 0.1)\n" - " ```\n" -). --spec loosely_equals(float(), float(), float()) -> boolean(). -loosely_equals(A, B, Tolerance) -> - Difference = absolute_value(A - B), - Difference =< Tolerance. - --file("src/gleam/float.gleam", 209). -?DOC( - " Rounds the value to the next highest whole number as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert ceiling(2.3) == 3.0\n" - " ```\n" -). --spec ceiling(float()) -> float(). -ceiling(X) -> - math:ceil(X). - --file("src/gleam/float.gleam", 221). -?DOC( - " Rounds the value to the next lowest whole number as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert floor(2.3) == 2.0\n" - " ```\n" -). --spec floor(float()) -> float(). -floor(X) -> - math:floor(X). - --file("src/gleam/float.gleam", 376). -?DOC( - " Returns the negative of the value provided.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert negate(1.0) == -1.0\n" - " ```\n" -). --spec negate(float()) -> float(). -negate(X) -> - -1.0 * X. - --file("src/gleam/float.gleam", 236). -?DOC( - " Rounds the value to the nearest whole number as an `Int`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert round(2.3) == 2\n" - " ```\n" - "\n" - " ```gleam\n" - " assert round(2.5) == 3\n" - " ```\n" -). --spec round(float()) -> integer(). -round(X) -> - erlang:round(X). - --file("src/gleam/float.gleam", 256). -?DOC( - " Returns the value as an `Int`, truncating all decimal digits.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert truncate(2.4343434847383438) == 2\n" - " ```\n" -). --spec truncate(float()) -> integer(). -truncate(X) -> - erlang:trunc(X). - --file("src/gleam/float.gleam", 273). -?DOC( - " Converts the value to a given precision as a `Float`.\n" - " The precision is the number of allowed decimal places.\n" - " Negative precisions are allowed and force rounding\n" - " to the nearest tenth, hundredth, thousandth etc.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_precision(2.43434348473, 2) == 2.43\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_precision(547890.453444, -3) == 548000.0\n" - " ```\n" -). --spec to_precision(float(), integer()) -> float(). -to_precision(X, Precision) -> - case Precision =< 0 of - true -> - Factor = math:pow(10.0, erlang:float(- Precision)), - erlang:float(erlang:round(case Factor of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> X / Gleam@denominator - end)) * Factor; - - false -> - Factor@1 = math:pow(10.0, erlang:float(Precision)), - case Factor@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> erlang:float(erlang:round(X * Factor@1)) - / Gleam@denominator@1 - end - end. - --file("src/gleam/float.gleam", 334). -?DOC( - " Returns the result of the base being raised to the power of the\n" - " exponent, as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert power(2.0, -1.0) == Ok(0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert power(2.0, 2.0) == Ok(4.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert power(8.0, 1.5) == Ok(22.627416997969522)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 4.0 |> power(of: 2.0) == Ok(16.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert power(-1.0, 0.5) == Error(Nil)\n" - " ```\n" -). --spec power(float(), float()) -> {ok, float()} | {error, nil}. -power(Base, Exponent) -> - Fractional = (math:ceil(Exponent) - Exponent) > +0.0, - case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent - < +0.0)) of - true -> - {error, nil}; - - false -> - {ok, math:pow(Base, Exponent)} - end. - --file("src/gleam/float.gleam", 364). -?DOC( - " Returns the square root of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert square_root(4.0) == Ok(2.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert square_root(-16.0) == Error(Nil)\n" - " ```\n" -). --spec square_root(float()) -> {ok, float()} | {error, nil}. -square_root(X) -> - power(X, 0.5). - --file("src/gleam/float.gleam", 392). --spec sum_loop(list(float()), float()) -> float(). -sum_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - sum_loop(Rest, First + Initial); - - [] -> - Initial - end. - --file("src/gleam/float.gleam", 388). -?DOC( - " Sums a list of `Float`s.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert sum([1.0, 2.2, 3.3]) == 6.5\n" - " ```\n" -). --spec sum(list(float())) -> float(). -sum(Numbers) -> - sum_loop(Numbers, +0.0). - --file("src/gleam/float.gleam", 411). --spec product_loop(list(float()), float()) -> float(). -product_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - product_loop(Rest, First * Initial); - - [] -> - Initial - end. - --file("src/gleam/float.gleam", 407). -?DOC( - " Multiplies a list of `Float`s and returns the product.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert product([2.5, 3.2, 4.2]) == 33.6\n" - " ```\n" -). --spec product(list(float())) -> float(). -product(Numbers) -> - product_loop(Numbers, 1.0). - --file("src/gleam/float.gleam", 433). -?DOC( - " Generates a random float between the given zero (inclusive) and one\n" - " (exclusive).\n" - "\n" - " On Erlang this updates the random state in the process dictionary.\n" - " See: \n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " random()\n" - " // -> 0.646355926896028\n" - " ```\n" -). --spec random() -> float(). -random() -> - rand:uniform(). - --file("src/gleam/float.gleam", 460). -?DOC( - " Computes the modulo of a float division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " The computed value will always have the same sign as the `divisor`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert modulo(13.3, by: 3.3) == Ok(0.1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(-13.3, by: 3.3) == Ok(3.2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(13.3, by: -3.3) == Ok(-3.2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(-13.3, by: -3.3) == Ok(-0.1)\n" - " ```\n" -). --spec modulo(float(), float()) -> {ok, float()} | {error, nil}. -modulo(Dividend, Divisor) -> - case Divisor of - +0.0 -> - {error, nil}; - - _ -> - {ok, Dividend - (math:floor(case Divisor of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> Dividend / Gleam@denominator - end) * Divisor)} - end. - --file("src/gleam/float.gleam", 479). -?DOC( - " Returns division of the inputs as a `Result`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert divide(0.0, 1.0) == Ok(0.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert divide(1.0, 0.0) == Error(Nil)\n" - " ```\n" -). --spec divide(float(), float()) -> {ok, float()} | {error, nil}. -divide(A, B) -> - case B of - +0.0 -> - {error, nil}; - - B@1 -> - {ok, case B@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> A / Gleam@denominator - end} - end. - --file("src/gleam/float.gleam", 507). -?DOC( - " Adds two floats together.\n" - "\n" - " It's the function equivalent of the `+.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert add(1.0, 2.0) == 3.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " assert list.fold([1.0, 2.0, 3.0], 0.0, add) == 6.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3.0 |> add(2.0) == 5.0\n" - " ```\n" -). --spec add(float(), float()) -> float(). -add(A, B) -> - A + B. - --file("src/gleam/float.gleam", 532). -?DOC( - " Multiplies two floats together.\n" - "\n" - " It's the function equivalent of the `*.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert multiply(2.0, 4.0) == 8.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " assert list.fold([2.0, 3.0, 4.0], 1.0, multiply) == 24.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3.0 |> multiply(2.0) == 6.0\n" - " ```\n" -). --spec multiply(float(), float()) -> float(). -multiply(A, B) -> - A * B. - --file("src/gleam/float.gleam", 561). -?DOC( - " Subtracts one float from another.\n" - "\n" - " It's the function equivalent of the `-.` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert subtract(3.0, 1.0) == 2.0\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " assert list.fold([1.0, 2.0, 3.0], 10.0, subtract) == 4.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3.0 |> subtract(_, 2.0) == 1.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3.0 |> subtract(2.0, _) == -1.0\n" - " ```\n" -). --spec subtract(float(), float()) -> float(). -subtract(A, B) -> - A - B. - --file("src/gleam/float.gleam", 586). -?DOC( - " Returns the natural logarithm (base e) of the given `Float` as a `Result`. If the\n" - " input is less than or equal to 0, returns `Error(Nil)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert logarithm(1.0) == Ok(0.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert logarithm(2.718281828459045) == Ok(1.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert logarithm(0.0) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert logarithm(-1.0) == Error(Nil)\n" - " ```\n" -). --spec logarithm(float()) -> {ok, float()} | {error, nil}. -logarithm(X) -> - case X =< +0.0 of - true -> - {error, nil}; - - false -> - {ok, math:log(X)} - end. - --file("src/gleam/float.gleam", 621). -?DOC( - " Returns e (Euler's number) raised to the power of the given exponent, as\n" - " a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert exponential(0.0) == 1.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert exponential(1.0) == 2.718281828459045\n" - " ```\n" - "\n" - " ```gleam\n" - " assert exponential(-1.0) == 0.36787944117144233\n" - " ```\n" -). --spec exponential(float()) -> float(). -exponential(X) -> - math:exp(X). diff --git a/ui/javascript/gleam_stdlib/gleam@function.erl b/ui/javascript/gleam_stdlib/gleam@function.erl deleted file mode 100644 index 63fff58..0000000 --- a/ui/javascript/gleam_stdlib/gleam@function.erl +++ /dev/null @@ -1,18 +0,0 @@ --module(gleam@function). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/function.gleam"). --export([identity/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/function.gleam", 3). -?DOC(" Takes a single argument and always returns its input value.\n"). --spec identity(CLV) -> CLV. -identity(X) -> - X. diff --git a/ui/javascript/gleam_stdlib/gleam@int.erl b/ui/javascript/gleam_stdlib/gleam@int.erl deleted file mode 100644 index 3504942..0000000 --- a/ui/javascript/gleam_stdlib/gleam@int.erl +++ /dev/null @@ -1,972 +0,0 @@ --module(gleam@int). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/int.gleam"). --export([absolute_value/1, to_float/1, power/2, square_root/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, max/2, min/2, clamp/3, compare/2, is_even/1, is_odd/1, negate/1, sum/1, product/1, random/1, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2, range/4]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Functions for working with integers.\n" - "\n" - " ## Division by zero\n" - "\n" - " In Erlang division by zero results in a crash, however Gleam does not have\n" - " partial functions and operators in core so instead division by zero returns\n" - " zero, a behaviour taken from Pony, Coq, and Lean.\n" - "\n" - " This may seem unexpected at first, but it is no less mathematically valid\n" - " than crashing or returning a special value. Division by zero is undefined\n" - " in mathematics.\n" -). - --file("src/gleam/int.gleam", 28). -?DOC( - " Returns the absolute value of the input.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert absolute_value(-12) == 12\n" - " ```\n" - "\n" - " ```gleam\n" - " assert absolute_value(10) == 10\n" - " ```\n" -). --spec absolute_value(integer()) -> integer(). -absolute_value(X) -> - case X >= 0 of - true -> - X; - - false -> - X * -1 - end. - --file("src/gleam/int.gleam", 251). -?DOC( - " Takes an int and returns its value as a float.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_float(5) == 5.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_float(0) == 0.0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_float(-3) == -3.0\n" - " ```\n" -). --spec to_float(integer()) -> float(). -to_float(X) -> - erlang:float(X). - --file("src/gleam/int.gleam", 60). -?DOC( - " Returns the result of the base being raised to the power of the\n" - " exponent, as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert power(2, -1.0) == Ok(0.5)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert power(2, 2.0) == Ok(4.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert power(8, 1.5) == Ok(22.627416997969522)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 4 |> power(of: 2.0) == Ok(16.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert power(-1, 0.5) == Error(Nil)\n" - " ```\n" -). --spec power(integer(), float()) -> {ok, float()} | {error, nil}. -power(Base, Exponent) -> - _pipe = Base, - _pipe@1 = erlang:float(_pipe), - gleam@float:power(_pipe@1, Exponent). - --file("src/gleam/int.gleam", 78). -?DOC( - " Returns the square root of the input as a `Float`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert square_root(4) == Ok(2.0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert square_root(-16) == Error(Nil)\n" - " ```\n" -). --spec square_root(integer()) -> {ok, float()} | {error, nil}. -square_root(X) -> - _pipe = X, - _pipe@1 = erlang:float(_pipe), - gleam@float:square_root(_pipe@1). - --file("src/gleam/int.gleam", 98). -?DOC( - " Parses a given string as an int if possible.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert parse(\"2\") == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert parse(\"ABC\") == Error(Nil)\n" - " ```\n" -). --spec parse(binary()) -> {ok, integer()} | {error, nil}. -parse(String) -> - gleam_stdlib:parse_int(String). - --file("src/gleam/int.gleam", 125). -?DOC( - " Parses a given string as an int in a given base if possible.\n" - " Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert base_parse(\"10\", 2) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert base_parse(\"30\", 16) == Ok(48)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert base_parse(\"1C\", 36) == Ok(48)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert base_parse(\"48\", 1) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert base_parse(\"48\", 37) == Error(Nil)\n" - " ```\n" -). --spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}. -base_parse(String, Base) -> - case (Base >= 2) andalso (Base =< 36) of - true -> - gleam_stdlib:int_from_base_string(String, Base); - - false -> - {error, nil} - end. - --file("src/gleam/int.gleam", 146). -?DOC( - " Prints a given int to a string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_string(2) == \"2\"\n" - " ```\n" -). --spec to_string(integer()) -> binary(). -to_string(X) -> - erlang:integer_to_binary(X). - --file("src/gleam/int.gleam", 174). -?DOC( - " Prints a given int to a string using the base number provided.\n" - " Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n" - " For common bases (2, 8, 16, 36), use the `to_baseN` functions.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_base_string(2, 2) == Ok(\"10\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_base_string(48, 16) == Ok(\"30\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_base_string(48, 36) == Ok(\"1C\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_base_string(48, 1) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_base_string(48, 37) == Error(Nil)\n" - " ```\n" -). --spec to_base_string(integer(), integer()) -> {ok, binary()} | {error, nil}. -to_base_string(X, Base) -> - case (Base >= 2) andalso (Base =< 36) of - true -> - {ok, erlang:integer_to_binary(X, Base)}; - - false -> - {error, nil} - end. - --file("src/gleam/int.gleam", 193). -?DOC( - " Prints a given int to a string using base-2.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_base2(2) == \"10\"\n" - " ```\n" -). --spec to_base2(integer()) -> binary(). -to_base2(X) -> - erlang:integer_to_binary(X, 2). - --file("src/gleam/int.gleam", 205). -?DOC( - " Prints a given int to a string using base-8.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_base8(15) == \"17\"\n" - " ```\n" -). --spec to_base8(integer()) -> binary(). -to_base8(X) -> - erlang:integer_to_binary(X, 8). - --file("src/gleam/int.gleam", 217). -?DOC( - " Prints a given int to a string using base-16.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_base16(48) == \"30\"\n" - " ```\n" -). --spec to_base16(integer()) -> binary(). -to_base16(X) -> - erlang:integer_to_binary(X, 16). - --file("src/gleam/int.gleam", 229). -?DOC( - " Prints a given int to a string using base-36.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_base36(48) == \"1C\"\n" - " ```\n" -). --spec to_base36(integer()) -> binary(). -to_base36(X) -> - erlang:integer_to_binary(X, 36). - --file("src/gleam/int.gleam", 326). -?DOC( - " Compares two ints, returning the larger of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert max(2, 3) == 3\n" - " ```\n" -). --spec max(integer(), integer()) -> integer(). -max(A, B) -> - case A > B of - true -> - A; - - false -> - B - end. - --file("src/gleam/int.gleam", 311). -?DOC( - " Compares two ints, returning the smaller of the two.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert min(2, 3) == 2\n" - " ```\n" -). --spec min(integer(), integer()) -> integer(). -min(A, B) -> - case A < B of - true -> - A; - - false -> - B - end. - --file("src/gleam/int.gleam", 269). -?DOC( - " Restricts an int between two bounds.\n" - "\n" - " Note: If the `min` argument is larger than the `max` argument then they\n" - " will be swapped, so the minimum bound is always lower than the maximum\n" - " bound.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert clamp(40, min: 50, max: 60) == 50\n" - " ```\n" - "\n" - " ```gleam\n" - " assert clamp(40, min: 50, max: 30) == 40\n" - " ```\n" -). --spec clamp(integer(), integer(), integer()) -> integer(). -clamp(X, Min_bound, Max_bound) -> - case Min_bound >= Max_bound of - true -> - _pipe = X, - _pipe@1 = min(_pipe, Min_bound), - max(_pipe@1, Max_bound); - - false -> - _pipe@2 = X, - _pipe@3 = min(_pipe@2, Max_bound), - max(_pipe@3, Min_bound) - end. - --file("src/gleam/int.gleam", 292). -?DOC( - " Compares two ints, returning an order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert compare(2, 3) == Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " assert compare(4, 3) == Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " assert compare(3, 3) == Eq\n" - " ```\n" -). --spec compare(integer(), integer()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - false -> - case A < B of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/int.gleam", 345). -?DOC( - " Returns whether the value provided is even.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_even(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_even(3)\n" - " ```\n" -). --spec is_even(integer()) -> boolean(). -is_even(X) -> - (X rem 2) =:= 0. - --file("src/gleam/int.gleam", 361). -?DOC( - " Returns whether the value provided is odd.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_odd(3)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_odd(2)\n" - " ```\n" -). --spec is_odd(integer()) -> boolean(). -is_odd(X) -> - (X rem 2) /= 0. - --file("src/gleam/int.gleam", 373). -?DOC( - " Returns the negative of the value provided.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert negate(1) == -1\n" - " ```\n" -). --spec negate(integer()) -> integer(). -negate(X) -> - -1 * X. - --file("src/gleam/int.gleam", 389). --spec sum_loop(list(integer()), integer()) -> integer(). -sum_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - sum_loop(Rest, First + Initial); - - [] -> - Initial - end. - --file("src/gleam/int.gleam", 385). -?DOC( - " Sums a list of ints.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert sum([1, 2, 3]) == 6\n" - " ```\n" -). --spec sum(list(integer())) -> integer(). -sum(Numbers) -> - sum_loop(Numbers, 0). - --file("src/gleam/int.gleam", 408). --spec product_loop(list(integer()), integer()) -> integer(). -product_loop(Numbers, Initial) -> - case Numbers of - [First | Rest] -> - product_loop(Rest, First * Initial); - - [] -> - Initial - end. - --file("src/gleam/int.gleam", 404). -?DOC( - " Multiplies a list of ints and returns the product.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert product([2, 3, 4]) == 24\n" - " ```\n" -). --spec product(list(integer())) -> integer(). -product(Numbers) -> - product_loop(Numbers, 1). - --file("src/gleam/int.gleam", 436). -?DOC( - " Generates a random int between zero and the given maximum.\n" - "\n" - " The lower number is inclusive, the upper number is exclusive.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " random(10)\n" - " // -> 4\n" - " ```\n" - "\n" - " ```gleam\n" - " random(1)\n" - " // -> 0\n" - " ```\n" - "\n" - " ```gleam\n" - " random(-1)\n" - " // -> -1\n" - " ```\n" -). --spec random(integer()) -> integer(). -random(Max) -> - _pipe = (rand:uniform() * erlang:float(Max)), - _pipe@1 = math:floor(_pipe), - erlang:round(_pipe@1). - --file("src/gleam/int.gleam", 465). -?DOC( - " Performs a truncated integer division.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert divide(0, 1) == Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert divide(1, 0) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert divide(5, 2) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert divide(-99, 2) == Ok(-49)\n" - " ```\n" -). --spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}. -divide(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend div Gleam@denominator - end} - end. - --file("src/gleam/int.gleam", 510). -?DOC( - " Computes the remainder of an integer division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " Most of the time you will want to use the `%` operator instead of this\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert remainder(3, 2) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remainder(1, 0) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remainder(10, -1) == Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remainder(13, by: 3) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remainder(-13, by: 3) == Ok(-1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remainder(13, by: -3) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remainder(-13, by: -3) == Ok(-1)\n" - " ```\n" -). --spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}. -remainder(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end} - end. - --file("src/gleam/int.gleam", 551). -?DOC( - " Computes the modulo of an integer division of inputs as a `Result`.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " Note that this is different from `int.remainder` and `%` in that the\n" - " computed value will always have the same sign as the `divisor`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert modulo(3, 2) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(1, 0) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(10, -1) == Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(13, by: 3) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(-13, by: 3) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert modulo(13, by: -3) == Ok(-2)\n" - " ```\n" -). --spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}. -modulo(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - _ -> - Remainder = case Divisor of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end, - case (Remainder * Divisor) < 0 of - true -> - {ok, Remainder + Divisor}; - - false -> - {ok, Remainder} - end - end. - --file("src/gleam/int.gleam", 591). -?DOC( - " Performs a *floored* integer division, which means that the result will\n" - " always be rounded towards negative infinity.\n" - "\n" - " If you want to perform truncated integer division (rounding towards zero),\n" - " use `int.divide()` or the `/` operator instead.\n" - "\n" - " Returns division of the inputs as a `Result`: If the given divisor equals\n" - " `0`, this function returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert floor_divide(1, 0) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert floor_divide(5, 2) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert floor_divide(6, -4) == Ok(-2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert floor_divide(-99, 2) == Ok(-50)\n" - " ```\n" -). --spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}. -floor_divide(Dividend, Divisor) -> - case Divisor of - 0 -> - {error, nil}; - - Divisor@1 -> - case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of - 0 -> 0; - Gleam@denominator -> Dividend rem Gleam@denominator - end) /= 0) of - true -> - {ok, (case Divisor@1 of - 0 -> 0; - Gleam@denominator@1 -> Dividend div Gleam@denominator@1 - end) - 1}; - - false -> - {ok, case Divisor@1 of - 0 -> 0; - Gleam@denominator@2 -> Dividend div Gleam@denominator@2 - end} - end - end. - --file("src/gleam/int.gleam", 622). -?DOC( - " Adds two integers together.\n" - "\n" - " It's the function equivalent of the `+` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert add(1, 2) == 3\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - " assert list.fold([1, 2, 3], 0, add) == 6\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3 |> add(2) == 5\n" - " ```\n" -). --spec add(integer(), integer()) -> integer(). -add(A, B) -> - A + B. - --file("src/gleam/int.gleam", 647). -?DOC( - " Multiplies two integers together.\n" - "\n" - " It's the function equivalent of the `*` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert multiply(2, 4) == 8\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " assert list.fold([2, 3, 4], 1, multiply) == 24\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3 |> multiply(2) == 6\n" - " ```\n" -). --spec multiply(integer(), integer()) -> integer(). -multiply(A, B) -> - A * B. - --file("src/gleam/int.gleam", 676). -?DOC( - " Subtracts one int from another.\n" - "\n" - " It's the function equivalent of the `-` operator.\n" - " This function is useful in higher order functions or pipes.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert subtract(3, 1) == 2\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/list\n" - "\n" - " assert list.fold([1, 2, 3], 10, subtract) == 4\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3 |> subtract(2) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert 3 |> subtract(2, _) == -1\n" - " ```\n" -). --spec subtract(integer(), integer()) -> integer(). -subtract(A, B) -> - A - B. - --file("src/gleam/int.gleam", 695). -?DOC( - " Calculates the bitwise AND of its arguments.\n" - "\n" - " Most the time you should use the bit array syntaxes instead of manipulating\n" - " bits as ints with bitwise functions.\n" - "\n" - " ## Target specific behaviour\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints. If you need to avoid the\n" - " overhead of big-ints on JavaScript use bit arrays or another package that\n" - " provides faster bitwise operations.\n" -). --spec bitwise_and(integer(), integer()) -> integer(). -bitwise_and(X, Y) -> - erlang:'band'(X, Y). - --file("src/gleam/int.gleam", 712). -?DOC( - " Calculates the bitwise NOT of its argument.\n" - "\n" - " Most the time you should use the bit array syntaxes instead of manipulating\n" - " bits as ints with bitwise functions.\n" - "\n" - " ## Target specific behaviour\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints. If you need to avoid the\n" - " overhead of big-ints on JavaScript use bit arrays or another package that\n" - " provides faster bitwise operations.\n" -). --spec bitwise_not(integer()) -> integer(). -bitwise_not(X) -> - erlang:'bnot'(X). - --file("src/gleam/int.gleam", 729). -?DOC( - " Calculates the bitwise OR of its arguments.\n" - "\n" - " Most the time you should use the bit array syntaxes instead of manipulating\n" - " bits as ints with bitwise functions.\n" - "\n" - " ## Target specific behaviour\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints. If you need to avoid the\n" - " overhead of big-ints on JavaScript use bit arrays or another package that\n" - " provides faster bitwise operations.\n" -). --spec bitwise_or(integer(), integer()) -> integer(). -bitwise_or(X, Y) -> - erlang:'bor'(X, Y). - --file("src/gleam/int.gleam", 746). -?DOC( - " Calculates the bitwise XOR of its arguments.\n" - "\n" - " Most the time you should use the bit array syntaxes instead of manipulating\n" - " bits as ints with bitwise functions.\n" - "\n" - " ## Target specific behaviour\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints. If you need to avoid the\n" - " overhead of big-ints on JavaScript use bit arrays or another package that\n" - " provides faster bitwise operations.\n" -). --spec bitwise_exclusive_or(integer(), integer()) -> integer(). -bitwise_exclusive_or(X, Y) -> - erlang:'bxor'(X, Y). - --file("src/gleam/int.gleam", 763). -?DOC( - " Calculates the result of an arithmetic left bitshift.\n" - "\n" - " Most the time you should use the bit array syntaxes instead of manipulating\n" - " bits as ints with bitwise functions.\n" - "\n" - " ## Target specific behaviour\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints. If you need to avoid the\n" - " overhead of big-ints on JavaScript use bit arrays or another package that\n" - " provides faster bitwise operations.\n" -). --spec bitwise_shift_left(integer(), integer()) -> integer(). -bitwise_shift_left(X, Y) -> - erlang:'bsl'(X, Y). - --file("src/gleam/int.gleam", 780). -?DOC( - " Calculates the result of an arithmetic right bitshift.\n" - "\n" - " Most the time you should use the bit array syntaxes instead of manipulating\n" - " bits as ints with bitwise functions.\n" - "\n" - " ## Target specific behaviour\n" - "\n" - " The exact behaviour of this function depends on the target platform.\n" - " On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n" - " is equivalent to bitwise operations on big-ints. If you need to avoid the\n" - " overhead of big-ints on JavaScript use bit arrays or another package that\n" - " provides faster bitwise operations.\n" -). --spec bitwise_shift_right(integer(), integer()) -> integer(). -bitwise_shift_right(X, Y) -> - erlang:'bsr'(X, Y). - --file("src/gleam/int.gleam", 813). --spec range_loop( - integer(), - integer(), - integer(), - CM, - fun((CM, integer()) -> CM) -) -> CM. -range_loop(Current, Stop, Increment, Acc, Reducer) -> - case Current =:= Stop of - true -> - Acc; - - false -> - Acc@1 = Reducer(Acc, Current), - Current@1 = Current + Increment, - range_loop(Current@1, Stop, Increment, Acc@1, Reducer) - end. - --file("src/gleam/int.gleam", 800). -?DOC( - " Run a function for each int between ints `from` and `to`.\n" - "\n" - " `from` is inclusive, and `to` is exclusive.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert\n" - " range(from: 0, to: 3, with: \"\", run: fn(acc, i) {\n" - " acc <> to_string(i)\n" - " })\n" - " == \"012\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert range(from: 1, to: -2, with: [], run: list.prepend) == [-1, 0, 1]\n" - " ```\n" -). --spec range(integer(), integer(), CL, fun((CL, integer()) -> CL)) -> CL. -range(Start, Stop, Acc, Reducer) -> - Increment = case Start < Stop of - true -> - 1; - - false -> - -1 - end, - range_loop(Start, Stop, Increment, Acc, Reducer). diff --git a/ui/javascript/gleam_stdlib/gleam@io.erl b/ui/javascript/gleam_stdlib/gleam@io.erl deleted file mode 100644 index 4b68e26..0000000 --- a/ui/javascript/gleam_stdlib/gleam@io.erl +++ /dev/null @@ -1,76 +0,0 @@ --module(gleam@io). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/io.gleam"). --export([print/1, print_error/1, println/1, println_error/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/io.gleam", 14). -?DOC( - " Writes a string to standard output (stdout).\n" - "\n" - " If you want your output to be printed on its own line see `println`.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert io.print(\"Hi mum\") == Nil\n" - " // Hi mum\n" - " ```\n" -). --spec print(binary()) -> nil. -print(String) -> - gleam_stdlib:print(String). - --file("src/gleam/io.gleam", 29). -?DOC( - " Writes a string to standard error (stderr).\n" - "\n" - " If you want your output to be printed on its own line see `println_error`.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert io.print_error(\"Hi pop\") == Nil\n" - " // Hi pop\n" - " ```\n" -). --spec print_error(binary()) -> nil. -print_error(String) -> - gleam_stdlib:print_error(String). - --file("src/gleam/io.gleam", 42). -?DOC( - " Writes a string to standard output (stdout), appending a newline to the end.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert io.println(\"Hi mum\") == Nil\n" - " // Hi mum\n" - " ```\n" -). --spec println(binary()) -> nil. -println(String) -> - gleam_stdlib:println(String). - --file("src/gleam/io.gleam", 55). -?DOC( - " Writes a string to standard error (stderr), appending a newline to the end.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " assert io.println_error(\"Hi pop\") == Nil\n" - " // Hi pop\n" - " ```\n" -). --spec println_error(binary()) -> nil. -println_error(String) -> - gleam_stdlib:println_error(String). diff --git a/ui/javascript/gleam_stdlib/gleam@list.erl b/ui/javascript/gleam_stdlib/gleam@list.erl deleted file mode 100644 index 510e22c..0000000 --- a/ui/javascript/gleam_stdlib/gleam@list.erl +++ /dev/null @@ -1,2716 +0,0 @@ --module(gleam@list). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/list.gleam"). --export([length/1, count/2, reverse/1, is_empty/1, contains/2, first/1, rest/1, group/2, filter/2, filter_map/2, map/2, map2/3, map_fold/3, index_map/2, try_map/2, drop/2, take/2, new/0, wrap/1, append/2, prepend/2, flatten/1, flat_map/2, fold/3, fold_right/3, index_fold/3, try_fold/3, fold_until/3, find/2, find_map/2, all/2, any/2, zip/2, strict_zip/2, unzip/1, intersperse/2, unique/1, sort/2, repeat/2, split/2, split_while/2, key_find/2, key_filter/2, key_pop/2, key_set/3, each/2, try_each/2, partition/2, permutations/1, window/2, window_by_2/1, drop_while/2, take_while/2, chunk/2, sized_chunk/2, reduce/2, scan/3, last/1, combinations/2, combination_pairs/1, transpose/1, interleave/1, shuffle/1, max/2, sample/2]). --export_type([continue_or_stop/1, sorting/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Lists are an ordered sequence of elements and are one of the most common\n" - " data types in Gleam.\n" - "\n" - " New elements can be added and removed from the front of a list in\n" - " constant time, while adding and removing from the end requires traversing\n" - " and copying the whole list, so keep this in mind when designing your\n" - " programs.\n" - "\n" - " There is a dedicated syntax for prefixing to a list:\n" - "\n" - " ```gleam\n" - " let new_list = [1, 2, ..existing_list]\n" - " ```\n" - "\n" - " And a matching syntax for getting the first elements of a list:\n" - "\n" - " ```gleam\n" - " case list {\n" - " [first_element, ..rest] -> first_element\n" - " _ -> \"this pattern matches when the list is empty\"\n" - " }\n" - " ```\n" - "\n" -). - --type continue_or_stop(AAE) :: {continue, AAE} | {stop, AAE}. - --type sorting() :: ascending | descending. - --file("src/gleam/list.gleam", 57). --spec length_loop(list(any()), integer()) -> integer(). -length_loop(List, Count) -> - case List of - [_ | List@1] -> - length_loop(List@1, Count + 1); - - [] -> - Count - end. - --file("src/gleam/list.gleam", 53). -?DOC( - " Counts the number of elements in a given list.\n" - "\n" - " This function has to traverse the list to determine the number of elements,\n" - " so it runs in linear time.\n" - "\n" - " This function is natively implemented by the virtual machine and is highly\n" - " optimised.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert length([]) == 0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert length([1]) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert length([1, 2]) == 2\n" - " ```\n" -). --spec length(list(any())) -> integer(). -length(List) -> - erlang:length(List). - --file("src/gleam/list.gleam", 87). --spec count_loop(list(AAL), fun((AAL) -> boolean()), integer()) -> integer(). -count_loop(List, Predicate, Acc) -> - case List of - [] -> - Acc; - - [First | Rest] -> - case Predicate(First) of - true -> - count_loop(Rest, Predicate, Acc + 1); - - false -> - count_loop(Rest, Predicate, Acc) - end - end. - --file("src/gleam/list.gleam", 83). -?DOC( - " Counts the number of elements in a given list satisfying a given predicate.\n" - "\n" - " This function has to traverse the list to determine the number of elements,\n" - " so it runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert count([], fn(a) { a > 0 }) == 0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert count([1], fn(a) { a > 0 }) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert count([1, 2, 3], int.is_odd) == 2\n" - " ```\n" -). --spec count(list(AAJ), fun((AAJ) -> boolean())) -> integer(). -count(List, Predicate) -> - count_loop(List, Predicate, 0). - --file("src/gleam/list.gleam", 122). -?DOC( - " Creates a new list from a given list containing the same elements but in the\n" - " opposite order.\n" - "\n" - " This function has to traverse the list to create the new reversed list, so\n" - " it runs in linear time.\n" - "\n" - " This function is natively implemented by the virtual machine and is highly\n" - " optimised.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert reverse([]) == []\n" - " ```\n" - "\n" - " ```gleam\n" - " assert reverse([1]) == [1]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert reverse([1, 2]) == [2, 1]\n" - " ```\n" -). --spec reverse(list(AAN)) -> list(AAN). -reverse(List) -> - lists:reverse(List). - --file("src/gleam/list.gleam", 156). -?DOC( - " Determines whether or not the list is empty.\n" - "\n" - " This function runs in constant time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_empty([])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_empty([1])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_empty([1, 1])\n" - " ```\n" -). --spec is_empty(list(any())) -> boolean(). -is_empty(List) -> - List =:= []. - --file("src/gleam/list.gleam", 187). -?DOC( - " Determines whether or not a given element exists within a given list.\n" - "\n" - " This function traverses the list to find the element, so it runs in linear\n" - " time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !contains([], any: 0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert [0] |> contains(any: 0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !contains([1], any: 0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !contains([1, 1], any: 0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert [1, 0] |> contains(any: 0)\n" - " ```\n" -). --spec contains(list(AAW), AAW) -> boolean(). -contains(List, Elem) -> - case List of - [] -> - false; - - [First | _] when First =:= Elem -> - true; - - [_ | Rest] -> - contains(Rest, Elem) - end. - --file("src/gleam/list.gleam", 211). -?DOC( - " Gets the first element from the start of the list, if there is one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert first([]) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert first([0]) == Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert first([1, 2]) == Ok(1)\n" - " ```\n" -). --spec first(list(AAY)) -> {ok, AAY} | {error, nil}. -first(List) -> - case List of - [] -> - {error, nil}; - - [First | _] -> - {ok, First} - end. - --file("src/gleam/list.gleam", 237). -?DOC( - " Returns the list minus the first element. If the list is empty, `Error(Nil)` is\n" - " returned.\n" - "\n" - " This function runs in constant time and does not make a copy of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert rest([]) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert rest([0]) == Ok([])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert rest([1, 2]) == Ok([2])\n" - " ```\n" -). --spec rest(list(ABC)) -> {ok, list(ABC)} | {error, nil}. -rest(List) -> - case List of - [] -> - {error, nil}; - - [_ | Rest] -> - {ok, Rest} - end. - --file("src/gleam/list.gleam", 276). -?DOC( - " Groups the elements from the given list by the given key function.\n" - "\n" - " Does not preserve the initial value order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/dict\n" - "\n" - " assert\n" - " [Ok(3), Error(\"Wrong\"), Ok(200), Ok(73)]\n" - " |> group(by: fn(i) {\n" - " case i {\n" - " Ok(_) -> \"Successful\"\n" - " Error(_) -> \"Failed\"\n" - " }\n" - " })\n" - " |> dict.to_list\n" - " == [\n" - " #(\"Failed\", [Error(\"Wrong\")]),\n" - " #(\"Successful\", [Ok(73), Ok(200), Ok(3)])\n" - " ]\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/dict\n" - "\n" - " assert group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 })\n" - " |> dict.to_list\n" - " == [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])]\n" - " ```\n" -). --spec group(list(ABH), fun((ABH) -> ABJ)) -> gleam@dict:dict(ABJ, list(ABH)). -group(List, Key) -> - gleam@dict:group(Key, List). - --file("src/gleam/list.gleam", 297). --spec filter_loop(list(ABQ), fun((ABQ) -> boolean()), list(ABQ)) -> list(ABQ). -filter_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - New_acc = case Fun(First) of - true -> - [First | Acc]; - - false -> - Acc - end, - filter_loop(Rest, Fun, New_acc) - end. - --file("src/gleam/list.gleam", 293). -?DOC( - " Returns a new list containing only the elements from the first list for\n" - " which the given functions returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert filter([2, 4, 6, 1], fn(x) { x > 2 }) == [4, 6]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert filter([2, 4, 6, 1], fn(x) { x > 6 }) == []\n" - " ```\n" -). --spec filter(list(ABN), fun((ABN) -> boolean())) -> list(ABN). -filter(List, Predicate) -> - filter_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 327). --spec filter_map_loop( - list(ACB), - fun((ACB) -> {ok, ACD} | {error, any()}), - list(ACD) -) -> list(ACD). -filter_map_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - New_acc = case Fun(First) of - {ok, First@1} -> - [First@1 | Acc]; - - {error, _} -> - Acc - end, - filter_map_loop(Rest, Fun, New_acc) - end. - --file("src/gleam/list.gleam", 323). -?DOC( - " Returns a new list containing only the elements from the first list for\n" - " which the given functions returns `Ok(_)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert filter_map([2, 4, 6, 1], Error) == []\n" - " ```\n" - "\n" - " ```gleam\n" - " assert filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) == [3, 5, 7, 2]\n" - " ```\n" -). --spec filter_map(list(ABU), fun((ABU) -> {ok, ABW} | {error, any()})) -> list(ABW). -filter_map(List, Fun) -> - filter_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 356). --spec map_loop(list(ACN), fun((ACN) -> ACP), list(ACP)) -> list(ACP). -map_loop(List, Fun, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - map_loop(Rest, Fun, [Fun(First) | Acc]) - end. - --file("src/gleam/list.gleam", 352). -?DOC( - " Returns a new list containing the results of applying the supplied function to each element.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert map([2, 4, 6], fn(x) { x * 2 }) == [4, 8, 12]\n" - " ```\n" -). --spec map(list(ACJ), fun((ACJ) -> ACL)) -> list(ACL). -map(List, Fun) -> - map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 382). --spec map2_loop(list(ACY), list(ADA), fun((ACY, ADA) -> ADC), list(ADC)) -> list(ADC). -map2_loop(List1, List2, Fun, Acc) -> - case {List1, List2} of - {[], _} -> - lists:reverse(Acc); - - {_, []} -> - lists:reverse(Acc); - - {[A | As_], [B | Bs]} -> - map2_loop(As_, Bs, Fun, [Fun(A, B) | Acc]) - end. - --file("src/gleam/list.gleam", 378). -?DOC( - " Combines two lists into a single list using the given function.\n" - "\n" - " If a list is longer than the other, the extra elements are dropped.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) == [5, 7, 9]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert map2([1, 2], [\"a\", \"b\", \"c\"], fn(i, x) { #(i, x) })\n" - " == [#(1, \"a\"), #(2, \"b\")]\n" - " ```\n" -). --spec map2(list(ACS), list(ACU), fun((ACS, ACU) -> ACW)) -> list(ACW). -map2(List1, List2, Fun) -> - map2_loop(List1, List2, Fun, []). - --file("src/gleam/list.gleam", 416). --spec map_fold_loop(list(ADK), fun((ADM, ADK) -> {ADM, ADN}), ADM, list(ADN)) -> {ADM, - list(ADN)}. -map_fold_loop(List, Fun, Acc, List_acc) -> - case List of - [] -> - {Acc, lists:reverse(List_acc)}; - - [First | Rest] -> - {Acc@1, First@1} = Fun(Acc, First), - map_fold_loop(Rest, Fun, Acc@1, [First@1 | List_acc]) - end. - --file("src/gleam/list.gleam", 408). -?DOC( - " Similar to `map` but also lets you pass around an accumulated value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert\n" - " map_fold(\n" - " over: [1, 2, 3],\n" - " from: 100,\n" - " with: fn(memo, i) { #(memo + i, i * 2) }\n" - " )\n" - " == #(106, [2, 4, 6])\n" - " ```\n" -). --spec map_fold(list(ADF), ADH, fun((ADH, ADF) -> {ADH, ADI})) -> {ADH, - list(ADI)}. -map_fold(List, Initial, Fun) -> - map_fold_loop(List, Fun, Initial, []). - --file("src/gleam/list.gleam", 447). --spec index_map_loop( - list(ADU), - fun((ADU, integer()) -> ADW), - integer(), - list(ADW) -) -> list(ADW). -index_map_loop(List, Fun, Index, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - Acc@1 = [Fun(First, Index) | Acc], - index_map_loop(Rest, Fun, Index + 1, Acc@1) - end. - --file("src/gleam/list.gleam", 443). -?DOC( - " Similar to `map`, but the supplied function will also be passed the index\n" - " of the element being mapped as an additional argument.\n" - "\n" - " The index starts at 0, so the first element is 0, the second is 1, and so\n" - " on.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert index_map([\"a\", \"b\"], fn(x, i) { #(i, x) }) == [#(0, \"a\"), #(1, \"b\")]\n" - " ```\n" -). --spec index_map(list(ADQ), fun((ADQ, integer()) -> ADS)) -> list(ADS). -index_map(List, Fun) -> - index_map_loop(List, Fun, 0, []). - --file("src/gleam/list.gleam", 497). --spec try_map_loop(list(AEI), fun((AEI) -> {ok, AEK} | {error, AEL}), list(AEK)) -> {ok, - list(AEK)} | - {error, AEL}. -try_map_loop(List, Fun, Acc) -> - case List of - [] -> - {ok, lists:reverse(Acc)}; - - [First | Rest] -> - case Fun(First) of - {ok, First@1} -> - try_map_loop(Rest, Fun, [First@1 | Acc]); - - {error, Error} -> - {error, Error} - end - end. - --file("src/gleam/list.gleam", 490). -?DOC( - " Takes a function that returns a `Result` and applies it to each element in a\n" - " given list in turn.\n" - "\n" - " If the function returns `Ok(new_value)` for all elements in the list then a\n" - " list of the new values is returned.\n" - "\n" - " If the function returns `Error(reason)` for any of the elements then it is\n" - " returned immediately. None of the elements in the list are processed after\n" - " one returns an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert try_map([1, 2, 3], fn(x) { Ok(x + 2) }) == Ok([3, 4, 5])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert try_map([1, 2, 3], fn(_) { Error(0) }) == Error(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert try_map([[1], [2, 3]], first) == Ok([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert try_map([[1], [], [2]], first) == Error(Nil)\n" - " ```\n" -). --spec try_map(list(ADZ), fun((ADZ) -> {ok, AEB} | {error, AEC})) -> {ok, - list(AEB)} | - {error, AEC}. -try_map(List, Fun) -> - try_map_loop(List, Fun, []). - --file("src/gleam/list.gleam", 530). -?DOC( - " Returns a list that is the given list with up to the given number of\n" - " elements removed from the front of the list.\n" - "\n" - " If the list has less than the number of elements an empty list is\n" - " returned.\n" - "\n" - " This function runs in linear time but does not copy the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert drop([1, 2, 3, 4], 2) == [3, 4]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert drop([1, 2, 3, 4], 9) == []\n" - " ```\n" -). --spec drop(list(AES), integer()) -> list(AES). -drop(List, N) -> - case N =< 0 of - true -> - List; - - false -> - case List of - [] -> - []; - - [_ | Rest] -> - drop(Rest, N - 1) - end - end. - --file("src/gleam/list.gleam", 563). --spec take_loop(list(AEY), integer(), list(AEY)) -> list(AEY). -take_loop(List, N, Acc) -> - case N =< 0 of - true -> - lists:reverse(Acc); - - false -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - take_loop(Rest, N - 1, [First | Acc]) - end - end. - --file("src/gleam/list.gleam", 559). -?DOC( - " Returns a list containing the first given number of elements from the given\n" - " list.\n" - "\n" - " If the list has less than the number of elements then the full list is\n" - " returned.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert take([1, 2, 3, 4], 2) == [1, 2]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert take([1, 2, 3, 4], 9) == [1, 2, 3, 4]\n" - " ```\n" -). --spec take(list(AEV), integer()) -> list(AEV). -take(List, N) -> - take_loop(List, N, []). - --file("src/gleam/list.gleam", 582). -?DOC( - " Returns a new empty list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() == []\n" - " ```\n" -). --spec new() -> list(any()). -new() -> - []. - --file("src/gleam/list.gleam", 603). -?DOC( - " Returns the given item wrapped in a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert wrap(1) == [1]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert wrap([\"a\", \"b\", \"c\"]) == [[\"a\", \"b\", \"c\"]]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert wrap([[]]) == [[[]]]\n" - " ```\n" -). --spec wrap(AFE) -> list(AFE). -wrap(Item) -> - [Item]. - --file("src/gleam/list.gleam", 623). --spec append_loop(list(AFK), list(AFK)) -> list(AFK). -append_loop(First, Second) -> - case First of - [] -> - Second; - - [First@1 | Rest] -> - append_loop(Rest, [First@1 | Second]) - end. - --file("src/gleam/list.gleam", 619). -?DOC( - " Joins one list onto the end of another.\n" - "\n" - " This function runs in linear time, and it traverses and copies the first\n" - " list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert append([1, 2], [3]) == [1, 2, 3]\n" - " ```\n" -). --spec append(list(AFG), list(AFG)) -> list(AFG). -append(First, Second) -> - lists:append(First, Second). - --file("src/gleam/list.gleam", 643). -?DOC( - " Prefixes an item to a list. This can also be done using the dedicated\n" - " syntax instead.\n" - "\n" - " ```gleam\n" - " let existing_list = [2, 3, 4]\n" - " assert [1, ..existing_list] == [1, 2, 3, 4]\n" - " ```\n" - "\n" - " ```gleam\n" - " let existing_list = [2, 3, 4]\n" - " assert prepend(to: existing_list, this: 1) == [1, 2, 3, 4]\n" - " ```\n" -). --spec prepend(list(AFO), AFO) -> list(AFO). -prepend(List, Item) -> - [Item | List]. - --file("src/gleam/list.gleam", 663). --spec flatten_loop(list(list(AFV)), list(AFV)) -> list(AFV). -flatten_loop(Lists, Acc) -> - case Lists of - [] -> - lists:reverse(Acc); - - [List | Further_lists] -> - flatten_loop(Further_lists, lists:reverse(List, Acc)) - end. - --file("src/gleam/list.gleam", 659). -?DOC( - " Joins a list of lists into a single list.\n" - "\n" - " This function traverses all elements twice on the JavaScript target.\n" - " This function traverses all elements once on the Erlang target.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert flatten([[1], [2, 3], []]) == [1, 2, 3]\n" - " ```\n" -). --spec flatten(list(list(AFR))) -> list(AFR). -flatten(Lists) -> - lists:append(Lists). - --file("src/gleam/list.gleam", 679). -?DOC( - " Maps the list with the given function into a list of lists, and then flattens it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert flat_map([2, 4, 6], fn(x) { [x, x + 1] }) == [2, 3, 4, 5, 6, 7]\n" - " ```\n" -). --spec flat_map(list(AGA), fun((AGA) -> list(AGC))) -> list(AGC). -flat_map(List, Fun) -> - lists:append(map(List, Fun)). - --file("src/gleam/list.gleam", 691). -?DOC( - " Reduces a list of elements into a single value by calling a given function\n" - " on each element, going from left to right.\n" - "\n" - " `fold([1, 2, 3], 0, add)` is the equivalent of\n" - " `add(add(add(0, 1), 2), 3)`.\n" - "\n" - " This function runs in linear time.\n" -). --spec fold(list(AGF), AGH, fun((AGH, AGF) -> AGH)) -> AGH. -fold(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - fold(Rest, Fun(Initial, First), Fun) - end. - --file("src/gleam/list.gleam", 713). -?DOC( - " Reduces a list of elements into a single value by calling a given function\n" - " on each element, going from right to left.\n" - "\n" - " `fold_right([1, 2, 3], 0, add)` is the equivalent of\n" - " `add(add(add(0, 3), 2), 1)`.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " Unlike `fold` this function is not tail recursive. Where possible use\n" - " `fold` instead as it will use less memory.\n" -). --spec fold_right(list(AGI), AGK, fun((AGK, AGI) -> AGK)) -> AGK. -fold_right(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - Fun(fold_right(Rest, Initial, Fun), First) - end. - --file("src/gleam/list.gleam", 750). --spec index_fold_loop( - list(AGO), - AGQ, - fun((AGQ, AGO, integer()) -> AGQ), - integer() -) -> AGQ. -index_fold_loop(Over, Acc, With, Index) -> - case Over of - [] -> - Acc; - - [First | Rest] -> - index_fold_loop(Rest, With(Acc, First, Index), With, Index + 1) - end. - --file("src/gleam/list.gleam", 742). -?DOC( - " Like `fold` but the folding function also receives the index of the current element.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [\"a\", \"b\", \"c\"]\n" - " |> index_fold(\"\", fn(acc, item, index) {\n" - " acc <> int.to_string(index) <> \":\" <> item <> \" \"\n" - " })\n" - " == \"0:a 1:b 2:c\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert [10, 20, 30]\n" - " |> index_fold(0, fn(acc, item, index) { acc + item * index })\n" - " == 80\n" - " ```\n" -). --spec index_fold(list(AGL), AGN, fun((AGN, AGL, integer()) -> AGN)) -> AGN. -index_fold(List, Initial, Fun) -> - index_fold_loop(List, Initial, Fun, 0). - --file("src/gleam/list.gleam", 782). -?DOC( - " A variant of fold that might fail.\n" - "\n" - " The folding function should return `Result(accumulator, error)`.\n" - " If the returned value is `Ok(accumulator)` try_fold will try the next value in the list.\n" - " If the returned value is `Error(error)` try_fold will stop and return that error.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [1, 2, 3, 4]\n" - " |> try_fold(0, fn(acc, i) {\n" - " case i < 3 {\n" - " True -> Ok(acc + i)\n" - " False -> Error(Nil)\n" - " }\n" - " })\n" - " == Error(Nil)\n" - " ```\n" -). --spec try_fold(list(AGR), AGT, fun((AGT, AGR) -> {ok, AGT} | {error, AGU})) -> {ok, - AGT} | - {error, AGU}. -try_fold(List, Initial, Fun) -> - case List of - [] -> - {ok, Initial}; - - [First | Rest] -> - case Fun(Initial, First) of - {ok, Result} -> - try_fold(Rest, Result, Fun); - - {error, _} = Error -> - Error - end - end. - --file("src/gleam/list.gleam", 821). -?DOC( - " A variant of fold that allows to stop folding earlier.\n" - "\n" - " The folding function should return `ContinueOrStop(accumulator)`.\n" - " If the returned value is `Continue(accumulator)` fold_until will try the next value in the list.\n" - " If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [1, 2, 3, 4]\n" - " |> fold_until(0, fn(acc, i) {\n" - " case i < 3 {\n" - " True -> Continue(acc + i)\n" - " False -> Stop(acc)\n" - " }\n" - " })\n" - " == 3\n" - " ```\n" -). --spec fold_until(list(AGZ), AHB, fun((AHB, AGZ) -> continue_or_stop(AHB))) -> AHB. -fold_until(List, Initial, Fun) -> - case List of - [] -> - Initial; - - [First | Rest] -> - case Fun(Initial, First) of - {continue, Next_accumulator} -> - fold_until(Rest, Next_accumulator, Fun); - - {stop, B} -> - B - end - end. - --file("src/gleam/list.gleam", 855). -?DOC( - " Finds the first element in a given list for which the given function returns\n" - " `True`.\n" - "\n" - " Returns `Error(Nil)` if no such element is found.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert find([1, 2, 3], fn(x) { x > 2 }) == Ok(3)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert find([1, 2, 3], fn(x) { x > 4 }) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert find([], fn(_) { True }) == Error(Nil)\n" - " ```\n" -). --spec find(list(AHD), fun((AHD) -> boolean())) -> {ok, AHD} | {error, nil}. -find(List, Is_desired) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - case Is_desired(First) of - true -> - {ok, First}; - - false -> - find(Rest, Is_desired) - end - end. - --file("src/gleam/list.gleam", 888). -?DOC( - " Finds the first element in a given list for which the given function returns\n" - " `Ok(new_value)`, then returns the wrapped `new_value`.\n" - "\n" - " Returns `Error(Nil)` if no such element is found.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert find_map([[], [2], [3]], first) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert find_map([[], []], first) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert find_map([], first) == Error(Nil)\n" - " ```\n" -). --spec find_map(list(AHH), fun((AHH) -> {ok, AHJ} | {error, any()})) -> {ok, AHJ} | - {error, nil}. -find_map(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - case Fun(First) of - {ok, First@1} -> - {ok, First@1}; - - {error, _} -> - find_map(Rest, Fun) - end - end. - --file("src/gleam/list.gleam", 920). -?DOC( - " Returns `True` if the given function returns `True` for all the elements in\n" - " the given list. If the function returns `False` for any of the elements it\n" - " immediately returns `False` without checking the rest of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert all([], fn(x) { x > 3 })\n" - " ```\n" - "\n" - " ```gleam\n" - " assert all([4, 5], fn(x) { x > 3 })\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !all([4, 3], fn(x) { x > 3 })\n" - " ```\n" -). --spec all(list(AHP), fun((AHP) -> boolean())) -> boolean(). -all(List, Predicate) -> - case List of - [] -> - true; - - [First | Rest] -> - case Predicate(First) of - true -> - all(Rest, Predicate); - - false -> - false - end - end. - --file("src/gleam/list.gleam", 953). -?DOC( - " Returns `True` if the given function returns `True` for any the elements in\n" - " the given list. If the function returns `True` for any of the elements it\n" - " immediately returns `True` without checking the rest of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !any([], fn(x) { x > 3 })\n" - " ```\n" - "\n" - " ```gleam\n" - " assert any([4, 5], fn(x) { x > 3 })\n" - " ```\n" - "\n" - " ```gleam\n" - " assert any([4, 3], fn(x) { x > 4 })\n" - " ```\n" - "\n" - " ```gleam\n" - " assert any([3, 4], fn(x) { x > 3 })\n" - " ```\n" -). --spec any(list(AHR), fun((AHR) -> boolean())) -> boolean(). -any(List, Predicate) -> - case List of - [] -> - false; - - [First | Rest] -> - case Predicate(First) of - true -> - true; - - false -> - any(Rest, Predicate) - end - end. - --file("src/gleam/list.gleam", 991). --spec zip_loop(list(AHY), list(AIA), list({AHY, AIA})) -> list({AHY, AIA}). -zip_loop(One, Other, Acc) -> - case {One, Other} of - {[First_one | Rest_one], [First_other | Rest_other]} -> - zip_loop(Rest_one, Rest_other, [{First_one, First_other} | Acc]); - - {_, _} -> - lists:reverse(Acc) - end. - --file("src/gleam/list.gleam", 987). -?DOC( - " Takes two lists and returns a single list of 2-element tuples.\n" - "\n" - " If one of the lists is longer than the other, the remaining elements from\n" - " the longer list are not used.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert zip([], []) == []\n" - " ```\n" - "\n" - " ```gleam\n" - " assert zip([1, 2], [3]) == [#(1, 3)]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert zip([1], [3, 4]) == [#(1, 3)]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert zip([1, 2], [3, 4]) == [#(1, 3), #(2, 4)]\n" - " ```\n" -). --spec zip(list(AHT), list(AHV)) -> list({AHT, AHV}). -zip(List, Other) -> - zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1028). --spec strict_zip_loop(list(AIL), list(AIN), list({AIL, AIN})) -> {ok, - list({AIL, AIN})} | - {error, nil}. -strict_zip_loop(One, Other, Acc) -> - case {One, Other} of - {[], []} -> - {ok, lists:reverse(Acc)}; - - {[], _} -> - {error, nil}; - - {_, []} -> - {error, nil}; - - {[First_one | Rest_one], [First_other | Rest_other]} -> - strict_zip_loop( - Rest_one, - Rest_other, - [{First_one, First_other} | Acc] - ) - end. - --file("src/gleam/list.gleam", 1021). -?DOC( - " Takes two lists and returns a single list of 2-element tuples.\n" - "\n" - " If one of the lists is longer than the other, an `Error` is returned.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert strict_zip([], []) == Ok([])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert strict_zip([1, 2], [3]) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert strict_zip([1], [3, 4]) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert strict_zip([1, 2], [3, 4]) == Ok([#(1, 3), #(2, 4)])\n" - " ```\n" -). --spec strict_zip(list(AIE), list(AIG)) -> {ok, list({AIE, AIG})} | {error, nil}. -strict_zip(List, Other) -> - strict_zip_loop(List, Other, []). - --file("src/gleam/list.gleam", 1057). --spec unzip_loop(list({AIY, AIZ}), list(AIY), list(AIZ)) -> {list(AIY), - list(AIZ)}. -unzip_loop(Input, One, Other) -> - case Input of - [] -> - {lists:reverse(One), lists:reverse(Other)}; - - [{First_one, First_other} | Rest] -> - unzip_loop(Rest, [First_one | One], [First_other | Other]) - end. - --file("src/gleam/list.gleam", 1053). -?DOC( - " Takes a single list of 2-element tuples and returns two lists.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert unzip([#(1, 2), #(3, 4)]) == #([1, 3], [2, 4])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert unzip([]) == #([], [])\n" - " ```\n" -). --spec unzip(list({AIT, AIU})) -> {list(AIT), list(AIU)}. -unzip(Input) -> - unzip_loop(Input, [], []). - --file("src/gleam/list.gleam", 1090). --spec intersperse_loop(list(AJI), AJI, list(AJI)) -> list(AJI). -intersperse_loop(List, Separator, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - intersperse_loop(Rest, Separator, [First, Separator | Acc]) - end. - --file("src/gleam/list.gleam", 1083). -?DOC( - " Inserts a given value between each existing element in a given list.\n" - "\n" - " This function runs in linear time and copies the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert intersperse([1, 1, 1], 2) == [1, 2, 1, 2, 1]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert intersperse([], 2) == []\n" - " ```\n" -). --spec intersperse(list(AJF), AJF) -> list(AJF). -intersperse(List, Elem) -> - case List of - [] -> - List; - - [_] -> - List; - - [First | Rest] -> - intersperse_loop(Rest, Elem, [First]) - end. - --file("src/gleam/list.gleam", 1112). --spec unique_loop(list(AJP), gleam@dict:dict(AJP, nil), list(AJP)) -> list(AJP). -unique_loop(List, Seen, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - case gleam@dict:has_key(Seen, First) of - true -> - unique_loop(Rest, Seen, Acc); - - false -> - unique_loop( - Rest, - gleam@dict:insert(Seen, First, nil), - [First | Acc] - ) - end - end. - --file("src/gleam/list.gleam", 1108). -?DOC( - " Removes any duplicate elements from a given list.\n" - "\n" - " This function returns in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert unique([1, 1, 1, 4, 7, 3, 3, 4]) == [1, 4, 7, 3]\n" - " ```\n" -). --spec unique(list(AJM)) -> list(AJM). -unique(List) -> - unique_loop(List, maps:new(), []). - --file("src/gleam/list.gleam", 1372). -?DOC( - " This is exactly the same as merge_ascendings but mirrored: it merges two\n" - " lists sorted in descending order into a single list sorted in ascending\n" - " order according to the given comparator function.\n" - "\n" - " This reversing of the sort order is not avoidable if we want to implement\n" - " merge as a tail recursive function. We could reverse the accumulator before\n" - " returning it but that would end up being less efficient; so the merging\n" - " algorithm has to play around this.\n" -). --spec merge_descendings( - list(ALA), - list(ALA), - fun((ALA, ALA) -> gleam@order:order()), - list(ALA) -) -> list(ALA). -merge_descendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - lists:reverse(List, Acc); - - {List, []} -> - lists:reverse(List, Acc); - - {[First1 | Rest1], [First2 | Rest2]} -> - case Compare(First1, First2) of - lt -> - merge_descendings(List1, Rest2, Compare, [First2 | Acc]); - - gt -> - merge_descendings(Rest1, List2, Compare, [First1 | Acc]); - - eq -> - merge_descendings(Rest1, List2, Compare, [First1 | Acc]) - end - end. - --file("src/gleam/list.gleam", 1320). -?DOC(" This is the same as merge_ascending_pairs but flipped for descending lists.\n"). --spec merge_descending_pairs( - list(list(AKP)), - fun((AKP, AKP) -> gleam@order:order()), - list(list(AKP)) -) -> list(list(AKP)). -merge_descending_pairs(Sequences, Compare, Acc) -> - case Sequences of - [] -> - lists:reverse(Acc); - - [Sequence] -> - lists:reverse([lists:reverse(Sequence) | Acc]); - - [Descending1, Descending2 | Rest] -> - Ascending = merge_descendings(Descending1, Descending2, Compare, []), - merge_descending_pairs(Rest, Compare, [Ascending | Acc]) - end. - --file("src/gleam/list.gleam", 1345). -?DOC( - " Merges two lists sorted in ascending order into a single list sorted in\n" - " descending order according to the given comparator function.\n" - "\n" - " This reversing of the sort order is not avoidable if we want to implement\n" - " merge as a tail recursive function. We could reverse the accumulator before\n" - " returning it but that would end up being less efficient; so the merging\n" - " algorithm has to play around this.\n" -). --spec merge_ascendings( - list(AKV), - list(AKV), - fun((AKV, AKV) -> gleam@order:order()), - list(AKV) -) -> list(AKV). -merge_ascendings(List1, List2, Compare, Acc) -> - case {List1, List2} of - {[], List} -> - lists:reverse(List, Acc); - - {List, []} -> - lists:reverse(List, Acc); - - {[First1 | Rest1], [First2 | Rest2]} -> - case Compare(First1, First2) of - lt -> - merge_ascendings(Rest1, List2, Compare, [First1 | Acc]); - - gt -> - merge_ascendings(List1, Rest2, Compare, [First2 | Acc]); - - eq -> - merge_ascendings(List1, Rest2, Compare, [First2 | Acc]) - end - end. - --file("src/gleam/list.gleam", 1298). -?DOC( - " Given a list of ascending lists, it merges adjacent pairs into a single\n" - " descending list, halving their number.\n" - " It returns a list of the remaining descending lists.\n" -). --spec merge_ascending_pairs( - list(list(AKJ)), - fun((AKJ, AKJ) -> gleam@order:order()), - list(list(AKJ)) -) -> list(list(AKJ)). -merge_ascending_pairs(Sequences, Compare, Acc) -> - case Sequences of - [] -> - lists:reverse(Acc); - - [Sequence] -> - lists:reverse([lists:reverse(Sequence) | Acc]); - - [Ascending1, Ascending2 | Rest] -> - Descending = merge_ascendings(Ascending1, Ascending2, Compare, []), - merge_ascending_pairs(Rest, Compare, [Descending | Acc]) - end. - --file("src/gleam/list.gleam", 1264). -?DOC( - " Given some some sorted sequences (assumed to be sorted in `direction`) it\n" - " merges them all together until we're left with just a list sorted in\n" - " ascending order.\n" -). --spec merge_all( - list(list(AKF)), - sorting(), - fun((AKF, AKF) -> gleam@order:order()) -) -> list(AKF). -merge_all(Sequences, Direction, Compare) -> - case {Sequences, Direction} of - {[], _} -> - []; - - {[Sequence], ascending} -> - Sequence; - - {[Sequence@1], descending} -> - lists:reverse(Sequence@1); - - {_, ascending} -> - Sequences@1 = merge_ascending_pairs(Sequences, Compare, []), - merge_all(Sequences@1, descending, Compare); - - {_, descending} -> - Sequences@2 = merge_descending_pairs(Sequences, Compare, []), - merge_all(Sequences@2, ascending, Compare) - end. - --file("src/gleam/list.gleam", 1197). -?DOC( - " Given a list it returns slices of it that are locally sorted in ascending\n" - " order.\n" - "\n" - " Imagine you have this list:\n" - "\n" - " ```\n" - " [1, 2, 3, 2, 1, 0]\n" - " ^^^^^^^ ^^^^^^^ This is a slice in descending order\n" - " |\n" - " | This is a slice that is sorted in ascending order\n" - " ```\n" - "\n" - " So the produced result will contain these two slices, each one sorted in\n" - " ascending order: `[[1, 2, 3], [0, 1, 2]]`.\n" - "\n" - " - `growing` is an accumulator with the current slice being grown\n" - " - `direction` is the growing direction of the slice being grown, it could\n" - " either be ascending or strictly descending\n" - " - `prev` is the previous element that needs to be added to the growing slice\n" - " it is carried around to check whether we have to keep growing the current\n" - " slice or not\n" - " - `acc` is the accumulator containing the slices sorted in ascending order\n" -). --spec sequences( - list(AJY), - fun((AJY, AJY) -> gleam@order:order()), - list(AJY), - sorting(), - AJY, - list(list(AJY)) -) -> list(list(AJY)). -sequences(List, Compare, Growing, Direction, Prev, Acc) -> - Growing@1 = [Prev | Growing], - case List of - [] -> - case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end; - - [New | Rest] -> - case {Compare(Prev, New), Direction} of - {gt, descending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {lt, ascending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {eq, ascending} -> - sequences(Rest, Compare, Growing@1, Direction, New, Acc); - - {gt, ascending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end; - - {lt, descending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end; - - {eq, descending} -> - Acc@1 = case Direction of - ascending -> - [lists:reverse(Growing@1) | Acc]; - - descending -> - [Growing@1 | Acc] - end, - case Rest of - [] -> - [[New] | Acc@1]; - - [Next | Rest@1] -> - Direction@1 = case Compare(New, Next) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - sequences( - Rest@1, - Compare, - [New], - Direction@1, - Next, - Acc@1 - ) - end - end - end. - --file("src/gleam/list.gleam", 1135). -?DOC( - " Sorts from smallest to largest based upon the ordering specified by a given\n" - " function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) == [1, 2, 3, 4, 4, 5, 6]\n" - " ```\n" -). --spec sort(list(AJV), fun((AJV, AJV) -> gleam@order:order())) -> list(AJV). -sort(List, Compare) -> - case List of - [] -> - []; - - [X] -> - [X]; - - [X@1, Y | Rest] -> - Direction = case Compare(X@1, Y) of - lt -> - ascending; - - eq -> - ascending; - - gt -> - descending - end, - Sequences = sequences(Rest, Compare, [X@1], Direction, Y, []), - merge_all(Sequences, ascending, Compare) - end. - --file("src/gleam/list.gleam", 1405). --spec repeat_loop(ALH, integer(), list(ALH)) -> list(ALH). -repeat_loop(Item, Times, Acc) -> - case Times =< 0 of - true -> - Acc; - - false -> - repeat_loop(Item, Times - 1, [Item | Acc]) - end. - --file("src/gleam/list.gleam", 1401). -?DOC( - " Builds a list of a given value a given number of times.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert repeat(\"a\", times: 0) == []\n" - " ```\n" - "\n" - " ```gleam\n" - " assert repeat(\"a\", times: 5) == [\"a\", \"a\", \"a\", \"a\", \"a\"]\n" - " ```\n" -). --spec repeat(ALF, integer()) -> list(ALF). -repeat(A, Times) -> - repeat_loop(A, Times, []). - --file("src/gleam/list.gleam", 1435). --spec split_loop(list(ALO), integer(), list(ALO)) -> {list(ALO), list(ALO)}. -split_loop(List, N, Taken) -> - case N =< 0 of - true -> - {lists:reverse(Taken), List}; - - false -> - case List of - [] -> - {lists:reverse(Taken), []}; - - [First | Rest] -> - split_loop(Rest, N - 1, [First | Taken]) - end - end. - --file("src/gleam/list.gleam", 1431). -?DOC( - " Splits a list in two before the given index.\n" - "\n" - " If the list is not long enough to have the given index the before list will\n" - " be the input list, and the after list will be empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert split([6, 7, 8, 9], 0) == #([], [6, 7, 8, 9])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert split([6, 7, 8, 9], 2) == #([6, 7], [8, 9])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert split([6, 7, 8, 9], 4) == #([6, 7, 8, 9], [])\n" - " ```\n" -). --spec split(list(ALK), integer()) -> {list(ALK), list(ALK)}. -split(List, Index) -> - split_loop(List, Index, []). - --file("src/gleam/list.gleam", 1471). --spec split_while_loop(list(ALX), fun((ALX) -> boolean()), list(ALX)) -> {list(ALX), - list(ALX)}. -split_while_loop(List, F, Acc) -> - case List of - [] -> - {lists:reverse(Acc), []}; - - [First | Rest] -> - case F(First) of - true -> - split_while_loop(Rest, F, [First | Acc]); - - false -> - {lists:reverse(Acc), List} - end - end. - --file("src/gleam/list.gleam", 1464). -?DOC( - " Splits a list in two before the first element that a given function returns\n" - " `False` for.\n" - "\n" - " If the function returns `True` for all elements the first list will be the\n" - " input list, and the second list will be empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 })\n" - " == #([1, 2, 3], [4, 5])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 })\n" - " == #([1, 2, 3, 4, 5], [])\n" - " ```\n" -). --spec split_while(list(ALT), fun((ALT) -> boolean())) -> {list(ALT), list(ALT)}. -split_while(List, Predicate) -> - split_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1508). -?DOC( - " Given a list of 2-element tuples, finds the first tuple that has a given\n" - " key as the first element and returns the second element.\n" - "\n" - " If no tuple is found with the given key then `Error(Nil)` is returned.\n" - "\n" - " This function may be useful for interacting with Erlang code where lists of\n" - " tuples are common.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert key_find([#(\"a\", 0), #(\"b\", 1)], \"a\") == Ok(0)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert key_find([#(\"a\", 0), #(\"b\", 1)], \"b\") == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert key_find([#(\"a\", 0), #(\"b\", 1)], \"c\") == Error(Nil)\n" - " ```\n" -). --spec key_find(list({AMC, AMD}), AMC) -> {ok, AMD} | {error, nil}. -key_find(Keyword_list, Desired_key) -> - find_map( - Keyword_list, - fun(Keyword) -> - {Key, Value} = Keyword, - case Key =:= Desired_key of - true -> - {ok, Value}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/list.gleam", 1537). -?DOC( - " Given a list of 2-element tuples, finds all tuples that have a given\n" - " key as the first element and returns the second element.\n" - "\n" - " This function may be useful for interacting with Erlang code where lists of\n" - " tuples are common.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert key_filter([#(\"a\", 0), #(\"b\", 1), #(\"a\", 2)], \"a\") == [0, 2]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert key_filter([#(\"a\", 0), #(\"b\", 1)], \"c\") == []\n" - " ```\n" -). --spec key_filter(list({AMH, AMI}), AMH) -> list(AMI). -key_filter(Keyword_list, Desired_key) -> - filter_map( - Keyword_list, - fun(Keyword) -> - {Key, Value} = Keyword, - case Key =:= Desired_key of - true -> - {ok, Value}; - - false -> - {error, nil} - end - end - ). - --file("src/gleam/list.gleam", 1574). --spec key_pop_loop(list({AMR, AMS}), AMR, list({AMR, AMS})) -> {ok, - {AMS, list({AMR, AMS})}} | - {error, nil}. -key_pop_loop(List, Key, Checked) -> - case List of - [] -> - {error, nil}; - - [{K, V} | Rest] when K =:= Key -> - {ok, {V, lists:reverse(Checked, Rest)}}; - - [First | Rest@1] -> - key_pop_loop(Rest@1, Key, [First | Checked]) - end. - --file("src/gleam/list.gleam", 1570). -?DOC( - " Given a list of 2-element tuples, finds the first tuple that has a given\n" - " key as the first element. This function will return the second element\n" - " of the found tuple and list with tuple removed.\n" - "\n" - " If no tuple is found with the given key then `Error(Nil)` is returned.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert key_pop([#(\"a\", 0), #(\"b\", 1)], \"a\") == Ok(#(0, [#(\"b\", 1)]))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert key_pop([#(\"a\", 0), #(\"b\", 1)], \"b\") == Ok(#(1, [#(\"a\", 0)]))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert key_pop([#(\"a\", 0), #(\"b\", 1)], \"c\") == Error(Nil)\n" - " ```\n" -). --spec key_pop(list({AML, AMM}), AML) -> {ok, {AMM, list({AML, AMM})}} | - {error, nil}. -key_pop(List, Key) -> - key_pop_loop(List, Key, []). - --file("src/gleam/list.gleam", 1606). --spec key_set_loop(list({ANC, AND}), ANC, AND, list({ANC, AND})) -> list({ANC, - AND}). -key_set_loop(List, Key, Value, Inspected) -> - case List of - [{K, _} | Rest] when K =:= Key -> - lists:reverse(Inspected, [{K, Value} | Rest]); - - [First | Rest@1] -> - key_set_loop(Rest@1, Key, Value, [First | Inspected]); - - [] -> - lists:reverse([{Key, Value} | Inspected]) - end. - --file("src/gleam/list.gleam", 1602). -?DOC( - " Given a list of 2-element tuples, inserts a key and value into the list.\n" - "\n" - " If there was already a tuple with the key then it is replaced, otherwise it\n" - " is added to the end of the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert key_set([#(5, 0), #(4, 1)], 4, 100) == [#(5, 0), #(4, 100)]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert key_set([#(5, 0), #(4, 1)], 1, 100) == [#(5, 0), #(4, 1), #(1, 100)]\n" - " ```\n" -). --spec key_set(list({AMY, AMZ}), AMY, AMZ) -> list({AMY, AMZ}). -key_set(List, Key, Value) -> - key_set_loop(List, Key, Value, []). - --file("src/gleam/list.gleam", 1633). -?DOC( - " Calls a function for each element in a list, discarding the return value.\n" - "\n" - " Useful for calling a side effect for every item of a list.\n" - "\n" - " ```gleam\n" - " import gleam/io\n" - "\n" - " assert each([\"1\", \"2\", \"3\"], io.println) == Nil\n" - " // 1\n" - " // 2\n" - " // 3\n" - " ```\n" -). --spec each(list(ANH), fun((ANH) -> any())) -> nil. -each(List, F) -> - case List of - [] -> - nil; - - [First | Rest] -> - F(First), - each(Rest, F) - end. - --file("src/gleam/list.gleam", 1660). -?DOC( - " Calls a `Result` returning function for each element in a list, discarding\n" - " the return value. If the function returns `Error` then the iteration is\n" - " stopped and the error is returned.\n" - "\n" - " Useful for calling a side effect for every item of a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert\n" - " try_each(\n" - " over: [1, 2, 3],\n" - " with: function_that_might_fail,\n" - " )\n" - " == Ok(Nil)\n" - " ```\n" -). --spec try_each(list(ANK), fun((ANK) -> {ok, any()} | {error, ANN})) -> {ok, nil} | - {error, ANN}. -try_each(List, Fun) -> - case List of - [] -> - {ok, nil}; - - [First | Rest] -> - case Fun(First) of - {ok, _} -> - try_each(Rest, Fun); - - {error, E} -> - {error, E} - end - end. - --file("src/gleam/list.gleam", 1692). --spec partition_loop(list(BGI), fun((BGI) -> boolean()), list(BGI), list(BGI)) -> {list(BGI), - list(BGI)}. -partition_loop(List, Categorise, Trues, Falses) -> - case List of - [] -> - {lists:reverse(Trues), lists:reverse(Falses)}; - - [First | Rest] -> - case Categorise(First) of - true -> - partition_loop(Rest, Categorise, [First | Trues], Falses); - - false -> - partition_loop(Rest, Categorise, Trues, [First | Falses]) - end - end. - --file("src/gleam/list.gleam", 1685). -?DOC( - " Partitions a list into a tuple/pair of lists\n" - " by a given categorisation function.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert [1, 2, 3, 4, 5] |> partition(int.is_odd) == #([1, 3, 5], [2, 4])\n" - " ```\n" -). --spec partition(list(ANS), fun((ANS) -> boolean())) -> {list(ANS), list(ANS)}. -partition(List, Categorise) -> - partition_loop(List, Categorise, [], []). - --file("src/gleam/list.gleam", 1736). --spec permutation_prepend( - AOM, - list(list(AOM)), - list(AOM), - list(AOM), - list(list(AOM)) -) -> list(list(AOM)). -permutation_prepend(El, Permutations, List_1, List_2, Acc) -> - case Permutations of - [] -> - permutation_zip(List_1, List_2, Acc); - - [Head | Tail] -> - permutation_prepend(El, Tail, List_1, List_2, [[El | Head] | Acc]) - end. - --file("src/gleam/list.gleam", 1718). --spec permutation_zip(list(AOF), list(AOF), list(list(AOF))) -> list(list(AOF)). -permutation_zip(List, Rest, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [Head | Tail] -> - permutation_prepend( - Head, - permutations(lists:reverse(Rest, Tail)), - Tail, - [Head | Rest], - Acc - ) - end. - --file("src/gleam/list.gleam", 1711). -?DOC( - " Returns all the permutations of a list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert permutations([1, 2]) == [[1, 2], [2, 1]]\n" - " ```\n" -). --spec permutations(list(AOB)) -> list(list(AOB)). -permutations(List) -> - case List of - [] -> - [[]]; - - L -> - permutation_zip(L, [], []) - end. - --file("src/gleam/list.gleam", 1769). --spec window_loop(list(list(AOZ)), list(AOZ), integer()) -> list(list(AOZ)). -window_loop(Acc, List, N) -> - Window = take(List, N), - case erlang:length(Window) =:= N of - true -> - window_loop([Window | Acc], drop(List, 1), N); - - false -> - lists:reverse(Acc) - end. - --file("src/gleam/list.gleam", 1762). -?DOC( - " Returns a list of sliding windows.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert window([1,2,3,4,5], 3) == [[1, 2, 3], [2, 3, 4], [3, 4, 5]]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert window([1, 2], 4) == []\n" - " ```\n" -). --spec window(list(AOV), integer()) -> list(list(AOV)). -window(List, N) -> - case N =< 0 of - true -> - []; - - false -> - window_loop([], List, N) - end. - --file("src/gleam/list.gleam", 1790). -?DOC( - " Returns a list of tuples containing two contiguous elements.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert window_by_2([1,2,3,4]) == [#(1, 2), #(2, 3), #(3, 4)]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert window_by_2([1]) == []\n" - " ```\n" -). --spec window_by_2(list(APF)) -> list({APF, APF}). -window_by_2(List) -> - zip(List, drop(List, 1)). - --file("src/gleam/list.gleam", 1802). -?DOC( - " Drops the first elements in a given list for which the predicate function returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert drop_while([1, 2, 3, 4], fn (x) { x < 3 }) == [3, 4]\n" - " ```\n" -). --spec drop_while(list(API), fun((API) -> boolean())) -> list(API). -drop_while(List, Predicate) -> - case List of - [] -> - []; - - [First | Rest] -> - case Predicate(First) of - true -> - drop_while(Rest, Predicate); - - false -> - [First | Rest] - end - end. - --file("src/gleam/list.gleam", 1831). --spec take_while_loop(list(APO), fun((APO) -> boolean()), list(APO)) -> list(APO). -take_while_loop(List, Predicate, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - case Predicate(First) of - true -> - take_while_loop(Rest, Predicate, [First | Acc]); - - false -> - lists:reverse(Acc) - end - end. - --file("src/gleam/list.gleam", 1824). -?DOC( - " Takes the first elements in a given list for which the predicate function returns `True`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) == [1, 2]\n" - " ```\n" -). --spec take_while(list(APL), fun((APL) -> boolean())) -> list(APL). -take_while(List, Predicate) -> - take_while_loop(List, Predicate, []). - --file("src/gleam/list.gleam", 1863). --spec chunk_loop(list(APX), fun((APX) -> APZ), APZ, list(APX), list(list(APX))) -> list(list(APX)). -chunk_loop(List, F, Previous_key, Current_chunk, Acc) -> - case List of - [First | Rest] -> - Key = F(First), - case Key =:= Previous_key of - true -> - chunk_loop(Rest, F, Key, [First | Current_chunk], Acc); - - false -> - New_acc = [lists:reverse(Current_chunk) | Acc], - chunk_loop(Rest, F, Key, [First], New_acc) - end; - - [] -> - lists:reverse([lists:reverse(Current_chunk) | Acc]) - end. - --file("src/gleam/list.gleam", 1856). -?DOC( - " Returns a list of chunks in which\n" - " the return value of calling `f` on each element is the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 })\n" - " == [[1], [2, 2], [3], [4, 4, 6], [7, 7]]\n" - " ```\n" -). --spec chunk(list(APS), fun((APS) -> any())) -> list(list(APS)). -chunk(List, F) -> - case List of - [] -> - []; - - [First | Rest] -> - chunk_loop(Rest, F, F(First), [First], []) - end. - --file("src/gleam/list.gleam", 1908). --spec sized_chunk_loop( - list(AQJ), - integer(), - integer(), - list(AQJ), - list(list(AQJ)) -) -> list(list(AQJ)). -sized_chunk_loop(List, Count, Left, Current_chunk, Acc) -> - case List of - [] -> - case Current_chunk of - [] -> - lists:reverse(Acc); - - Remaining -> - lists:reverse([lists:reverse(Remaining) | Acc]) - end; - - [First | Rest] -> - Chunk = [First | Current_chunk], - case Left > 1 of - true -> - sized_chunk_loop(Rest, Count, Left - 1, Chunk, Acc); - - false -> - sized_chunk_loop( - Rest, - Count, - Count, - [], - [lists:reverse(Chunk) | Acc] - ) - end - end. - --file("src/gleam/list.gleam", 1904). -?DOC( - " Returns a list of chunks containing `count` elements each.\n" - "\n" - " If the last chunk does not have `count` elements, it is instead\n" - " a partial chunk, with less than `count` elements.\n" - "\n" - " For any `count` less than 1 this function behaves as if it was set to 1.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2)\n" - " == [[1, 2], [3, 4], [5, 6]]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3)\n" - " == [[1, 2, 3], [4, 5, 6], [7, 8]]\n" - " ```\n" -). --spec sized_chunk(list(AQF), integer()) -> list(list(AQF)). -sized_chunk(List, Count) -> - sized_chunk_loop(List, Count, Count, [], []). - --file("src/gleam/list.gleam", 1950). -?DOC( - " This function acts similar to fold, but does not take an initial state.\n" - " Instead, it starts from the first element in the list\n" - " and combines it with each subsequent element in turn using the given\n" - " function. The function is called as `fun(accumulator, current_element)`.\n" - "\n" - " Returns `Ok` to indicate a successful run, and `Error` if called on an\n" - " empty list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [] |> reduce(fn(acc, x) { acc + x }) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) == Ok(15)\n" - " ```\n" -). --spec reduce(list(AQQ), fun((AQQ, AQQ) -> AQQ)) -> {ok, AQQ} | {error, nil}. -reduce(List, Fun) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, fold(Rest, First, Fun)} - end. - --file("src/gleam/list.gleam", 1974). --spec scan_loop(list(AQY), ARA, list(ARA), fun((ARA, AQY) -> ARA)) -> list(ARA). -scan_loop(List, Accumulator, Accumulated, Fun) -> - case List of - [] -> - lists:reverse(Accumulated); - - [First | Rest] -> - Next = Fun(Accumulator, First), - scan_loop(Rest, Next, [Next | Accumulated], Fun) - end. - --file("src/gleam/list.gleam", 1966). -?DOC( - " Similar to `fold`, but yields the state of the accumulator at each stage.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i })\n" - " == [101, 103, 106]\n" - " ```\n" -). --spec scan(list(AQU), AQW, fun((AQW, AQU) -> AQW)) -> list(AQW). -scan(List, Initial, Fun) -> - scan_loop(List, Initial, [], Fun). - --file("src/gleam/list.gleam", 2005). -?DOC( - " Returns the last element in the given list.\n" - "\n" - " Returns `Error(Nil)` if the list is empty.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert last([]) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert last([1, 2, 3, 4, 5]) == Ok(5)\n" - " ```\n" -). --spec last(list(ARD)) -> {ok, ARD} | {error, nil}. -last(List) -> - case List of - [] -> - {error, nil}; - - [Last] -> - {ok, Last}; - - [_ | Rest] -> - last(Rest) - end. - --file("src/gleam/list.gleam", 2026). -?DOC( - " Return unique combinations of elements in the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert combinations([1, 2, 3], 2) == [[1, 2], [1, 3], [2, 3]]\n" - " ```\n" - "\n" - " ```gleam\n" - " assert combinations([1, 2, 3, 4], 3)\n" - " == [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]\n" - " ```\n" -). --spec combinations(list(ARH), integer()) -> list(list(ARH)). -combinations(Items, N) -> - case {N, Items} of - {0, _} -> - [[]]; - - {_, []} -> - []; - - {_, [First | Rest]} -> - _pipe = Rest, - _pipe@1 = combinations(_pipe, N - 1), - _pipe@2 = map( - _pipe@1, - fun(Combination) -> [First | Combination] end - ), - _pipe@3 = lists:reverse(_pipe@2), - fold(_pipe@3, combinations(Rest, N), fun(Acc, C) -> [C | Acc] end) - end. - --file("src/gleam/list.gleam", 2051). --spec combination_pairs_loop(list(ARO), list({ARO, ARO})) -> list({ARO, ARO}). -combination_pairs_loop(Items, Acc) -> - case Items of - [] -> - lists:reverse(Acc); - - [First | Rest] -> - First_combinations = map(Rest, fun(Other) -> {First, Other} end), - Acc@1 = lists:reverse(First_combinations, Acc), - combination_pairs_loop(Rest, Acc@1) - end. - --file("src/gleam/list.gleam", 2047). -?DOC( - " Return unique pair combinations of elements in the list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert combination_pairs([1, 2, 3]) == [#(1, 2), #(1, 3), #(2, 3)]\n" - " ```\n" -). --spec combination_pairs(list(ARL)) -> list({ARL, ARL}). -combination_pairs(Items) -> - combination_pairs_loop(Items, []). - --file("src/gleam/list.gleam", 2107). --spec take_firsts(list(list(ASI)), list(ASI), list(list(ASI))) -> {list(ASI), - list(list(ASI))}. -take_firsts(Rows, Column, Remaining_rows) -> - case Rows of - [] -> - {lists:reverse(Column), lists:reverse(Remaining_rows)}; - - [[] | Rest] -> - take_firsts(Rest, Column, Remaining_rows); - - [[First | Remaining_row] | Rest_rows] -> - Remaining_rows@1 = [Remaining_row | Remaining_rows], - take_firsts(Rest_rows, [First | Column], Remaining_rows@1) - end. - --file("src/gleam/list.gleam", 2094). --spec transpose_loop(list(list(ASB)), list(list(ASB))) -> list(list(ASB)). -transpose_loop(Rows, Columns) -> - case Rows of - [] -> - lists:reverse(Columns); - - _ -> - {Column, Rest} = take_firsts(Rows, [], []), - case Column of - [_ | _] -> - transpose_loop(Rest, [Column | Columns]); - - [] -> - transpose_loop(Rest, Columns) - end - end. - --file("src/gleam/list.gleam", 2090). -?DOC( - " Transpose rows and columns of the list of lists.\n" - "\n" - " Notice: This function is not tail recursive,\n" - " and thus may exceed stack size if called,\n" - " with large lists (on the JavaScript target).\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert transpose([[1, 2, 3], [101, 102, 103]])\n" - " == [[1, 101], [2, 102], [3, 103]]\n" - " ```\n" -). --spec transpose(list(list(ARW))) -> list(list(ARW)). -transpose(List_of_lists) -> - transpose_loop(List_of_lists, []). - --file("src/gleam/list.gleam", 2071). -?DOC( - " Make a list alternating the elements from the given lists\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert interleave([[1, 2], [101, 102], [201, 202]])\n" - " == [1, 101, 201, 2, 102, 202]\n" - " ```\n" -). --spec interleave(list(list(ARS))) -> list(ARS). -interleave(List) -> - _pipe = List, - _pipe@1 = transpose(_pipe), - lists:append(_pipe@1). - --file("src/gleam/list.gleam", 2140). --spec shuffle_pair_unwrap_loop(list({float(), ASU}), list(ASU)) -> list(ASU). -shuffle_pair_unwrap_loop(List, Acc) -> - case List of - [] -> - Acc; - - [Elem_pair | Enumerable] -> - shuffle_pair_unwrap_loop( - Enumerable, - [erlang:element(2, Elem_pair) | Acc] - ) - end. - --file("src/gleam/list.gleam", 2148). --spec do_shuffle_by_pair_indexes(list({float(), ASY})) -> list({float(), ASY}). -do_shuffle_by_pair_indexes(List_of_pairs) -> - sort( - List_of_pairs, - fun(A_pair, B_pair) -> - gleam@float:compare( - erlang:element(1, A_pair), - erlang:element(1, B_pair) - ) - end - ). - --file("src/gleam/list.gleam", 2133). -?DOC( - " Takes a list, randomly sorts all items and returns the shuffled list.\n" - "\n" - " This function uses `float.random` to decide the order of the elements.\n" - "\n" - " ## Example\n" - "\n" - " ```gleam\n" - " [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |> shuffle\n" - " // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5]\n" - " ```\n" -). --spec shuffle(list(ASR)) -> list(ASR). -shuffle(List) -> - _pipe = List, - _pipe@1 = fold(_pipe, [], fun(Acc, A) -> [{rand:uniform(), A} | Acc] end), - _pipe@2 = do_shuffle_by_pair_indexes(_pipe@1), - shuffle_pair_unwrap_loop(_pipe@2, []). - --file("src/gleam/list.gleam", 2178). --spec max_loop(list(ATI), fun((ATI, ATI) -> gleam@order:order()), ATI) -> ATI. -max_loop(List, Compare, Max) -> - case List of - [] -> - Max; - - [First | Rest] -> - case Compare(First, Max) of - gt -> - max_loop(Rest, Compare, First); - - lt -> - max_loop(Rest, Compare, Max); - - eq -> - max_loop(Rest, Compare, Max) - end - end. - --file("src/gleam/list.gleam", 2168). -?DOC( - " Takes a list and a comparator, and returns the maximum element in the list\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert [1, 2, 3, 4, 5] |> list.max(int.compare) == Ok(5)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert [\"a\", \"c\", \"b\"] |> list.max(string.compare) == Ok(\"c\")\n" - " ```\n" -). --spec max(list(ATB), fun((ATB, ATB) -> gleam@order:order())) -> {ok, ATB} | - {error, nil}. -max(List, Compare) -> - case List of - [] -> - {error, nil}; - - [First | Rest] -> - {ok, max_loop(Rest, Compare, First)} - end. - --file("src/gleam/list.gleam", 2243). --spec log_random() -> float(). -log_random() -> - Random@1 = case gleam@float:logarithm( - rand:uniform() + 2.2250738585072014e-308 - ) of - {ok, Random} -> Random; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam/list"/utf8>>, - function => <<"log_random"/utf8>>, - line => 2244, - value => _assert_fail, - start => 55129, - 'end' => 55200, - pattern_start => 55140, - pattern_end => 55150}) - end, - Random@1. - --file("src/gleam/list.gleam", 2220). --spec sample_loop( - list(ATM), - gleam@dict:dict(integer(), ATM), - integer(), - float() -) -> gleam@dict:dict(integer(), ATM). -sample_loop(List, Reservoir, N, W) -> - Skip = begin - Log@1 = case gleam@float:logarithm(1.0 - W) of - {ok, Log} -> Log; - _assert_fail -> - erlang:error(#{gleam_error => let_assert, - message => <<"Pattern match failed, no pattern matched the value."/utf8>>, - file => <>, - module => <<"gleam/list"/utf8>>, - function => <<"sample_loop"/utf8>>, - line => 2227, - value => _assert_fail, - start => 54690, - 'end' => 54736, - pattern_start => 54701, - pattern_end => 54708}) - end, - erlang:round(math:floor(case Log@1 of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> log_random() / Gleam@denominator - end)) - end, - case drop(List, Skip) of - [] -> - Reservoir; - - [First | Rest] -> - Reservoir@1 = gleam@dict:insert( - Reservoir, - gleam@int:random(N), - First - ), - W@1 = W * math:exp(case erlang:float(N) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator@1 -> log_random() / Gleam@denominator@1 - end), - sample_loop(Rest, Reservoir@1, N, W@1) - end. - --file("src/gleam/list.gleam", 2259). --spec build_reservoir_loop( - list(ATX), - integer(), - gleam@dict:dict(integer(), ATX) -) -> {gleam@dict:dict(integer(), ATX), list(ATX)}. -build_reservoir_loop(List, Size, Reservoir) -> - Reservoir_size = maps:size(Reservoir), - case Reservoir_size >= Size of - true -> - {Reservoir, List}; - - false -> - case List of - [] -> - {Reservoir, []}; - - [First | Rest] -> - Reservoir@1 = gleam@dict:insert( - Reservoir, - Reservoir_size, - First - ), - build_reservoir_loop(Rest, Size, Reservoir@1) - end - end. - --file("src/gleam/list.gleam", 2255). -?DOC( - " Builds the initial reservoir used by Algorithm L.\n" - " This is a dictionary with keys ranging from `0` up to `n - 1` where each\n" - " value is the corresponding element at that position in `list`.\n" - "\n" - " This also returns the remaining elements of `list` that didn't end up in\n" - " the reservoir.\n" -). --spec build_reservoir(list(ATS), integer()) -> {gleam@dict:dict(integer(), ATS), - list(ATS)}. -build_reservoir(List, N) -> - build_reservoir_loop(List, N, maps:new()). - --file("src/gleam/list.gleam", 2202). -?DOC( - " Returns a random sample of up to n elements from a list using reservoir\n" - " sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L).\n" - " Returns an empty list if the sample size is less than or equal to 0.\n" - "\n" - " Order is not random, only selection is.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " sample([1, 2, 3, 4, 5], 3)\n" - " // -> [2, 4, 5] // A random sample of 3 items\n" - " ```\n" -). --spec sample(list(ATJ), integer()) -> list(ATJ). -sample(List, N) -> - {Reservoir, Rest} = build_reservoir(List, N), - case gleam@dict:is_empty(Reservoir) of - true -> - []; - - false -> - W = math:exp(case erlang:float(N) of - +0.0 -> +0.0; - -0.0 -> -0.0; - Gleam@denominator -> log_random() / Gleam@denominator - end), - maps:values(sample_loop(Rest, Reservoir, N, W)) - end. diff --git a/ui/javascript/gleam_stdlib/gleam@option.erl b/ui/javascript/gleam_stdlib/gleam@option.erl deleted file mode 100644 index 1204ae6..0000000 --- a/ui/javascript/gleam_stdlib/gleam@option.erl +++ /dev/null @@ -1,381 +0,0 @@ --module(gleam@option). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/option.gleam"). --export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]). --export_type([option/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type option(EL) :: {some, EL} | none. - --file("src/gleam/option.gleam", 57). --spec reverse_and_prepend(list(FA), list(FA)) -> list(FA). -reverse_and_prepend(Prefix, Suffix) -> - case Prefix of - [] -> - Suffix; - - [First | Rest] -> - reverse_and_prepend(Rest, [First | Suffix]) - end. - --file("src/gleam/option.gleam", 42). --spec all_loop(list(option(ER)), list(ER)) -> option(list(ER)). -all_loop(List, Acc) -> - case List of - [] -> - {some, lists:reverse(Acc)}; - - [none | _] -> - none; - - [{some, First} | Rest] -> - all_loop(Rest, [First | Acc]) - end. - --file("src/gleam/option.gleam", 38). -?DOC( - " Combines a list of `Option`s into a single `Option`.\n" - " If all elements in the list are `Some` then returns a `Some` holding the list of values.\n" - " If any element is `None` then returns `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert all([Some(1), Some(2)]) == Some([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert all([Some(1), None]) == None\n" - " ```\n" -). --spec all(list(option(EM))) -> option(list(EM)). -all(List) -> - all_loop(List, []). - --file("src/gleam/option.gleam", 76). -?DOC( - " Checks whether the `Option` is a `Some` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_some(Some(1))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_some(None)\n" - " ```\n" -). --spec is_some(option(any())) -> boolean(). -is_some(Option) -> - Option /= none. - --file("src/gleam/option.gleam", 92). -?DOC( - " Checks whether the `Option` is a `None` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !is_none(Some(1))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert is_none(None)\n" - " ```\n" -). --spec is_none(option(any())) -> boolean(). -is_none(Option) -> - Option =:= none. - --file("src/gleam/option.gleam", 108). -?DOC( - " Converts an `Option` type to a `Result` type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_result(Some(1), \"some_error\") == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_result(None, \"some_error\") == Error(\"some_error\")\n" - " ```\n" -). --spec to_result(option(FI), FL) -> {ok, FI} | {error, FL}. -to_result(Option, E) -> - case Option of - {some, A} -> - {ok, A}; - - none -> - {error, E} - end. - --file("src/gleam/option.gleam", 127). -?DOC( - " Converts a `Result` type to an `Option` type.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_result(Ok(1)) == Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_result(Error(\"some_error\")) == None\n" - " ```\n" -). --spec from_result({ok, FO} | {error, any()}) -> option(FO). -from_result(Result) -> - case Result of - {ok, A} -> - {some, A}; - - {error, _} -> - none - end. - --file("src/gleam/option.gleam", 146). -?DOC( - " Extracts the value from an `Option`, returning a default value if there is none.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert unwrap(Some(1), 0) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert unwrap(None, 0) == 0\n" - " ```\n" -). --spec unwrap(option(FT), FT) -> FT. -unwrap(Option, Default) -> - case Option of - {some, X} -> - X; - - none -> - Default - end. - --file("src/gleam/option.gleam", 165). -?DOC( - " Extracts the value from an `Option`, evaluating the default function if the option is `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert lazy_unwrap(Some(1), fn() { 0 }) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_unwrap(None, fn() { 0 }) == 0\n" - " ```\n" -). --spec lazy_unwrap(option(FV), fun(() -> FV)) -> FV. -lazy_unwrap(Option, Default) -> - case Option of - {some, X} -> - X; - - none -> - Default() - end. - --file("src/gleam/option.gleam", 188). -?DOC( - " Updates a value held within the `Some` of an `Option` by calling a given function\n" - " on it.\n" - "\n" - " If the `Option` is a `None` rather than `Some`, the function is not called and the\n" - " `Option` stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert map(over: Some(1), with: fn(x) { x + 1 }) == Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert map(over: None, with: fn(x) { x + 1 }) == None\n" - " ```\n" -). --spec map(option(FX), fun((FX) -> FZ)) -> option(FZ). -map(Option, Fun) -> - case Option of - {some, X} -> - {some, Fun(X)}; - - none -> - none - end. - --file("src/gleam/option.gleam", 211). -?DOC( - " Merges a nested `Option` into a single layer.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert flatten(Some(Some(1))) == Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert flatten(Some(None)) == None\n" - " ```\n" - "\n" - " ```gleam\n" - " assert flatten(None) == None\n" - " ```\n" -). --spec flatten(option(option(GB))) -> option(GB). -flatten(Option) -> - case Option of - {some, X} -> - X; - - none -> - none - end. - --file("src/gleam/option.gleam", 246). -?DOC( - " Updates a value held within the `Some` of an `Option` by calling a given function\n" - " on it, where the given function also returns an `Option`. The two options are\n" - " then merged together into one `Option`.\n" - "\n" - " If the `Option` is a `None` rather than `Some` the function is not called and the\n" - " option stays the same.\n" - "\n" - " This function is the equivalent of calling `map` followed by `flatten`, and\n" - " it is useful for chaining together multiple functions that return `Option`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert then(Some(1), fn(x) { Some(x + 1) }) == Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert then(Some(1), fn(x) { Some(#(\"a\", x)) }) == Some(#(\"a\", 1))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert then(Some(1), fn(_) { None }) == None\n" - " ```\n" - "\n" - " ```gleam\n" - " assert then(None, fn(x) { Some(x + 1) }) == None\n" - " ```\n" -). --spec then(option(GF), fun((GF) -> option(GH))) -> option(GH). -then(Option, Fun) -> - case Option of - {some, X} -> - Fun(X); - - none -> - none - end. - --file("src/gleam/option.gleam", 273). -?DOC( - " Returns the first value if it is `Some`, otherwise returns the second value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert or(Some(1), Some(2)) == Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(Some(1), None) == Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(None, Some(2)) == Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(None, None) == None\n" - " ```\n" -). --spec 'or'(option(GK), option(GK)) -> option(GK). -'or'(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second - end. - --file("src/gleam/option.gleam", 300). -?DOC( - " Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert lazy_or(Some(1), fn() { Some(2) }) == Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_or(Some(1), fn() { None }) == Some(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_or(None, fn() { Some(2) }) == Some(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_or(None, fn() { None }) == None\n" - " ```\n" -). --spec lazy_or(option(GO), fun(() -> option(GO))) -> option(GO). -lazy_or(First, Second) -> - case First of - {some, _} -> - First; - - none -> - Second() - end. - --file("src/gleam/option.gleam", 320). --spec values_loop(list(option(GW)), list(GW)) -> list(GW). -values_loop(List, Acc) -> - case List of - [] -> - lists:reverse(Acc); - - [none | Rest] -> - values_loop(Rest, Acc); - - [{some, First} | Rest@1] -> - values_loop(Rest@1, [First | Acc]) - end. - --file("src/gleam/option.gleam", 316). -?DOC( - " Given a list of `Option`s,\n" - " returns only the values inside `Some`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert values([Some(1), None, Some(3)]) == [1, 3]\n" - " ```\n" -). --spec values(list(option(GS))) -> list(GS). -values(Options) -> - values_loop(Options, []). diff --git a/ui/javascript/gleam_stdlib/gleam@order.erl b/ui/javascript/gleam_stdlib/gleam@order.erl deleted file mode 100644 index c4e87be..0000000 --- a/ui/javascript/gleam_stdlib/gleam@order.erl +++ /dev/null @@ -1,188 +0,0 @@ --module(gleam@order). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/order.gleam"). --export([negate/1, to_int/1, compare/2, reverse/1, break_tie/2, lazy_break_tie/2]). --export_type([order/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type order() :: lt | eq | gt. - --file("src/gleam/order.gleam", 32). -?DOC( - " Inverts an order, so less-than becomes greater-than and greater-than\n" - " becomes less-than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert negate(Lt) == Gt\n" - " ```\n" - "\n" - " ```gleam\n" - " assert negate(Eq) == Eq\n" - " ```\n" - "\n" - " ```gleam\n" - " assert negate(Gt) == Lt\n" - " ```\n" -). --spec negate(order()) -> order(). -negate(Order) -> - case Order of - lt -> - gt; - - eq -> - eq; - - gt -> - lt - end. - --file("src/gleam/order.gleam", 56). -?DOC( - " Produces a numeric representation of the order.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_int(Lt) == -1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_int(Eq) == 0\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_int(Gt) == 1\n" - " ```\n" -). --spec to_int(order()) -> integer(). -to_int(Order) -> - case Order of - lt -> - -1; - - eq -> - 0; - - gt -> - 1 - end. - --file("src/gleam/order.gleam", 72). -?DOC( - " Compares two `Order` values to one another, producing a new `Order`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert compare(Eq, with: Lt) == Gt\n" - " ```\n" -). --spec compare(order(), order()) -> order(). -compare(A, B) -> - case {A, B} of - {X, Y} when X =:= Y -> - eq; - - {lt, _} -> - lt; - - {eq, gt} -> - lt; - - {_, _} -> - gt - end. - --file("src/gleam/order.gleam", 92). -?DOC( - " Inverts an ordering function, so less-than becomes greater-than and greater-than\n" - " becomes less-than.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - " import gleam/list\n" - "\n" - " assert list.sort([1, 5, 4], by: reverse(int.compare)) == [5, 4, 1]\n" - " ```\n" -). --spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()). -reverse(Orderer) -> - fun(A, B) -> Orderer(B, A) end. - --file("src/gleam/order.gleam", 112). -?DOC( - " Return a fallback `Order` in case the first argument is `Eq`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert break_tie(in: int.compare(1, 1), with: Lt) == Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert break_tie(in: int.compare(1, 0), with: Eq) == Gt\n" - " ```\n" -). --spec break_tie(order(), order()) -> order(). -break_tie(Order, Other) -> - case Order of - lt -> - Order; - - gt -> - Order; - - eq -> - Other - end. - --file("src/gleam/order.gleam", 139). -?DOC( - " Invokes a fallback function returning an `Order` in case the first argument\n" - " is `Eq`.\n" - "\n" - " This can be useful when the fallback comparison might be expensive and it\n" - " needs to be delayed until strictly necessary.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt }) == Lt\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq }) == Gt\n" - " ```\n" -). --spec lazy_break_tie(order(), fun(() -> order())) -> order(). -lazy_break_tie(Order, Comparison) -> - case Order of - lt -> - Order; - - gt -> - Order; - - eq -> - Comparison() - end. diff --git a/ui/javascript/gleam_stdlib/gleam@pair.erl b/ui/javascript/gleam_stdlib/gleam@pair.erl deleted file mode 100644 index 68ac227..0000000 --- a/ui/javascript/gleam_stdlib/gleam@pair.erl +++ /dev/null @@ -1,104 +0,0 @@ --module(gleam@pair). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/pair.gleam"). --export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --file("src/gleam/pair.gleam", 9). -?DOC( - " Returns the first element in a pair.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert first(#(1, 2)) == 1\n" - " ```\n" -). --spec first({CLY, any()}) -> CLY. -first(Pair) -> - {A, _} = Pair, - A. - --file("src/gleam/pair.gleam", 22). -?DOC( - " Returns the second element in a pair.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert second(#(1, 2)) == 2\n" - " ```\n" -). --spec second({any(), CMB}) -> CMB. -second(Pair) -> - {_, A} = Pair, - A. - --file("src/gleam/pair.gleam", 35). -?DOC( - " Returns a new pair with the elements swapped.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert swap(#(1, 2)) == #(2, 1)\n" - " ```\n" -). --spec swap({CMC, CMD}) -> {CMD, CMC}. -swap(Pair) -> - {A, B} = Pair, - {B, A}. - --file("src/gleam/pair.gleam", 49). -?DOC( - " Returns a new pair with the first element having had `with` applied to\n" - " it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert #(1, 2) |> map_first(fn(n) { n * 2 }) == #(2, 2)\n" - " ```\n" -). --spec map_first({CME, CMF}, fun((CME) -> CMG)) -> {CMG, CMF}. -map_first(Pair, Fun) -> - {A, B} = Pair, - {Fun(A), B}. - --file("src/gleam/pair.gleam", 63). -?DOC( - " Returns a new pair with the second element having had `with` applied to\n" - " it.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert #(1, 2) |> map_second(fn(n) { n * 2 }) == #(1, 4)\n" - " ```\n" -). --spec map_second({CMH, CMI}, fun((CMI) -> CMJ)) -> {CMH, CMJ}. -map_second(Pair, Fun) -> - {A, B} = Pair, - {A, Fun(B)}. - --file("src/gleam/pair.gleam", 77). -?DOC( - " Returns a new pair with the given elements. This can also be done using the dedicated\n" - " syntax instead: `new(1, 2) == #(1, 2)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new(1, 2) == #(1, 2)\n" - " ```\n" -). --spec new(CMK, CML) -> {CMK, CML}. -new(First, Second) -> - {First, Second}. diff --git a/ui/javascript/gleam_stdlib/gleam@result.erl b/ui/javascript/gleam_stdlib/gleam@result.erl deleted file mode 100644 index 7aed253..0000000 --- a/ui/javascript/gleam_stdlib/gleam@result.erl +++ /dev/null @@ -1,500 +0,0 @@ --module(gleam@result). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/result.gleam"). --export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Result represents the result of something that may succeed or not.\n" - " `Ok` means it was successful, `Error` means it was not successful.\n" -). - --file("src/gleam/result.gleam", 18). -?DOC( - " Checks whether the result is an `Ok` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_ok(Ok(1))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_ok(Error(Nil))\n" - " ```\n" -). --spec is_ok({ok, any()} | {error, any()}) -> boolean(). -is_ok(Result) -> - case Result of - {error, _} -> - false; - - {ok, _} -> - true - end. - --file("src/gleam/result.gleam", 37). -?DOC( - " Checks whether the result is an `Error` value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !is_error(Ok(1))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert is_error(Error(Nil))\n" - " ```\n" -). --spec is_error({ok, any()} | {error, any()}) -> boolean(). -is_error(Result) -> - case Result of - {ok, _} -> - false; - - {error, _} -> - true - end. - --file("src/gleam/result.gleam", 60). -?DOC( - " Updates a value held within the `Ok` of a result by calling a given function\n" - " on it.\n" - "\n" - " If the result is an `Error` rather than `Ok` the function is not called and the\n" - " result stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert map(over: Ok(1), with: fn(x) { x + 1 }) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert map(over: Error(1), with: fn(x) { x + 1 }) == Error(1)\n" - " ```\n" -). --spec map({ok, CMV} | {error, CMW}, fun((CMV) -> CMZ)) -> {ok, CMZ} | - {error, CMW}. -map(Result, Fun) -> - case Result of - {ok, X} -> - {ok, Fun(X)}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 83). -?DOC( - " Updates a value held within the `Error` of a result by calling a given function\n" - " on it.\n" - "\n" - " If the result is `Ok` rather than `Error` the function is not called and the\n" - " result stays the same.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert map_error(over: Error(1), with: fn(x) { x + 1 }) == Error(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert map_error(over: Ok(1), with: fn(x) { x + 1 }) == Ok(1)\n" - " ```\n" -). --spec map_error({ok, CNC} | {error, CND}, fun((CND) -> CNG)) -> {ok, CNC} | - {error, CNG}. -map_error(Result, Fun) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, Error} -> - {error, Fun(Error)} - end. - --file("src/gleam/result.gleam", 109). -?DOC( - " Merges a nested `Result` into a single layer.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert flatten(Ok(Ok(1))) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert flatten(Ok(Error(\"\"))) == Error(\"\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert flatten(Error(Nil)) == Error(Nil)\n" - " ```\n" -). --spec flatten({ok, {ok, CNJ} | {error, CNK}} | {error, CNK}) -> {ok, CNJ} | - {error, CNK}. -flatten(Result) -> - case Result of - {ok, X} -> - X; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 143). -?DOC( - " \"Updates\" an `Ok` result by passing its value to a function that yields a result,\n" - " and returning the yielded result. (This may \"replace\" the `Ok` with an `Error`.)\n" - "\n" - " If the input is an `Error` rather than an `Ok`, the function is not called and\n" - " the original `Error` is returned.\n" - "\n" - " This function is the equivalent of calling `map` followed by `flatten`, and\n" - " it is useful for chaining together multiple functions that may fail.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert try(Ok(1), fn(x) { Ok(x + 1) }) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert try(Ok(1), fn(x) { Ok(#(\"a\", x)) }) == Ok(#(\"a\", 1))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert try(Ok(1), fn(_) { Error(\"Oh no\") }) == Error(\"Oh no\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert try(Error(Nil), fn(x) { Ok(x + 1) }) == Error(Nil)\n" - " ```\n" -). --spec 'try'({ok, CNR} | {error, CNS}, fun((CNR) -> {ok, CNV} | {error, CNS})) -> {ok, - CNV} | - {error, CNS}. -'try'(Result, Fun) -> - case Result of - {ok, X} -> - Fun(X); - - {error, E} -> - {error, E} - end. - --file("src/gleam/result.gleam", 166). -?DOC( - " Extracts the `Ok` value from a result, returning a default value if the result\n" - " is an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert unwrap(Ok(1), 0) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert unwrap(Error(\"\"), 0) == 0\n" - " ```\n" -). --spec unwrap({ok, COA} | {error, any()}, COA) -> COA. -unwrap(Result, Default) -> - case Result of - {ok, V} -> - V; - - {error, _} -> - Default - end. - --file("src/gleam/result.gleam", 186). -?DOC( - " Extracts the `Ok` value from a result, evaluating the default function if the result\n" - " is an `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert lazy_unwrap(Ok(1), fn() { 0 }) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_unwrap(Error(\"\"), fn() { 0 }) == 0\n" - " ```\n" -). --spec lazy_unwrap({ok, COE} | {error, any()}, fun(() -> COE)) -> COE. -lazy_unwrap(Result, Default) -> - case Result of - {ok, V} -> - V; - - {error, _} -> - Default() - end. - --file("src/gleam/result.gleam", 206). -?DOC( - " Extracts the `Error` value from a result, returning a default value if the result\n" - " is an `Ok`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert unwrap_error(Error(1), 0) == 1\n" - " ```\n" - "\n" - " ```gleam\n" - " assert unwrap_error(Ok(\"\"), 0) == 0\n" - " ```\n" -). --spec unwrap_error({ok, any()} | {error, COJ}, COJ) -> COJ. -unwrap_error(Result, Default) -> - case Result of - {ok, _} -> - Default; - - {error, E} -> - E - end. - --file("src/gleam/result.gleam", 233). -?DOC( - " Returns the first value if it is `Ok`, otherwise returns the second value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert or(Ok(1), Ok(2)) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(Ok(1), Error(\"Error 2\")) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(Error(\"Error 1\"), Ok(2)) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert or(Error(\"Error 1\"), Error(\"Error 2\")) == Error(\"Error 2\")\n" - " ```\n" -). --spec 'or'({ok, COM} | {error, CON}, {ok, COM} | {error, CON}) -> {ok, COM} | - {error, CON}. -'or'(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second - end. - --file("src/gleam/result.gleam", 263). -?DOC( - " Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value.\n" - "\n" - " If you need access to the initial error value, use `result.try_recover`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert lazy_or(Ok(1), fn() { Ok(2) }) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_or(Ok(1), fn() { Error(\"Error 2\") }) == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_or(Error(\"Error 1\"), fn() { Ok(2) }) == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert lazy_or(Error(\"Error 1\"), fn() { Error(\"Error 2\") })\n" - " == Error(\"Error 2\")\n" - " ```\n" -). --spec lazy_or({ok, COU} | {error, COV}, fun(() -> {ok, COU} | {error, COV})) -> {ok, - COU} | - {error, COV}. -lazy_or(First, Second) -> - case First of - {ok, _} -> - First; - - {error, _} -> - Second() - end. - --file("src/gleam/result.gleam", 287). -?DOC( - " Combines a list of results into a single result.\n" - " If all elements in the list are `Ok` then returns an `Ok` holding the list of values.\n" - " If any element is `Error` then returns the first error.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert all([Ok(1), Ok(2)]) == Ok([1, 2])\n" - " ```\n" - "\n" - " ```gleam\n" - " assert all([Ok(1), Error(\"e\")]) == Error(\"e\")\n" - " ```\n" -). --spec all(list({ok, CPC} | {error, CPD})) -> {ok, list(CPC)} | {error, CPD}. -all(Results) -> - gleam@list:try_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 307). --spec partition_loop(list({ok, CPR} | {error, CPS}), list(CPR), list(CPS)) -> {list(CPR), - list(CPS)}. -partition_loop(Results, Oks, Errors) -> - case Results of - [] -> - {Oks, Errors}; - - [{ok, A} | Rest] -> - partition_loop(Rest, [A | Oks], Errors); - - [{error, E} | Rest@1] -> - partition_loop(Rest@1, Oks, [E | Errors]) - end. - --file("src/gleam/result.gleam", 303). -?DOC( - " Given a list of results, returns a pair where the first element is a list\n" - " of all the values inside `Ok` and the second element is a list with all the\n" - " values inside `Error`. The values in both lists appear in reverse order with\n" - " respect to their position in the original list of results.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert partition([Ok(1), Error(\"a\"), Error(\"b\"), Ok(2)])\n" - " == #([2, 1], [\"b\", \"a\"])\n" - " ```\n" -). --spec partition(list({ok, CPK} | {error, CPL})) -> {list(CPK), list(CPL)}. -partition(Results) -> - partition_loop(Results, [], []). - --file("src/gleam/result.gleam", 327). -?DOC( - " Replace the value within a result\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert replace(Ok(1), Nil) == Ok(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert replace(Error(1), Nil) == Error(1)\n" - " ```\n" -). --spec replace({ok, any()} | {error, CQA}, CQD) -> {ok, CQD} | {error, CQA}. -replace(Result, Value) -> - case Result of - {ok, _} -> - {ok, Value}; - - {error, Error} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 346). -?DOC( - " Replace the error within a result\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert replace_error(Error(1), Nil) == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert replace_error(Ok(1), Nil) == Ok(1)\n" - " ```\n" -). --spec replace_error({ok, CQG} | {error, any()}, CQK) -> {ok, CQG} | {error, CQK}. -replace_error(Result, Error) -> - case Result of - {ok, X} -> - {ok, X}; - - {error, _} -> - {error, Error} - end. - --file("src/gleam/result.gleam", 361). -?DOC( - " Given a list of results, returns only the values inside `Ok`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert values([Ok(1), Error(\"a\"), Ok(3)]) == [1, 3]\n" - " ```\n" -). --spec values(list({ok, CQN} | {error, any()})) -> list(CQN). -values(Results) -> - gleam@list:filter_map(Results, fun(Result) -> Result end). - --file("src/gleam/result.gleam", 397). -?DOC( - " Updates a value held within the `Error` of a result by calling a given function\n" - " on it, where the given function also returns a result. The two results are\n" - " then merged together into one result.\n" - "\n" - " If the result is an `Ok` rather than `Error` the function is not called and the\n" - " result stays the same.\n" - "\n" - " This function is useful for chaining together computations that may fail\n" - " and trying to recover from possible errors.\n" - "\n" - " If you do not need access to the initial error value, use `result.lazy_or`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert Ok(1)\n" - " |> try_recover(with: fn(_) { Error(\"failed to recover\") })\n" - " == Ok(1)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert Error(1)\n" - " |> try_recover(with: fn(error) { Ok(error + 1) })\n" - " == Ok(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert Error(1)\n" - " |> try_recover(with: fn(error) { Error(\"failed to recover\") })\n" - " == Error(\"failed to recover\")\n" - " ```\n" -). --spec try_recover( - {ok, CQT} | {error, CQU}, - fun((CQU) -> {ok, CQT} | {error, CQX}) -) -> {ok, CQT} | {error, CQX}. -try_recover(Result, Fun) -> - case Result of - {ok, Value} -> - {ok, Value}; - - {error, Error} -> - Fun(Error) - end. diff --git a/ui/javascript/gleam_stdlib/gleam@set.erl b/ui/javascript/gleam_stdlib/gleam@set.erl deleted file mode 100644 index f461fe9..0000000 --- a/ui/javascript/gleam_stdlib/gleam@set.erl +++ /dev/null @@ -1,430 +0,0 @@ --module(gleam@set). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/set.gleam"). --export([new/0, size/1, is_empty/1, insert/2, contains/2, delete/2, to_list/1, from_list/1, fold/3, filter/2, map/2, drop/2, take/2, union/2, intersection/2, difference/2, is_subset/2, is_disjoint/2, symmetric_difference/2, each/2]). --export_type([set/1]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --opaque set(CVK) :: {set, gleam@dict:dict(CVK, list(nil))}. - --file("src/gleam/set.gleam", 32). -?DOC(" Creates a new empty set.\n"). --spec new() -> set(any()). -new() -> - {set, maps:new()}. - --file("src/gleam/set.gleam", 50). -?DOC( - " Gets the number of members in a set.\n" - "\n" - " This function runs in constant time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new()\n" - " |> insert(1)\n" - " |> insert(2)\n" - " |> size\n" - " == 2\n" - " ```\n" -). --spec size(set(any())) -> integer(). -size(Set) -> - maps:size(erlang:element(2, Set)). - --file("src/gleam/set.gleam", 66). -?DOC( - " Determines whether or not the set is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> is_empty\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !{ new() |> insert(1) |> is_empty }\n" - " ```\n" -). --spec is_empty(set(any())) -> boolean(). -is_empty(Set) -> - Set =:= new(). - --file("src/gleam/set.gleam", 84). -?DOC( - " Inserts a member into the set.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new()\n" - " |> insert(1)\n" - " |> insert(2)\n" - " |> size\n" - " == 2\n" - " ```\n" -). --spec insert(set(CVS), CVS) -> set(CVS). -insert(Set, Member) -> - {set, gleam@dict:insert(erlang:element(2, Set), Member, [])}. - --file("src/gleam/set.gleam", 108). -?DOC( - " Checks whether a set contains a given member.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new()\n" - " |> insert(2)\n" - " |> contains(2)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !{\n" - " new()\n" - " |> insert(2)\n" - " |> contains(1)\n" - " }\n" - " ```\n" -). --spec contains(set(CVV), CVV) -> boolean(). -contains(Set, Member) -> - _pipe = erlang:element(2, Set), - _pipe@1 = gleam_stdlib:map_get(_pipe, Member), - gleam@result:is_ok(_pipe@1). - --file("src/gleam/set.gleam", 130). -?DOC( - " Removes a member from a set. If the set does not contain the member then\n" - " the set is returned unchanged.\n" - "\n" - " This function runs in logarithmic time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !{\n" - " new()\n" - " |> insert(2)\n" - " |> delete(2)\n" - " |> contains(2)\n" - " }\n" - " ```\n" -). --spec delete(set(CVX), CVX) -> set(CVX). -delete(Set, Member) -> - {set, gleam@dict:delete(erlang:element(2, Set), Member)}. - --file("src/gleam/set.gleam", 147). -?DOC( - " Converts the set into a list of the contained members.\n" - "\n" - " The list has no specific ordering, any unintentional ordering may change in\n" - " future versions of Gleam or Erlang.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert new() |> insert(2) |> to_list == [2]\n" - " ```\n" -). --spec to_list(set(CWA)) -> list(CWA). -to_list(Set) -> - maps:keys(erlang:element(2, Set)). - --file("src/gleam/set.gleam", 168). -?DOC( - " Creates a new set of the members in a given list.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - " import gleam/list\n" - "\n" - " assert [1, 1, 2, 4, 3, 2]\n" - " |> from_list\n" - " |> to_list\n" - " |> list.sort(by: int.compare)\n" - " == [1, 2, 3, 4]\n" - " ```\n" -). --spec from_list(list(CWD)) -> set(CWD). -from_list(Members) -> - Dict = gleam@list:fold( - Members, - maps:new(), - fun(M, K) -> gleam@dict:insert(M, K, []) end - ), - {set, Dict}. - --file("src/gleam/set.gleam", 191). -?DOC( - " Combines all entries into a single value by calling a given function on each\n" - " one.\n" - "\n" - " Sets are not ordered so the values are not returned in any specific order.\n" - " Do not write code that relies on the order entries are used by this\n" - " function as it may change in later versions of Gleam or Erlang.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([1, 3, 9])\n" - " |> fold(0, fn(accumulator, member) { accumulator + member })\n" - " == 13\n" - " ```\n" -). --spec fold(set(CWG), CWI, fun((CWI, CWG) -> CWI)) -> CWI. -fold(Set, Initial, Reducer) -> - gleam@dict:fold( - erlang:element(2, Set), - Initial, - fun(A, K, _) -> Reducer(A, K) end - ). - --file("src/gleam/set.gleam", 215). -?DOC( - " Creates a new set from an existing set, minus any members that a given\n" - " function returns `False` for.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/int\n" - "\n" - " assert from_list([1, 4, 6, 3, 675, 44, 67])\n" - " |> filter(keeping: int.is_even)\n" - " |> to_list\n" - " == [4, 6, 44]\n" - " ```\n" -). --spec filter(set(CWJ), fun((CWJ) -> boolean())) -> set(CWJ). -filter(Set, Predicate) -> - {set, - gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}. - --file("src/gleam/set.gleam", 234). -?DOC( - " Creates a new set from a given set with the result of applying the given\n" - " function to each member.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([1, 2, 3, 4])\n" - " |> map(with: fn(x) { x * 2 })\n" - " |> to_list\n" - " == [2, 4, 6, 8]\n" - " ```\n" -). --spec map(set(CWM), fun((CWM) -> CWO)) -> set(CWO). -map(Set, Fun) -> - fold(Set, new(), fun(Acc, Member) -> insert(Acc, Fun(Member)) end). - --file("src/gleam/set.gleam", 252). -?DOC( - " Creates a new set from a given set with all the same entries except any\n" - " entry found on the given list.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([1, 2, 3, 4])\n" - " |> drop([1, 3])\n" - " |> to_list\n" - " == [2, 4]\n" - " ```\n" -). --spec drop(set(CWQ), list(CWQ)) -> set(CWQ). -drop(Set, Disallowed) -> - gleam@list:fold(Disallowed, Set, fun delete/2). - --file("src/gleam/set.gleam", 270). -?DOC( - " Creates a new set from a given set, only including any members which are in\n" - " a given list.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_list([1, 2, 3])\n" - " |> take([1, 3, 5])\n" - " |> to_list\n" - " == [1, 3]\n" - " ```\n" -). --spec take(set(CWU), list(CWU)) -> set(CWU). -take(Set, Desired) -> - {set, gleam@dict:take(erlang:element(2, Set), Desired)}. - --file("src/gleam/set.gleam", 290). --spec order(set(CXC), set(CXC)) -> {set(CXC), set(CXC)}. -order(First, Second) -> - case maps:size(erlang:element(2, First)) > maps:size( - erlang:element(2, Second) - ) of - true -> - {First, Second}; - - false -> - {Second, First} - end. - --file("src/gleam/set.gleam", 285). -?DOC( - " Creates a new set that contains all members of both given sets.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert union(from_list([1, 2]), from_list([2, 3])) |> to_list\n" - " == [1, 2, 3]\n" - " ```\n" -). --spec union(set(CWY), set(CWY)) -> set(CWY). -union(First, Second) -> - {Larger, Smaller} = order(First, Second), - fold(Smaller, Larger, fun insert/2). - --file("src/gleam/set.gleam", 308). -?DOC( - " Creates a new set that contains members that are present in both given sets.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert intersection(from_list([1, 2]), from_list([2, 3])) |> to_list\n" - " == [2]\n" - " ```\n" -). --spec intersection(set(CXH), set(CXH)) -> set(CXH). -intersection(First, Second) -> - {Larger, Smaller} = order(First, Second), - take(Larger, to_list(Smaller)). - --file("src/gleam/set.gleam", 326). -?DOC( - " Creates a new set that contains members that are present in the first set\n" - " but not the second.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list\n" - " == [1]\n" - " ```\n" -). --spec difference(set(CXL), set(CXL)) -> set(CXL). -difference(First, Second) -> - drop(First, to_list(Second)). - --file("src/gleam/set.gleam", 345). -?DOC( - " Determines if a set is fully contained by another.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_subset(from_list([1]), from_list([1, 2]))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_subset(from_list([1, 2, 3]), from_list([3, 4, 5]))\n" - " ```\n" -). --spec is_subset(set(CXP), set(CXP)) -> boolean(). -is_subset(First, Second) -> - intersection(First, Second) =:= First. - --file("src/gleam/set.gleam", 361). -?DOC( - " Determines if two sets contain no common members\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6]))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5]))\n" - " ```\n" -). --spec is_disjoint(set(CXS), set(CXS)) -> boolean(). -is_disjoint(First, Second) -> - intersection(First, Second) =:= new(). - --file("src/gleam/set.gleam", 376). -?DOC( - " Creates a new set that contains members that are present in either set, but\n" - " not both.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert symmetric_difference(from_list([1, 2, 3]), from_list([3, 4]))\n" - " |> to_list\n" - " == [1, 2, 4]\n" - " ```\n" -). --spec symmetric_difference(set(CXV), set(CXV)) -> set(CXV). -symmetric_difference(First, Second) -> - difference(union(First, Second), intersection(First, Second)). - --file("src/gleam/set.gleam", 405). -?DOC( - " Calls a function for each member in a set, discarding the return\n" - " value.\n" - "\n" - " Useful for producing a side effect for every item of a set.\n" - "\n" - " The order of elements in the iteration is an implementation detail that\n" - " should not be relied upon.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let set = from_list([\"apple\", \"banana\", \"cherry\"])\n" - "\n" - " assert each(set, io.println) == Nil\n" - " // apple\n" - " // banana\n" - " // cherry\n" - " ```\n" -). --spec each(set(CXZ), fun((CXZ) -> any())) -> nil. -each(Set, Fun) -> - fold( - Set, - nil, - fun(Nil, Member) -> - Fun(Member), - Nil - end - ). diff --git a/ui/javascript/gleam_stdlib/gleam@string.erl b/ui/javascript/gleam_stdlib/gleam@string.erl deleted file mode 100644 index 7d3d1a1..0000000 --- a/ui/javascript/gleam_stdlib/gleam@string.erl +++ /dev/null @@ -1,1006 +0,0 @@ --module(gleam@string). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/string.gleam"). --export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, slice/3, crop/2, byte_size/1, drop_start/2, drop_end/2, contains/2, starts_with/2, ends_with/2, pop_grapheme/1, to_graphemes/1, split/2, split_once/2, append/2, concat/1, repeat/2, join/2, pad_start/3, pad_end/3, trim_end/1, trim_start/1, trim/1, to_utf_codepoints/1, from_utf_codepoints/1, utf_codepoint/1, utf_codepoint_to_int/1, to_option/1, first/1, last/1, capitalise/1, inspect/1, remove_prefix/2, remove_suffix/2]). --export_type([direction/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Strings in Gleam are UTF-8 binaries. They can be written in your code as\n" - " text surrounded by `\"double quotes\"`.\n" -). - --type direction() :: leading | trailing. - --file("src/gleam/string.gleam", 21). -?DOC( - " Determines if a `String` is empty.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert is_empty(\"\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !is_empty(\"the world\")\n" - " ```\n" -). --spec is_empty(binary()) -> boolean(). -is_empty(Str) -> - Str =:= <<""/utf8>>. - --file("src/gleam/string.gleam", 46). -?DOC( - " Gets the number of grapheme clusters in a given `String`.\n" - "\n" - " This function has to iterate across the whole string to count the number of\n" - " graphemes, so it runs in linear time. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert length(\"Gleam\") == 5\n" - " ```\n" - "\n" - " ```gleam\n" - " assert length(\"ß↑e̊\") == 3\n" - " ```\n" - "\n" - " ```gleam\n" - " assert length(\"\") == 0\n" - " ```\n" -). --spec length(binary()) -> integer(). -length(String) -> - string:length(String). - --file("src/gleam/string.gleam", 59). -?DOC( - " Reverses a `String`.\n" - "\n" - " This function has to iterate across the whole `String` so it runs in linear\n" - " time. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert reverse(\"stressed\") == \"desserts\"\n" - " ```\n" -). --spec reverse(binary()) -> binary(). -reverse(String) -> - _pipe = String, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = string:reverse(_pipe@1), - unicode:characters_to_binary(_pipe@2). - --file("src/gleam/string.gleam", 78). -?DOC( - " Creates a new `String` by replacing all occurrences of a given substring.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert replace(\"www.example.com\", each: \".\", with: \"-\") == \"www-example-com\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert replace(\"a,b,c,d,e\", each: \",\", with: \"/\") == \"a/b/c/d/e\"\n" - " ```\n" -). --spec replace(binary(), binary(), binary()) -> binary(). -replace(String, Pattern, Substitute) -> - _pipe = String, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = gleam_stdlib:string_replace(_pipe@1, Pattern, Substitute), - unicode:characters_to_binary(_pipe@2). - --file("src/gleam/string.gleam", 102). -?DOC( - " Creates a new `String` with all the graphemes in the input `String` converted to\n" - " lowercase.\n" - "\n" - " Useful for case-insensitive comparisons.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert lowercase(\"X-FILES\") == \"x-files\"\n" - " ```\n" -). --spec lowercase(binary()) -> binary(). -lowercase(String) -> - string:lowercase(String). - --file("src/gleam/string.gleam", 117). -?DOC( - " Creates a new `String` with all the graphemes in the input `String` converted to\n" - " uppercase.\n" - "\n" - " Useful for case-insensitive comparisons and VIRTUAL YELLING.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert uppercase(\"skinner\") == \"SKINNER\"\n" - " ```\n" -). --spec uppercase(binary()) -> binary(). -uppercase(String) -> - string:uppercase(String). - --file("src/gleam/string.gleam", 137). -?DOC( - " Compares two `String`s to see which is \"larger\" by comparing their graphemes.\n" - "\n" - " This does not compare the size or length of the given `String`s.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " import gleam/order\n" - "\n" - " assert compare(\"Anthony\", \"Anthony\") == order.Eq\n" - " ```\n" - "\n" - " ```gleam\n" - " import gleam/order\n" - "\n" - " assert compare(\"A\", \"B\") == order.Lt\n" - " ```\n" -). --spec compare(binary(), binary()) -> gleam@order:order(). -compare(A, B) -> - case A =:= B of - true -> - eq; - - _ -> - case gleam_stdlib:less_than(A, B) of - true -> - lt; - - false -> - gt - end - end. - --file("src/gleam/string.gleam", 181). -?DOC( - " Takes a substring given a start grapheme index and a length. Negative indexes\n" - " are taken starting from the *end* of the string.\n" - "\n" - " This function runs in linear time with the size of the index and the\n" - " length. Negative indexes are linear with the size of the input string in\n" - " addition to the other costs.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert slice(from: \"gleam\", at_index: 1, length: 2) == \"le\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert slice(from: \"gleam\", at_index: 1, length: 10) == \"leam\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert slice(from: \"gleam\", at_index: 10, length: 3) == \"\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert slice(from: \"gleam\", at_index: -2, length: 2) == \"am\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert slice(from: \"gleam\", at_index: -12, length: 2) == \"\"\n" - " ```\n" -). --spec slice(binary(), integer(), integer()) -> binary(). -slice(String, Idx, Len) -> - case Len =< 0 of - true -> - <<""/utf8>>; - - false -> - case Idx < 0 of - true -> - Translated_idx = string:length(String) + Idx, - case Translated_idx < 0 of - true -> - <<""/utf8>>; - - false -> - gleam_stdlib:slice(String, Translated_idx, Len) - end; - - false -> - gleam_stdlib:slice(String, Idx, Len) - end - end. - --file("src/gleam/string.gleam", 218). -?DOC( - " Drops contents of the first `String` that occur before the second `String`.\n" - " If the `from` string does not contain the `before` string, `from` is\n" - " returned unchanged.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert crop(from: \"The Lone Gunmen\", before: \"Lone\") == \"Lone Gunmen\"\n" - " ```\n" -). --spec crop(binary(), binary()) -> binary(). -crop(String, Substring) -> - gleam_stdlib:crop_string(String, Substring). - --file("src/gleam/string.gleam", 852). -?DOC( - " Returns the number of bytes in a `String`.\n" - "\n" - " This function runs in constant time on Erlang and in linear time on\n" - " JavaScript.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert byte_size(\"🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻\") == 58\n" - " ```\n" -). --spec byte_size(binary()) -> integer(). -byte_size(String) -> - erlang:byte_size(String). - --file("src/gleam/string.gleam", 230). -?DOC( - " Drops *n* graphemes from the start of a `String`.\n" - "\n" - " This function runs in linear time with the number of graphemes to drop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert drop_start(from: \"The Lone Gunmen\", up_to: 2) == \"e Lone Gunmen\"\n" - " ```\n" -). --spec drop_start(binary(), integer()) -> binary(). -drop_start(String, Num_graphemes) -> - case Num_graphemes =< 0 of - true -> - String; - - false -> - Prefix = gleam_stdlib:slice(String, 0, Num_graphemes), - Prefix_size = erlang:byte_size(Prefix), - binary:part( - String, - Prefix_size, - erlang:byte_size(String) - Prefix_size - ) - end. - --file("src/gleam/string.gleam", 253). -?DOC( - " Drops *n* graphemes from the end of a `String`.\n" - "\n" - " This function traverses the full string, so it runs in linear time with the\n" - " size of the string. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert drop_end(from: \"Cigarette Smoking Man\", up_to: 2)\n" - " == \"Cigarette Smoking M\"\n" - " ```\n" -). --spec drop_end(binary(), integer()) -> binary(). -drop_end(String, Num_graphemes) -> - case Num_graphemes =< 0 of - true -> - String; - - false -> - slice(String, 0, string:length(String) - Num_graphemes) - end. - --file("src/gleam/string.gleam", 278). -?DOC( - " Checks if the first `String` contains the second.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert contains(does: \"theory\", contain: \"ory\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert contains(does: \"theory\", contain: \"the\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert !contains(does: \"theory\", contain: \"THE\")\n" - " ```\n" -). --spec contains(binary(), binary()) -> boolean(). -contains(Haystack, Needle) -> - gleam_stdlib:contains_string(Haystack, Needle). - --file("src/gleam/string.gleam", 290). -?DOC( - " Checks whether the first `String` starts with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !starts_with(\"theory\", \"ory\")\n" - " ```\n" -). --spec starts_with(binary(), binary()) -> boolean(). -starts_with(String, Prefix) -> - gleam_stdlib:string_starts_with(String, Prefix). - --file("src/gleam/string.gleam", 302). -?DOC( - " Checks whether the first `String` ends with the second one.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert ends_with(\"theory\", \"ory\")\n" - " ```\n" -). --spec ends_with(binary(), binary()) -> boolean(). -ends_with(String, Suffix) -> - gleam_stdlib:string_ends_with(String, Suffix). - --file("src/gleam/string.gleam", 594). -?DOC( - " Splits a non-empty `String` into its first element (head) and rest (tail).\n" - " This lets you pattern match on `String`s exactly as you would with lists.\n" - "\n" - " ## Performance\n" - "\n" - " There is a notable overhead to using this function, so you may not want to\n" - " use it in a tight loop. If you wish to efficiently parse a string you may\n" - " want to use alternatives such as the [splitter package](https://hex.pm/packages/splitter).\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert pop_grapheme(\"gleam\") == Ok(#(\"g\", \"leam\"))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert pop_grapheme(\"\") == Error(Nil)\n" - " ```\n" -). --spec pop_grapheme(binary()) -> {ok, {binary(), binary()}} | {error, nil}. -pop_grapheme(String) -> - gleam_stdlib:string_pop_grapheme(String). - --file("src/gleam/string.gleam", 610). --spec to_graphemes_loop(binary(), list(binary())) -> list(binary()). -to_graphemes_loop(String, Acc) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {Grapheme, Rest}} -> - to_graphemes_loop(Rest, [Grapheme | Acc]); - - {error, _} -> - Acc - end. - --file("src/gleam/string.gleam", 604). -?DOC( - " Converts a `String` to a list of\n" - " [graphemes](https://en.wikipedia.org/wiki/Grapheme).\n" - "\n" - " ```gleam\n" - " assert to_graphemes(\"abc\") == [\"a\", \"b\", \"c\"]\n" - " ```\n" -). --spec to_graphemes(binary()) -> list(binary()). -to_graphemes(String) -> - _pipe = String, - _pipe@1 = to_graphemes_loop(_pipe, []), - lists:reverse(_pipe@1). - --file("src/gleam/string.gleam", 313). -?DOC( - " Creates a list of `String`s by splitting a given string on a given substring.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert split(\"home/gleam/desktop/\", on: \"/\")\n" - " == [\"home\", \"gleam\", \"desktop\", \"\"]\n" - " ```\n" -). --spec split(binary(), binary()) -> list(binary()). -split(X, Substring) -> - case Substring of - <<""/utf8>> -> - to_graphemes(X); - - _ -> - _pipe = X, - _pipe@1 = gleam_stdlib:identity(_pipe), - _pipe@2 = gleam@string_tree:split(_pipe@1, Substring), - gleam@list:map(_pipe@2, fun unicode:characters_to_binary/1) - end. - --file("src/gleam/string.gleam", 340). -?DOC( - " Splits a `String` a single time on the given substring.\n" - "\n" - " Returns an `Error` if substring not present.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert split_once(\"home/gleam/desktop/\", on: \"/\")\n" - " == Ok(#(\"home\", \"gleam/desktop/\"))\n" - " ```\n" - "\n" - " ```gleam\n" - " assert split_once(\"home/gleam/desktop/\", on: \"?\") == Error(Nil)\n" - " ```\n" -). --spec split_once(binary(), binary()) -> {ok, {binary(), binary()}} | - {error, nil}. -split_once(String, Substring) -> - case string:split(String, Substring) of - [First, Rest] -> - {ok, {First, Rest}}; - - _ -> - {error, nil} - end. - --file("src/gleam/string.gleam", 370). -?DOC( - " Creates a new `String` by joining two `String`s together.\n" - "\n" - " This function typically copies both `String`s and runs in linear time, but\n" - " the exact behaviour will depend on how the runtime you are using optimises\n" - " your code. Benchmark and profile your code if you need to understand its\n" - " performance better.\n" - "\n" - " If you are joining together large string and want to avoid copying any data\n" - " you may want to investigate using the [`string_tree`](../gleam/string_tree.html)\n" - " module.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert append(to: \"butter\", suffix: \"fly\") == \"butterfly\"\n" - " ```\n" -). --spec append(binary(), binary()) -> binary(). -append(First, Second) -> - <>. - --file("src/gleam/string.gleam", 389). --spec concat_loop(list(binary()), binary()) -> binary(). -concat_loop(Strings, Accumulator) -> - case Strings of - [String | Strings@1] -> - concat_loop(Strings@1, <>); - - [] -> - Accumulator - end. - --file("src/gleam/string.gleam", 385). -?DOC( - " Creates a new `String` by joining many `String`s together.\n" - "\n" - " This function copies all the `String`s and runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert concat([\"never\", \"the\", \"less\"]) == \"nevertheless\"\n" - " ```\n" -). --spec concat(list(binary())) -> binary(). -concat(Strings) -> - erlang:list_to_binary(Strings). - --file("src/gleam/string.gleam", 413). --spec repeat_loop(integer(), binary(), binary()) -> binary(). -repeat_loop(Times, Doubling_acc, Acc) -> - Acc@1 = case Times rem 2 of - 0 -> - Acc; - - _ -> - <> - end, - Times@1 = Times div 2, - case Times@1 =< 0 of - true -> - Acc@1; - - false -> - repeat_loop( - Times@1, - <>, - Acc@1 - ) - end. - --file("src/gleam/string.gleam", 406). -?DOC( - " Creates a new `String` by repeating a `String` a given number of times.\n" - "\n" - " This function runs in loglinear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert repeat(\"ha\", times: 3) == \"hahaha\"\n" - " ```\n" -). --spec repeat(binary(), integer()) -> binary(). -repeat(String, Times) -> - case Times =< 0 of - true -> - <<""/utf8>>; - - false -> - repeat_loop(Times, String, <<""/utf8>>) - end. - --file("src/gleam/string.gleam", 442). --spec join_loop(list(binary()), binary(), binary()) -> binary(). -join_loop(Strings, Separator, Accumulator) -> - case Strings of - [] -> - Accumulator; - - [String | Strings@1] -> - join_loop( - Strings@1, - Separator, - <<<>/binary, - String/binary>> - ) - end. - --file("src/gleam/string.gleam", 435). -?DOC( - " Joins many `String`s together with a given separator.\n" - "\n" - " This function runs in linear time.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert join([\"home\",\"evan\",\"Desktop\"], with: \"/\") == \"home/evan/Desktop\"\n" - " ```\n" -). --spec join(list(binary()), binary()) -> binary(). -join(Strings, Separator) -> - case Strings of - [] -> - <<""/utf8>>; - - [First | Rest] -> - join_loop(Rest, Separator, First) - end. - --file("src/gleam/string.gleam", 514). --spec padding(integer(), binary()) -> binary(). -padding(Size, Pad_string) -> - Pad_string_length = string:length(Pad_string), - Num_pads = case Pad_string_length of - 0 -> 0; - Gleam@denominator -> Size div Gleam@denominator - end, - Extra = case Pad_string_length of - 0 -> 0; - Gleam@denominator@1 -> Size rem Gleam@denominator@1 - end, - <<(repeat(Pad_string, Num_pads))/binary, - (slice(Pad_string, 0, Extra))/binary>>. - --file("src/gleam/string.gleam", 470). -?DOC( - " Pads the start of a `String` until it has a given length.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert pad_start(\"121\", to: 5, with: \".\") == \"..121\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert pad_start(\"121\", to: 3, with: \".\") == \"121\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert pad_start(\"121\", to: 2, with: \".\") == \"121\"\n" - " ```\n" -). --spec pad_start(binary(), integer(), binary()) -> binary(). -pad_start(String, Desired_length, Pad_string) -> - Current_length = string:length(String), - To_pad_length = Desired_length - Current_length, - case To_pad_length =< 0 of - true -> - String; - - false -> - <<(padding(To_pad_length, Pad_string))/binary, String/binary>> - end. - --file("src/gleam/string.gleam", 500). -?DOC( - " Pads the end of a `String` until it has a given length.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert pad_end(\"123\", to: 5, with: \".\") == \"123..\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert pad_end(\"123\", to: 3, with: \".\") == \"123\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert pad_end(\"123\", to: 2, with: \".\") == \"123\"\n" - " ```\n" -). --spec pad_end(binary(), integer(), binary()) -> binary(). -pad_end(String, Desired_length, Pad_string) -> - Current_length = string:length(String), - To_pad_length = Desired_length - Current_length, - case To_pad_length =< 0 of - true -> - String; - - false -> - <> - end. - --file("src/gleam/string.gleam", 569). -?DOC( - " Removes whitespace at the end of a `String`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert trim_end(\" hats \\n\") == \" hats\"\n" - " ```\n" -). --spec trim_end(binary()) -> binary(). -trim_end(String) -> - string:trim(String, trailing). - --file("src/gleam/string.gleam", 556). -?DOC( - " Removes whitespace at the start of a `String`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert trim_start(\" hats \\n\") == \"hats \\n\"\n" - " ```\n" -). --spec trim_start(binary()) -> binary(). -trim_start(String) -> - string:trim(String, leading). - --file("src/gleam/string.gleam", 535). -?DOC( - " Removes whitespace on both sides of a `String`.\n" - "\n" - " Whitespace in this function is the set of nonbreakable whitespace\n" - " codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1].\n" - "\n" - " [1]: https://unicode.org/reports/tr31/\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert trim(\" hats \\n\") == \"hats\"\n" - " ```\n" -). --spec trim(binary()) -> binary(). -trim(String) -> - _pipe = String, - _pipe@1 = trim_start(_pipe), - trim_end(_pipe@1). - --file("src/gleam/string.gleam", 656). --spec to_utf_codepoints_loop(bitstring(), list(integer())) -> list(integer()). -to_utf_codepoints_loop(Bit_array, Acc) -> - case Bit_array of - <> -> - to_utf_codepoints_loop(Rest, [First | Acc]); - - _ -> - lists:reverse(Acc) - end. - --file("src/gleam/string.gleam", 651). --spec do_to_utf_codepoints(binary()) -> list(integer()). -do_to_utf_codepoints(String) -> - to_utf_codepoints_loop(<>, []). - --file("src/gleam/string.gleam", 646). -?DOC( - " Converts a `String` to a `List` of `UtfCodepoint`.\n" - "\n" - " See and\n" - " for an\n" - " explanation on code points.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert \"a\" |> to_utf_codepoints == [UtfCodepoint(97)]\n" - " ```\n" - "\n" - " ```gleam\n" - " // Semantically the same as:\n" - " // [\"🏳\", \"️\", \"‍\", \"🌈\"] or:\n" - " // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow]\n" - " assert \"🏳️‍🌈\" |> to_utf_codepoints\n" - " == [\n" - " UtfCodepoint(127987),\n" - " UtfCodepoint(65039),\n" - " UtfCodepoint(8205),\n" - " UtfCodepoint(127752),\n" - " ]\n" - " ```\n" -). --spec to_utf_codepoints(binary()) -> list(integer()). -to_utf_codepoints(String) -> - do_to_utf_codepoints(String). - --file("src/gleam/string.gleam", 695). -?DOC( - " Converts a `List` of `UtfCodepoint`s to a `String`.\n" - "\n" - " See and\n" - " for an\n" - " explanation on code points.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(a) = utf_codepoint(97)\n" - " let assert Ok(b) = utf_codepoint(98)\n" - " let assert Ok(c) = utf_codepoint(99)\n" - " assert from_utf_codepoints([a, b, c]) == \"abc\"\n" - " ```\n" -). --spec from_utf_codepoints(list(integer())) -> binary(). -from_utf_codepoints(Utf_codepoints) -> - gleam_stdlib:utf_codepoint_list_to_string(Utf_codepoints). - --file("src/gleam/string.gleam", 701). -?DOC( - " Converts an integer to a `UtfCodepoint`.\n" - "\n" - " Returns an `Error` if the integer does not represent a valid UTF codepoint.\n" -). --spec utf_codepoint(integer()) -> {ok, integer()} | {error, nil}. -utf_codepoint(Value) -> - case Value of - I when I > 1114111 -> - {error, nil}; - - I@1 when (I@1 >= 55296) andalso (I@1 =< 57343) -> - {error, nil}; - - I@2 when I@2 < 0 -> - {error, nil}; - - I@3 -> - {ok, gleam_stdlib:identity(I@3)} - end. - --file("src/gleam/string.gleam", 721). -?DOC( - " Converts a `UtfCodepoint` to its ordinal code point value.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert [utf_codepoint, ..] = to_utf_codepoints(\"💜\")\n" - " assert utf_codepoint_to_int(utf_codepoint) == 128156\n" - " ```\n" -). --spec utf_codepoint_to_int(integer()) -> integer(). -utf_codepoint_to_int(Cp) -> - gleam_stdlib:identity(Cp). - --file("src/gleam/string.gleam", 736). -?DOC( - " Converts a `String` into `Option(String)` where an empty `String` becomes\n" - " `None`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert to_option(\"\") == None\n" - " ```\n" - "\n" - " ```gleam\n" - " assert to_option(\"hats\") == Some(\"hats\")\n" - " ```\n" -). --spec to_option(binary()) -> gleam@option:option(binary()). -to_option(String) -> - case String of - <<""/utf8>> -> - none; - - _ -> - {some, String} - end. - --file("src/gleam/string.gleam", 757). -?DOC( - " Returns the first grapheme cluster in a given `String` and wraps it in a\n" - " `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.\n" - " Otherwise, it returns `Ok(String)`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert first(\"\") == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert first(\"icecream\") == Ok(\"i\")\n" - " ```\n" -). --spec first(binary()) -> {ok, binary()} | {error, nil}. -first(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, _}} -> - {ok, First}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/string.gleam", 781). -?DOC( - " Returns the last grapheme cluster in a given `String` and wraps it in a\n" - " `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.\n" - " Otherwise, it returns `Ok(String)`.\n" - "\n" - " This function traverses the full string, so it runs in linear time with the\n" - " length of the string. Avoid using this in a loop.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert last(\"\") == Error(Nil)\n" - " ```\n" - "\n" - " ```gleam\n" - " assert last(\"icecream\") == Ok(\"m\")\n" - " ```\n" -). --spec last(binary()) -> {ok, binary()} | {error, nil}. -last(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, <<""/utf8>>}} -> - {ok, First}; - - {ok, {_, Rest}} -> - {ok, slice(Rest, -1, 1)}; - - {error, E} -> - {error, E} - end. - --file("src/gleam/string.gleam", 798). -?DOC( - " Creates a new `String` with the first grapheme in the input `String`\n" - " converted to uppercase and the remaining graphemes to lowercase.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert capitalise(\"mamouna\") == \"Mamouna\"\n" - " ```\n" -). --spec capitalise(binary()) -> binary(). -capitalise(String) -> - case gleam_stdlib:string_pop_grapheme(String) of - {ok, {First, Rest}} -> - append(string:uppercase(First), string:lowercase(Rest)); - - {error, _} -> - <<""/utf8>> - end. - --file("src/gleam/string.gleam", 829). -?DOC( - " Returns a `String` representation of a term in Gleam syntax.\n" - "\n" - " This may be occasionally useful for quick-and-dirty printing of values in\n" - " scripts. For error reporting and other uses prefer constructing strings by\n" - " pattern matching on the values.\n" - "\n" - " ## Limitations\n" - "\n" - " The output format of this function is not stable and could change at any\n" - " time. The output is not suitable for parsing.\n" - "\n" - " This function works using runtime reflection, so the output may not be\n" - " perfectly accurate for data structures where the runtime structure doesn't\n" - " hold enough information to determine the original syntax. For example,\n" - " tuples with an Erlang atom in the first position will be mistaken for Gleam\n" - " records.\n" - "\n" - " ## Security and safety\n" - "\n" - " There is no limit to how large the strings that this function can produce.\n" - " Be careful not to call this function with large data structures or you\n" - " could use very large amounts of memory, potentially causing runtime\n" - " problems.\n" -). --spec inspect(any()) -> binary(). -inspect(Term) -> - _pipe = Term, - _pipe@1 = gleam_stdlib:inspect(_pipe), - unicode:characters_to_binary(_pipe@1). - --file("src/gleam/string.gleam", 871). -?DOC( - " Removes the given prefix from the start of a `String`, if present.\n" - "\n" - " If the `String` does not start with the given prefix the string is returned\n" - " unchanged.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert remove_prefix(\"@lpil\", \"@\") == \"lpil\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remove_prefix(\"hello!\", \"@\") == \"hello!\"\n" - " ```\n" -). --spec remove_prefix(binary(), binary()) -> binary(). -remove_prefix(String, Prefix) -> - gleam_stdlib:string_remove_prefix(String, Prefix). - --file("src/gleam/string.gleam", 890). -?DOC( - " Removes the given suffix from the end of a `String`, if present.\n" - "\n" - " If the `String` does not end with the given suffix the string is returned\n" - " unchanged.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert remove_suffix(\"Hello!\", \"!\") == \"Hello\"\n" - " ```\n" - "\n" - " ```gleam\n" - " assert remove_suffix(\"Hello!?\", \"!\") == \"Hello!?\"\n" - " ```\n" -). --spec remove_suffix(binary(), binary()) -> binary(). -remove_suffix(String, Suffix) -> - gleam_stdlib:string_remove_suffix(String, Suffix). diff --git a/ui/javascript/gleam_stdlib/gleam@string_tree.erl b/ui/javascript/gleam_stdlib/gleam@string_tree.erl deleted file mode 100644 index 2b09b6c..0000000 --- a/ui/javascript/gleam_stdlib/gleam@string_tree.erl +++ /dev/null @@ -1,202 +0,0 @@ --module(gleam@string_tree). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/string_tree.gleam"). --export([from_strings/1, new/0, from_string/1, append_tree/2, prepend/2, append/2, prepend_tree/2, concat/1, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]). --export_type([string_tree/0, direction/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type string_tree() :: any(). - --type direction() :: all. - --file("src/gleam/string_tree.gleam", 69). -?DOC( - " Converts a list of strings into a `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec from_strings(list(binary())) -> string_tree(). -from_strings(Strings) -> - gleam_stdlib:identity(Strings). - --file("src/gleam/string_tree.gleam", 24). -?DOC( - " Create an empty `StringTree`. Useful as the start of a pipe chaining many\n" - " trees together.\n" -). --spec new() -> string_tree(). -new() -> - gleam_stdlib:identity([]). - --file("src/gleam/string_tree.gleam", 85). -?DOC( - " Converts a string into a `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec from_string(binary()) -> string_tree(). -from_string(String) -> - gleam_stdlib:identity(String). - --file("src/gleam/string_tree.gleam", 61). -?DOC( - " Appends some `StringTree` onto the end of another.\n" - "\n" - " Runs in constant time.\n" -). --spec append_tree(string_tree(), string_tree()) -> string_tree(). -append_tree(Tree, Suffix) -> - gleam_stdlib:iodata_append(Tree, Suffix). - --file("src/gleam/string_tree.gleam", 32). -?DOC( - " Prepends a `String` onto the start of some `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend(string_tree(), binary()) -> string_tree(). -prepend(Tree, Prefix) -> - gleam_stdlib:iodata_append(gleam_stdlib:identity(Prefix), Tree). - --file("src/gleam/string_tree.gleam", 40). -?DOC( - " Appends a `String` onto the end of some `StringTree`.\n" - "\n" - " Runs in constant time.\n" -). --spec append(string_tree(), binary()) -> string_tree(). -append(Tree, Second) -> - gleam_stdlib:iodata_append(Tree, gleam_stdlib:identity(Second)). - --file("src/gleam/string_tree.gleam", 48). -?DOC( - " Prepends some `StringTree` onto the start of another.\n" - "\n" - " Runs in constant time.\n" -). --spec prepend_tree(string_tree(), string_tree()) -> string_tree(). -prepend_tree(Tree, Prefix) -> - gleam_stdlib:iodata_append(Prefix, Tree). - --file("src/gleam/string_tree.gleam", 77). -?DOC( - " Joins a list of trees into a single tree.\n" - "\n" - " Runs in constant time.\n" -). --spec concat(list(string_tree())) -> string_tree(). -concat(Trees) -> - gleam_stdlib:identity(Trees). - --file("src/gleam/string_tree.gleam", 94). -?DOC( - " Turns a `StringTree` into a `String`.\n" - "\n" - " This function is implemented natively by the virtual machine and is highly\n" - " optimised.\n" -). --spec to_string(string_tree()) -> binary(). -to_string(Tree) -> - unicode:characters_to_binary(Tree). - --file("src/gleam/string_tree.gleam", 100). -?DOC(" Returns the size of the `StringTree` in bytes.\n"). --spec byte_size(string_tree()) -> integer(). -byte_size(Tree) -> - erlang:iolist_size(Tree). - --file("src/gleam/string_tree.gleam", 104). -?DOC(" Joins the given trees into a new tree separated with the given string.\n"). --spec join(list(string_tree()), binary()) -> string_tree(). -join(Trees, Sep) -> - _pipe = Trees, - _pipe@1 = gleam@list:intersperse(_pipe, gleam_stdlib:identity(Sep)), - gleam_stdlib:identity(_pipe@1). - --file("src/gleam/string_tree.gleam", 115). -?DOC( - " Converts a `StringTree` to a new one where the contents have been\n" - " lowercased.\n" -). --spec lowercase(string_tree()) -> string_tree(). -lowercase(Tree) -> - string:lowercase(Tree). - --file("src/gleam/string_tree.gleam", 122). -?DOC( - " Converts a `StringTree` to a new one where the contents have been\n" - " uppercased.\n" -). --spec uppercase(string_tree()) -> string_tree(). -uppercase(Tree) -> - string:uppercase(Tree). - --file("src/gleam/string_tree.gleam", 127). -?DOC(" Converts a `StringTree` to a new one with the contents reversed.\n"). --spec reverse(string_tree()) -> string_tree(). -reverse(Tree) -> - string:reverse(Tree). - --file("src/gleam/string_tree.gleam", 145). -?DOC(" Splits a `StringTree` on a given pattern into a list of trees.\n"). --spec split(string_tree(), binary()) -> list(string_tree()). -split(Tree, Pattern) -> - string:split(Tree, Pattern, all). - --file("src/gleam/string_tree.gleam", 156). -?DOC(" Replaces all instances of a pattern with a given string substitute.\n"). --spec replace(string_tree(), binary(), binary()) -> string_tree(). -replace(Tree, Pattern, Substitute) -> - gleam_stdlib:string_replace(Tree, Pattern, Substitute). - --file("src/gleam/string_tree.gleam", 180). -?DOC( - " Compares two string trees to determine if they have the same textual\n" - " content.\n" - "\n" - " Comparing two string trees using the `==` operator may return `False` even\n" - " if they have the same content as they may have been built in different ways,\n" - " so using this function is often preferred.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert from_strings([\"a\", \"b\"]) != from_string(\"ab\")\n" - " ```\n" - "\n" - " ```gleam\n" - " assert is_equal(from_strings([\"a\", \"b\"]), from_string(\"ab\"))\n" - " ```\n" -). --spec is_equal(string_tree(), string_tree()) -> boolean(). -is_equal(A, B) -> - string:equal(A, B). - --file("src/gleam/string_tree.gleam", 201). -?DOC( - " Inspects a `StringTree` to determine if it is equivalent to an empty string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert !{ from_string(\"ok\") |> is_empty }\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_string(\"\") |> is_empty\n" - " ```\n" - "\n" - " ```gleam\n" - " assert from_strings([]) |> is_empty\n" - " ```\n" -). --spec is_empty(string_tree()) -> boolean(). -is_empty(Tree) -> - string:is_empty(Tree). diff --git a/ui/javascript/gleam_stdlib/gleam@uri.erl b/ui/javascript/gleam_stdlib/gleam@uri.erl deleted file mode 100644 index 2124ff7..0000000 --- a/ui/javascript/gleam_stdlib/gleam@uri.erl +++ /dev/null @@ -1,1042 +0,0 @@ --module(gleam@uri). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleam/uri.gleam"). --export([parse/1, parse_query/1, percent_encode/1, query_to_string/1, percent_decode/1, path_segments/1, to_string/1, origin/1, merge/2]). --export_type([uri/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC( - " Utilities for working with URIs\n" - "\n" - " This module provides functions for working with URIs (for example, parsing\n" - " URIs or encoding query strings). The functions in this module are implemented\n" - " according to [RFC 3986](https://tools.ietf.org/html/rfc3986).\n" - "\n" - " Query encoding (Form encoding) is defined in the\n" - " [W3C specification](https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data).\n" -). - --type uri() :: {uri, - gleam@option:option(binary()), - gleam@option:option(binary()), - gleam@option:option(binary()), - gleam@option:option(integer()), - binary(), - gleam@option:option(binary()), - gleam@option:option(binary())}. - --file("src/gleam/uri.gleam", 506). --spec parse_fragment(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_fragment(Rest, Pieces) -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - {some, Rest}}}. - --file("src/gleam/uri.gleam", 478). --spec parse_query_with_question_mark_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_query_with_question_mark_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"#"/utf8, Rest/binary>> when Size =:= 0 -> - parse_fragment(Rest, Pieces); - - <<"#"/utf8, Rest@1/binary>> -> - Query = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - {some, Query}, - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@1); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - {some, Original}, - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_query_with_question_mark_loop( - Original, - Rest@2, - Pieces, - Size + 1 - ) - end. - --file("src/gleam/uri.gleam", 471). --spec parse_query_with_question_mark(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_query_with_question_mark(Uri_string, Pieces) -> - parse_query_with_question_mark_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 437). --spec parse_path_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_path_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"?"/utf8, Rest/binary>> -> - Path = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Path, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest, Pieces@1); - - <<"#"/utf8, Rest@1/binary>> -> - Path@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Path@1, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@2); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Original, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_path_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 433). --spec parse_path(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_path(Uri_string, Pieces) -> - parse_path_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 388). --spec parse_port_loop(binary(), uri(), integer()) -> {ok, uri()} | {error, nil}. -parse_port_loop(Uri_string, Pieces, Port) -> - case Uri_string of - <<"0"/utf8, Rest/binary>> -> - parse_port_loop(Rest, Pieces, Port * 10); - - <<"1"/utf8, Rest@1/binary>> -> - parse_port_loop(Rest@1, Pieces, (Port * 10) + 1); - - <<"2"/utf8, Rest@2/binary>> -> - parse_port_loop(Rest@2, Pieces, (Port * 10) + 2); - - <<"3"/utf8, Rest@3/binary>> -> - parse_port_loop(Rest@3, Pieces, (Port * 10) + 3); - - <<"4"/utf8, Rest@4/binary>> -> - parse_port_loop(Rest@4, Pieces, (Port * 10) + 4); - - <<"5"/utf8, Rest@5/binary>> -> - parse_port_loop(Rest@5, Pieces, (Port * 10) + 5); - - <<"6"/utf8, Rest@6/binary>> -> - parse_port_loop(Rest@6, Pieces, (Port * 10) + 6); - - <<"7"/utf8, Rest@7/binary>> -> - parse_port_loop(Rest@7, Pieces, (Port * 10) + 7); - - <<"8"/utf8, Rest@8/binary>> -> - parse_port_loop(Rest@8, Pieces, (Port * 10) + 8); - - <<"9"/utf8, Rest@9/binary>> -> - parse_port_loop(Rest@9, Pieces, (Port * 10) + 9); - - <<"?"/utf8, Rest@10/binary>> -> - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@10, Pieces@1); - - <<"#"/utf8, Rest@11/binary>> -> - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@11, Pieces@2); - - <<"/"/utf8, _/binary>> -> - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@3); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - {some, Port}, - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 353). --spec parse_port(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_port(Uri_string, Pieces) -> - case Uri_string of - <<":0"/utf8, Rest/binary>> -> - parse_port_loop(Rest, Pieces, 0); - - <<":1"/utf8, Rest@1/binary>> -> - parse_port_loop(Rest@1, Pieces, 1); - - <<":2"/utf8, Rest@2/binary>> -> - parse_port_loop(Rest@2, Pieces, 2); - - <<":3"/utf8, Rest@3/binary>> -> - parse_port_loop(Rest@3, Pieces, 3); - - <<":4"/utf8, Rest@4/binary>> -> - parse_port_loop(Rest@4, Pieces, 4); - - <<":5"/utf8, Rest@5/binary>> -> - parse_port_loop(Rest@5, Pieces, 5); - - <<":6"/utf8, Rest@6/binary>> -> - parse_port_loop(Rest@6, Pieces, 6); - - <<":7"/utf8, Rest@7/binary>> -> - parse_port_loop(Rest@7, Pieces, 7); - - <<":8"/utf8, Rest@8/binary>> -> - parse_port_loop(Rest@8, Pieces, 8); - - <<":9"/utf8, Rest@9/binary>> -> - parse_port_loop(Rest@9, Pieces, 9); - - <<":"/utf8>> -> - {ok, Pieces}; - - <<""/utf8>> -> - {ok, Pieces}; - - <<"?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<":?"/utf8, Rest@10/binary>> -> - parse_query_with_question_mark(Rest@10, Pieces); - - <<"#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<":#"/utf8, Rest@11/binary>> -> - parse_fragment(Rest@11, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_path(Uri_string, Pieces); - - <<":"/utf8, Rest@12/binary>> -> - case Rest@12 of - <<"/"/utf8, _/binary>> -> - parse_path(Rest@12, Pieces); - - _ -> - {error, nil} - end; - - _ -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 309). --spec parse_host_outside_of_brackets_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_host_outside_of_brackets_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Original}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<":"/utf8, _/binary>> -> - Host = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Uri_string, Pieces@1); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@1}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@2}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest, Pieces@3); - - <<"#"/utf8, Rest@1/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@3}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@1, Pieces@4); - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_host_outside_of_brackets_loop( - Original, - Rest@2, - Pieces, - Size + 1 - ) - end. - --file("src/gleam/uri.gleam", 302). --spec parse_host_outside_of_brackets(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_host_outside_of_brackets(Uri_string, Pieces) -> - parse_host_outside_of_brackets_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 289). --spec is_valid_host_within_brackets_char(integer()) -> boolean(). -is_valid_host_within_brackets_char(Char) -> - (((((48 >= Char) andalso (Char =< 57)) orelse ((65 >= Char) andalso (Char =< 90))) - orelse ((97 >= Char) andalso (Char =< 122))) - orelse (Char =:= 58)) - orelse (Char =:= 46). - --file("src/gleam/uri.gleam", 229). --spec parse_host_within_brackets_loop(binary(), binary(), uri(), integer()) -> {ok, - uri()} | - {error, nil}. -parse_host_within_brackets_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Uri_string}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<"]"/utf8, Rest/binary>> when Size =:= 0 -> - parse_port(Rest, Pieces); - - <<"]"/utf8, Rest@1/binary>> -> - Host = binary:part(Original, 0, Size + 1), - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Rest@1, Pieces@1); - - <<"/"/utf8, _/binary>> when Size =:= 0 -> - parse_path(Uri_string, Pieces); - - <<"/"/utf8, _/binary>> -> - Host@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@1}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_path(Uri_string, Pieces@2); - - <<"?"/utf8, Rest@2/binary>> when Size =:= 0 -> - parse_query_with_question_mark(Rest@2, Pieces); - - <<"?"/utf8, Rest@3/binary>> -> - Host@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@2}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@3, Pieces@3); - - <<"#"/utf8, Rest@4/binary>> when Size =:= 0 -> - parse_fragment(Rest@4, Pieces); - - <<"#"/utf8, Rest@5/binary>> -> - Host@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, Host@3}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@5, Pieces@4); - - _ -> - {Char, Rest@6} = gleam_stdlib:string_pop_codeunit(Uri_string), - case is_valid_host_within_brackets_char(Char) of - true -> - parse_host_within_brackets_loop( - Original, - Rest@6, - Pieces, - Size + 1 - ); - - false -> - parse_host_outside_of_brackets_loop( - Original, - Original, - Pieces, - 0 - ) - end - end. - --file("src/gleam/uri.gleam", 222). --spec parse_host_within_brackets(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_host_within_brackets(Uri_string, Pieces) -> - parse_host_within_brackets_loop(Uri_string, Uri_string, Pieces, 0). - --file("src/gleam/uri.gleam", 199). --spec parse_host(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_host(Uri_string, Pieces) -> - case Uri_string of - <<"["/utf8, _/binary>> -> - parse_host_within_brackets(Uri_string, Pieces); - - <<":"/utf8, _/binary>> -> - Pieces@1 = {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_port(Uri_string, Pieces@1); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - parse_host_outside_of_brackets(Uri_string, Pieces) - end. - --file("src/gleam/uri.gleam", 167). --spec parse_userinfo_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_userinfo_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"@"/utf8, Rest/binary>> when Size =:= 0 -> - parse_host(Rest, Pieces); - - <<"@"/utf8, Rest@1/binary>> -> - Userinfo = binary:part(Original, 0, Size), - Pieces@1 = {uri, - erlang:element(2, Pieces), - {some, Userinfo}, - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_host(Rest@1, Pieces@1); - - <<""/utf8>> -> - parse_host(Original, Pieces); - - <<"/"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - <<"?"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - <<"#"/utf8, _/binary>> -> - parse_host(Original, Pieces); - - _ -> - {_, Rest@2} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_userinfo_loop(Original, Rest@2, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 163). --spec parse_authority_pieces(binary(), uri()) -> {ok, uri()} | {error, nil}. -parse_authority_pieces(String, Pieces) -> - parse_userinfo_loop(String, String, Pieces, 0). - --file("src/gleam/uri.gleam", 150). --spec parse_authority_with_slashes(binary(), uri()) -> {ok, uri()} | - {error, nil}. -parse_authority_with_slashes(Uri_string, Pieces) -> - case Uri_string of - <<"//"/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - {some, <<""/utf8>>}, - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - <<"//"/utf8, Rest/binary>> -> - parse_authority_pieces(Rest, Pieces); - - _ -> - parse_path(Uri_string, Pieces) - end. - --file("src/gleam/uri.gleam", 91). --spec parse_scheme_loop(binary(), binary(), uri(), integer()) -> {ok, uri()} | - {error, nil}. -parse_scheme_loop(Original, Uri_string, Pieces, Size) -> - case Uri_string of - <<"/"/utf8, _/binary>> when Size =:= 0 -> - parse_authority_with_slashes(Uri_string, Pieces); - - <<"/"/utf8, _/binary>> -> - Scheme = binary:part(Original, 0, Size), - Pieces@1 = {uri, - {some, string:lowercase(Scheme)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_authority_with_slashes(Uri_string, Pieces@1); - - <<"?"/utf8, Rest/binary>> when Size =:= 0 -> - parse_query_with_question_mark(Rest, Pieces); - - <<"?"/utf8, Rest@1/binary>> -> - Scheme@1 = binary:part(Original, 0, Size), - Pieces@2 = {uri, - {some, string:lowercase(Scheme@1)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_query_with_question_mark(Rest@1, Pieces@2); - - <<"#"/utf8, Rest@2/binary>> when Size =:= 0 -> - parse_fragment(Rest@2, Pieces); - - <<"#"/utf8, Rest@3/binary>> -> - Scheme@2 = binary:part(Original, 0, Size), - Pieces@3 = {uri, - {some, string:lowercase(Scheme@2)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_fragment(Rest@3, Pieces@3); - - <<":"/utf8, _/binary>> when Size =:= 0 -> - {error, nil}; - - <<":"/utf8, Rest@4/binary>> -> - Scheme@3 = binary:part(Original, 0, Size), - Pieces@4 = {uri, - {some, string:lowercase(Scheme@3)}, - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - erlang:element(6, Pieces), - erlang:element(7, Pieces), - erlang:element(8, Pieces)}, - parse_authority_with_slashes(Rest@4, Pieces@4); - - <<""/utf8>> -> - {ok, - {uri, - erlang:element(2, Pieces), - erlang:element(3, Pieces), - erlang:element(4, Pieces), - erlang:element(5, Pieces), - Original, - erlang:element(7, Pieces), - erlang:element(8, Pieces)}}; - - _ -> - {_, Rest@5} = gleam_stdlib:string_pop_codeunit(Uri_string), - parse_scheme_loop(Original, Rest@5, Pieces, Size + 1) - end. - --file("src/gleam/uri.gleam", 81). -?DOC( - " Parses a compliant URI string into the `Uri` type.\n" - " If the string is not a valid URI string then an error is returned.\n" - "\n" - " The opposite operation is `uri.to_string`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert parse(\"https://example.com:1234/a/b?query=true#fragment\")\n" - " == Ok(\n" - " Uri(\n" - " scheme: Some(\"https\"),\n" - " userinfo: None,\n" - " host: Some(\"example.com\"),\n" - " port: Some(1234),\n" - " path: \"/a/b\",\n" - " query: Some(\"query=true\"),\n" - " fragment: Some(\"fragment\")\n" - " )\n" - " )\n" - " ```\n" -). --spec parse(binary()) -> {ok, uri()} | {error, nil}. -parse(Uri_string) -> - gleam_stdlib:uri_parse(Uri_string). - --file("src/gleam/uri.gleam", 536). -?DOC( - " Parses an URL-encoded query string into a list of key value pairs.\n" - " Returns an error for invalid encoding.\n" - "\n" - " The opposite operation is `uri.query_to_string`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert parse_query(\"a=1&b=2\") == Ok([#(\"a\", \"1\"), #(\"b\", \"2\")])\n" - " ```\n" -). --spec parse_query(binary()) -> {ok, list({binary(), binary()})} | {error, nil}. -parse_query(Query) -> - gleam_stdlib:parse_query(Query). - --file("src/gleam/uri.gleam", 576). -?DOC( - " Encodes a string into a percent encoded representation.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert percent_encode(\"100% great\") == \"100%25%20great\"\n" - " ```\n" -). --spec percent_encode(binary()) -> binary(). -percent_encode(Value) -> - gleam_stdlib:percent_encode(Value). - --file("src/gleam/uri.gleam", 561). --spec percent_encode_query(binary()) -> binary(). -percent_encode_query(Part) -> - _pipe = gleam_stdlib:percent_encode(Part), - gleam@string:replace(_pipe, <<"+"/utf8>>, <<"%2B"/utf8>>). - --file("src/gleam/uri.gleam", 556). --spec query_pair({binary(), binary()}) -> gleam@string_tree:string_tree(). -query_pair(Pair) -> - _pipe = [percent_encode_query(erlang:element(1, Pair)), - <<"="/utf8>>, - percent_encode_query(erlang:element(2, Pair))], - gleam_stdlib:identity(_pipe). - --file("src/gleam/uri.gleam", 548). -?DOC( - " Encodes a list of key value pairs as a URI query string.\n" - "\n" - " The opposite operation is `uri.parse_query`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert query_to_string([#(\"a\", \"1\"), #(\"b\", \"2\")]) == \"a=1&b=2\"\n" - " ```\n" -). --spec query_to_string(list({binary(), binary()})) -> binary(). -query_to_string(Query) -> - _pipe = Query, - _pipe@1 = gleam@list:map(_pipe, fun query_pair/1), - _pipe@2 = gleam@list:intersperse( - _pipe@1, - gleam_stdlib:identity(<<"&"/utf8>>) - ), - _pipe@3 = gleam_stdlib:identity(_pipe@2), - unicode:characters_to_binary(_pipe@3). - --file("src/gleam/uri.gleam", 588). -?DOC( - " Decodes a percent encoded string.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert percent_decode(\"100%25%20great+fun\") == Ok(\"100% great+fun\")\n" - " ```\n" -). --spec percent_decode(binary()) -> {ok, binary()} | {error, nil}. -percent_decode(Value) -> - gleam_stdlib:percent_decode(Value). - --file("src/gleam/uri.gleam", 609). --spec remove_dot_segments_loop(list(binary()), list(binary())) -> list(binary()). -remove_dot_segments_loop(Input, Accumulator) -> - case Input of - [] -> - lists:reverse(Accumulator); - - [Segment | Rest] -> - Accumulator@5 = case {Segment, Accumulator} of - {<<""/utf8>>, Accumulator@1} -> - Accumulator@1; - - {<<"."/utf8>>, Accumulator@2} -> - Accumulator@2; - - {<<".."/utf8>>, []} -> - []; - - {<<".."/utf8>>, [_ | Accumulator@3]} -> - Accumulator@3; - - {Segment@1, Accumulator@4} -> - [Segment@1 | Accumulator@4] - end, - remove_dot_segments_loop(Rest, Accumulator@5) - end. - --file("src/gleam/uri.gleam", 605). --spec remove_dot_segments(list(binary())) -> list(binary()). -remove_dot_segments(Input) -> - remove_dot_segments_loop(Input, []). - --file("src/gleam/uri.gleam", 601). -?DOC( - " Splits the path section of a URI into its constituent segments.\n" - "\n" - " Removes empty segments and resolves dot-segments as specified in\n" - " [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " assert path_segments(\"/users/1\") == [\"users\" ,\"1\"]\n" - " ```\n" -). --spec path_segments(binary()) -> list(binary()). -path_segments(Path) -> - remove_dot_segments(gleam@string:split(Path, <<"/"/utf8>>)). - --file("src/gleam/uri.gleam", 639). -?DOC( - " Encodes a `Uri` value as a URI string.\n" - "\n" - " The opposite operation is `uri.parse`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let uri = Uri(..empty, scheme: Some(\"https\"), host: Some(\"example.com\"))\n" - " assert to_string(uri) == \"https://example.com\"\n" - " ```\n" -). --spec to_string(uri()) -> binary(). -to_string(Uri) -> - Parts = case erlang:element(8, Uri) of - {some, Fragment} -> - [<<"#"/utf8>>, Fragment]; - - none -> - [] - end, - Parts@1 = case erlang:element(7, Uri) of - {some, Query} -> - [<<"?"/utf8>>, Query | Parts]; - - none -> - Parts - end, - Parts@2 = [erlang:element(6, Uri) | Parts@1], - Parts@3 = case {erlang:element(4, Uri), - gleam_stdlib:string_starts_with(erlang:element(6, Uri), <<"/"/utf8>>)} of - {{some, Host}, false} when Host =/= <<""/utf8>> -> - [<<"/"/utf8>> | Parts@2]; - - {_, _} -> - Parts@2 - end, - Parts@4 = case {erlang:element(4, Uri), erlang:element(5, Uri)} of - {{some, _}, {some, Port}} -> - [<<":"/utf8>>, erlang:integer_to_binary(Port) | Parts@3]; - - {_, _} -> - Parts@3 - end, - Parts@5 = case {erlang:element(2, Uri), - erlang:element(3, Uri), - erlang:element(4, Uri)} of - {{some, S}, {some, U}, {some, H}} -> - [S, <<"://"/utf8>>, U, <<"@"/utf8>>, H | Parts@4]; - - {{some, S@1}, none, {some, H@1}} -> - [S@1, <<"://"/utf8>>, H@1 | Parts@4]; - - {{some, S@2}, {some, _}, none} -> - [S@2, <<":"/utf8>> | Parts@4]; - - {{some, S@2}, none, none} -> - [S@2, <<":"/utf8>> | Parts@4]; - - {none, none, {some, H@2}} -> - [<<"//"/utf8>>, H@2 | Parts@4]; - - {_, _, _} -> - Parts@4 - end, - erlang:list_to_binary(Parts@5). - --file("src/gleam/uri.gleam", 682). -?DOC( - " Fetches the origin of a URI.\n" - "\n" - " Returns the origin of a uri as defined in\n" - " [RFC 6454](https://tools.ietf.org/html/rfc6454)\n" - "\n" - " The supported URI schemes are `http` and `https`.\n" - " URLs without a scheme will return `Error`.\n" - "\n" - " ## Examples\n" - "\n" - " ```gleam\n" - " let assert Ok(uri) = parse(\"https://example.com/path?foo#bar\")\n" - " assert origin(uri) == Ok(\"https://example.com\")\n" - " ```\n" -). --spec origin(uri()) -> {ok, binary()} | {error, nil}. -origin(Uri) -> - {uri, Scheme, _, Host, Port, _, _, _} = Uri, - case {Host, Scheme} of - {{some, H}, {some, <<"https"/utf8>>}} when Port =:= {some, 443} -> - {ok, erlang:list_to_binary([<<"https://"/utf8>>, H])}; - - {{some, H@1}, {some, <<"http"/utf8>>}} when Port =:= {some, 80} -> - {ok, erlang:list_to_binary([<<"http://"/utf8>>, H@1])}; - - {{some, H@2}, {some, S}} when (S =:= <<"http"/utf8>>) orelse (S =:= <<"https"/utf8>>) -> - case Port of - {some, P} -> - {ok, - erlang:list_to_binary( - [S, - <<"://"/utf8>>, - H@2, - <<":"/utf8>>, - erlang:integer_to_binary(P)] - )}; - - none -> - {ok, erlang:list_to_binary([S, <<"://"/utf8>>, H@2])} - end; - - {_, _} -> - {error, nil} - end. - --file("src/gleam/uri.gleam", 767). --spec join_segments(list(binary())) -> binary(). -join_segments(Segments) -> - gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). - --file("src/gleam/uri.gleam", 763). --spec drop_last(list(DDN)) -> list(DDN). -drop_last(Elements) -> - gleam@list:take(Elements, erlang:length(Elements) - 1). - --file("src/gleam/uri.gleam", 705). -?DOC( - " Resolves a URI with respect to the given base URI.\n" - "\n" - " The base URI must be an absolute URI or this function will return an error.\n" - " The algorithm for merging URIs is described in\n" - " [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2).\n" -). --spec merge(uri(), uri()) -> {ok, uri()} | {error, nil}. -merge(Base, Relative) -> - case Base of - {uri, {some, _}, _, {some, _}, _, _, _, _} -> - case Relative of - {uri, _, _, {some, _}, _, _, _, _} -> - Path = begin - _pipe = erlang:element(6, Relative), - _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), - _pipe@2 = remove_dot_segments(_pipe@1), - join_segments(_pipe@2) - end, - Resolved = {uri, - gleam@option:'or'( - erlang:element(2, Relative), - erlang:element(2, Base) - ), - none, - erlang:element(4, Relative), - gleam@option:'or'( - erlang:element(5, Relative), - erlang:element(5, Base) - ), - Path, - erlang:element(7, Relative), - erlang:element(8, Relative)}, - {ok, Resolved}; - - _ -> - {New_path, New_query} = case erlang:element(6, Relative) of - <<""/utf8>> -> - {erlang:element(6, Base), - gleam@option:'or'( - erlang:element(7, Relative), - erlang:element(7, Base) - )}; - - _ -> - Path_segments = case gleam_stdlib:string_starts_with( - erlang:element(6, Relative), - <<"/"/utf8>> - ) of - true -> - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ); - - false -> - _pipe@3 = erlang:element(6, Base), - _pipe@4 = gleam@string:split( - _pipe@3, - <<"/"/utf8>> - ), - _pipe@5 = drop_last(_pipe@4), - lists:append( - _pipe@5, - gleam@string:split( - erlang:element(6, Relative), - <<"/"/utf8>> - ) - ) - end, - Path@1 = begin - _pipe@6 = Path_segments, - _pipe@7 = remove_dot_segments(_pipe@6), - join_segments(_pipe@7) - end, - {Path@1, erlang:element(7, Relative)} - end, - Resolved@1 = {uri, - erlang:element(2, Base), - none, - erlang:element(4, Base), - erlang:element(5, Base), - New_path, - New_query, - erlang:element(8, Relative)}, - {ok, Resolved@1} - end; - - _ -> - {error, nil} - end. diff --git a/ui/javascript/gleam_stdlib/gleam_stdlib.erl b/ui/javascript/gleam_stdlib/gleam_stdlib.erl deleted file mode 100644 index 9017bc7..0000000 --- a/ui/javascript/gleam_stdlib/gleam_stdlib.erl +++ /dev/null @@ -1,554 +0,0 @@ --module(gleam_stdlib). - --export([ - map_get/2, iodata_append/2, identity/1, parse_int/1, parse_float/1, - less_than/2, string_pop_grapheme/1, string_pop_codeunit/1, - string_starts_with/2, wrap_list/1, string_ends_with/2, string_pad/4, - uri_parse/1, bit_array_slice/3, percent_encode/1, percent_decode/1, - base64_decode/1, parse_query/1, bit_array_concat/1, - base64_encode/2, tuple_get/2, classify_dynamic/1, print/1, - println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, - int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, - crop_string/2, base16_encode/1, base16_decode/1, string_replace/3, slice/3, - bit_array_to_int_and_size/1, bit_array_pad_to_bytes/1, index/2, list/5, - dict/1, int/1, float/1, bit_array/1, is_null/1, string_remove_prefix/2, - string_remove_suffix/2 -]). - -%% Taken from OTP's uri_string module --define(DEC2HEX(X), - if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; - ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 - end). - -%% Taken from OTP's uri_string module --define(HEX2DEC(X), - if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; - ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; - ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 - end). - --define(is_lowercase_char(X), - (X > 96 andalso X < 123)). --define(is_underscore_char(X), - (X == 95)). --define(is_digit_char(X), - (X > 47 andalso X < 58)). --define(is_ascii_character(X), - (erlang:is_integer(X) andalso X >= 32 andalso X =< 126)). - -uppercase(X) -> X - 32. - -map_get(Map, Key) -> - case maps:find(Key, Map) of - error -> {error, nil}; - OkFound -> OkFound - end. - -iodata_append(Iodata, String) -> [Iodata, String]. - -identity(X) -> X. - -classify_dynamic(nil) -> <<"Nil">>; -classify_dynamic(null) -> <<"Nil">>; -classify_dynamic(undefined) -> <<"Nil">>; -classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; -classify_dynamic(X) when is_atom(X) -> <<"Atom">>; -classify_dynamic(X) when is_binary(X) -> <<"String">>; -classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>; -classify_dynamic(X) when is_integer(X) -> <<"Int">>; -classify_dynamic(X) when is_float(X) -> <<"Float">>; -classify_dynamic(X) when is_list(X) -> <<"List">>; -classify_dynamic(X) when is_map(X) -> <<"Dict">>; -classify_dynamic(X) when is_tuple(X) -> <<"Array">>; -classify_dynamic(X) when is_reference(X) -> <<"Reference">>; -classify_dynamic(X) when is_pid(X) -> <<"Pid">>; -classify_dynamic(X) when is_port(X) -> <<"Port">>; -classify_dynamic(X) when is_function(X) -> <<"Function">>; -classify_dynamic(_) -> <<"Unknown">>. - -tuple_get(_tup, Index) when Index < 0 -> {error, nil}; -tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil}; -tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}. - -int_from_base_string(String, Base) -> - try binary_to_integer(String, Base) of - Int when is_integer(Int) -> {ok, Int}; - _ -> {error, nil} - catch _:_ -> {error, nil} - end. - -parse_int(String) -> - try binary_to_integer(String) of - Int when is_integer(Int) -> {ok, Int}; - _ -> {error, nil} - catch _:_ -> {error, nil} - end. - -parse_float(String) -> - try binary_to_float(String) of - Float when is_float(Float) -> {ok, Float}; - _ -> {error, nil} - catch _:_ -> {error, nil} - end. - -less_than(Lhs, Rhs) -> - Lhs < Rhs. - -string_starts_with(_, <<>>) -> true; -string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false; -string_starts_with(String, Prefix) -> - PrefixSize = byte_size(Prefix), - Prefix == binary_part(String, 0, PrefixSize). - -string_ends_with(_, <<>>) -> true; -string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false; -string_ends_with(String, Suffix) -> - SuffixSize = byte_size(Suffix), - Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize). - -string_pad(String, Length, Dir, PadString) -> - Chars = string:pad(String, Length, Dir, binary_to_list(PadString)), - case unicode:characters_to_binary(Chars) of - Bin when is_binary(Bin) -> Bin; - Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}}) - end. - -string_pop_grapheme(String) -> - case string:next_grapheme(String) of - [ Next | Rest ] when is_binary(Rest) -> - {ok, {unicode:characters_to_binary([Next]), Rest}}; - - [ Next | Rest ] -> - {ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}}; - - _ -> {error, nil} - end. - -string_pop_codeunit(<>) -> {Cp, Rest}; -string_pop_codeunit(Binary) -> {0, Binary}. - -bit_array_pad_to_bytes(Bin) -> - case erlang:bit_size(Bin) rem 8 of - 0 -> Bin; - TrailingBits -> - PaddingBits = 8 - TrailingBits, - <> - end. - -bit_array_concat(BitArrays) -> - list_to_bitstring(BitArrays). - --if(?OTP_RELEASE >= 26). -base64_encode(Bin, Padding) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - base64:encode(PaddedBin, #{padding => Padding}). --else. -base64_encode(_Bin, _Padding) -> - erlang:error(<<"Erlang OTP/26 or higher is required to use base64:encode">>). --endif. - -bit_array_slice(Bin, Pos, Len) -> - try {ok, binary:part(Bin, Pos, Len)} - catch error:badarg -> {error, nil} - end. - -base64_decode(S) -> - try {ok, base64:decode(S)} - catch error:_ -> {error, nil} - end. - -wrap_list(X) when is_list(X) -> X; -wrap_list(X) -> [X]. - -parse_query(Query) -> - case uri_string:dissect_query(Query) of - {error, _, _} -> {error, nil}; - Pairs -> - Pairs1 = lists:map(fun - ({K, true}) -> {K, <<"">>}; - (Pair) -> Pair - end, Pairs), - {ok, Pairs1} - end. - -percent_encode(B) -> percent_encode(B, <<>>). -percent_encode(<<>>, Acc) -> - Acc; -percent_encode(<>, Acc) -> - case percent_ok(H) of - true -> - percent_encode(T, <>); - false -> - <> = <>, - percent_encode(T, <>) - end. - -percent_decode(Cs) -> percent_decode(Cs, <<>>). -percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> - case is_hex_digit(C0) andalso is_hex_digit(C1) of - true -> - B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), - percent_decode(Cs, <>); - false -> - {error, nil} - end; -percent_decode(<>, Acc) -> - percent_decode(Cs, <>); -percent_decode(<<>>, Acc) -> - check_utf8(Acc). - -percent_ok($!) -> true; -percent_ok($$) -> true; -percent_ok($') -> true; -percent_ok($() -> true; -percent_ok($)) -> true; -percent_ok($*) -> true; -percent_ok($+) -> true; -percent_ok($-) -> true; -percent_ok($.) -> true; -percent_ok($_) -> true; -percent_ok($~) -> true; -percent_ok(C) when $0 =< C, C =< $9 -> true; -percent_ok(C) when $A =< C, C =< $Z -> true; -percent_ok(C) when $a =< C, C =< $z -> true; -percent_ok(_) -> false. - -is_hex_digit(C) -> - ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). - -check_utf8(Cs) -> - case unicode:characters_to_list(Cs) of - {incomplete, _, _} -> {error, nil}; - {error, _, _} -> {error, nil}; - _ -> {ok, Cs} - end. - -uri_parse(String) -> - case uri_string:parse(String) of - {error, _, _} -> {error, nil}; - Uri -> - Port = - try maps:get(port, Uri) of - undefined -> none; - Value -> {some, Value} - catch _:_ -> none - end, - {ok, {uri, - maps_get_optional_lowercase(Uri, scheme), - maps_get_optional(Uri, userinfo), - maps_get_optional(Uri, host), - Port, - maps_get_or(Uri, path, <<>>), - maps_get_optional(Uri, query), - maps_get_optional(Uri, fragment) - }} - end. - -maps_get_optional_lowercase(Map, Key) -> - try {some, string:lowercase(maps:get(Key, Map))} - catch _:_ -> none - end. - -maps_get_optional(Map, Key) -> - try {some, maps:get(Key, Map)} - catch _:_ -> none - end. - -maps_get_or(Map, Key, Default) -> - try maps:get(Key, Map) - catch _:_ -> Default - end. - -print(String) -> - io:put_chars(String), - nil. - -println(String) -> - io:put_chars([String, $\n]), - nil. - -print_error(String) -> - io:put_chars(standard_error, String), - nil. - -println_error(String) -> - io:put_chars(standard_error, [String, $\n]), - nil. - -inspect(true) -> - "True"; -inspect(false) -> - "False"; -inspect(nil) -> - "Nil"; -inspect(Data) when is_map(Data) -> - Fields = [ - [<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>] - || {Key, Value} <- maps:to_list(Data) - ], - ["dict.from_list([", lists:join(", ", Fields), "])"]; -inspect(Atom) when is_atom(Atom) -> - erlang:element(2, inspect_atom(Atom)); -inspect(Any) when is_integer(Any) -> - erlang:integer_to_list(Any); -inspect(Any) when is_float(Any) -> - io_lib_format:fwrite_g(Any); -inspect(Binary) when is_binary(Binary) -> - case inspect_maybe_utf8_string(Binary, <<>>) of - {ok, InspectedUtf8String} -> InspectedUtf8String; - {error, not_a_utf8_string} -> - Segments = [erlang:integer_to_list(X) || <> <= Binary], - ["<<", lists:join(", ", Segments), ">>"] - end; -inspect(Bits) when is_bitstring(Bits) -> - inspect_bit_array(Bits); -inspect(List) when is_list(List) -> - case inspect_list(List, true) of - {charlist, _} -> ["charlist.from_string(\"", list_to_binary(List), "\")"]; - {proper, Elements} -> ["[", Elements, "]"]; - {improper, Elements} -> ["//erl([", Elements, "])"] - end; -inspect(Any) when is_tuple(Any) % Record constructors - andalso is_atom(element(1, Any)) - andalso element(1, Any) =/= false - andalso element(1, Any) =/= true - andalso element(1, Any) =/= nil --> - [Atom | ArgsList] = erlang:tuple_to_list(Any), - InspectedArgs = lists:map(fun inspect/1, ArgsList), - case inspect_atom(Atom) of - {gleam_atom, GleamAtom} -> - Args = lists:join(<<", ">>, InspectedArgs), - [GleamAtom, "(", Args, ")"]; - {erlang_atom, ErlangAtom} -> - Args = lists:join(<<", ">>, [ErlangAtom | InspectedArgs]), - ["#(", Args, ")"] - end; -inspect(Tuple) when is_tuple(Tuple) -> - Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)), - ["#(", lists:join(", ", Elements), ")"]; -inspect(Any) when is_function(Any) -> - {arity, Arity} = erlang:fun_info(Any, arity), - ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), - Args = lists:join(<<", ">>, - lists:map(fun(Arg) -> <> end, ArgsAsciiCodes) - ), - ["//fn(", Args, ") { ... }"]; -inspect(Any) -> - ["//erl(", io_lib:format("~p", [Any]), ")"]. - -inspect_atom(Atom) -> - Binary = erlang:atom_to_binary(Atom), - case inspect_maybe_gleam_atom(Binary, none, <<>>) of - {ok, Inspected} -> {gleam_atom, Inspected}; - {error, _} -> {erlang_atom, ["atom.create(\"", Binary, "\")"]} - end. - -inspect_maybe_gleam_atom(<<>>, none, _) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, none, _) when ?is_digit_char(First) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) -> - {error, nil}; -inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, _PrevChar, _Acc) - when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) -> - {error, nil}; -inspect_maybe_gleam_atom(<>, none, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) -> - inspect_maybe_gleam_atom(Rest, $_, Acc); -inspect_maybe_gleam_atom(<>, $_, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<>, _PrevChar, Acc) -> - inspect_maybe_gleam_atom(Rest, First, <>); -inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) -> - {ok, Acc}; -inspect_maybe_gleam_atom(A, B, C) -> - erlang:display({A, B, C}), - throw({gleam_error, A, B, C}). - -inspect_list([], _) -> - {proper, []}; -inspect_list([First], true) when ?is_ascii_character(First) -> - {charlist, nil}; -inspect_list([First], _) -> - {proper, [inspect(First)]}; -inspect_list([First | Rest], ValidCharlist) when is_list(Rest) -> - StillValidCharlist = ValidCharlist andalso ?is_ascii_character(First), - {Kind, Inspected} = inspect_list(Rest, StillValidCharlist), - {Kind, [inspect(First), <<", ">> | Inspected]}; -inspect_list([First | ImproperTail], _) -> - {improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}. - -inspect_bit_array(Bits) -> - Text = inspect_bit_array(Bits, <<"<<">>), - <>">>. - -inspect_bit_array(<<>>, Acc) -> - Acc; -inspect_bit_array(<>, Acc) -> - inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X))); -inspect_bit_array(Rest, Acc) -> - Size = bit_size(Rest), - <> = Rest, - X1 = erlang:integer_to_binary(X), - Size1 = erlang:integer_to_binary(Size), - Segment = <>, - inspect_bit_array(<<>>, append_segment(Acc, Segment)). - -bit_array_to_int_and_size(A) -> - Size = bit_size(A), - <> = A, - {A1, Size}. - -append_segment(<<"<<">>, Segment) -> - <<"<<", Segment/binary>>; -append_segment(Acc, Segment) -> - <>. - - -inspect_maybe_utf8_string(Binary, Acc) -> - case Binary of - <<>> -> {ok, <<$", Acc/binary, $">>}; - <> -> - Escaped = case First of - $" -> <<$\\, $">>; - $\\ -> <<$\\, $\\>>; - $\r -> <<$\\, $r>>; - $\n -> <<$\\, $n>>; - $\t -> <<$\\, $t>>; - $\f -> <<$\\, $f>>; - X when X > 126, X < 160 -> convert_to_u(X); - X when X < 32 -> convert_to_u(X); - Other -> <> - end, - inspect_maybe_utf8_string(Rest, <>); - _ -> {error, not_a_utf8_string} - end. - -convert_to_u(Code) -> - list_to_binary(io_lib:format("\\u{~4.16.0B}", [Code])). - -float_to_string(Float) when is_float(Float) -> - erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)). - -utf_codepoint_list_to_string(List) -> - case unicode:characters_to_binary(List) of - {error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}}); - Binary -> Binary - end. - -crop_string(String, Prefix) -> - case string:find(String, Prefix) of - nomatch -> String; - New -> New - end. - -contains_string(String, Substring) -> - is_bitstring(string:find(String, Substring)). - -base16_encode(Bin) -> - PaddedBin = bit_array_pad_to_bytes(Bin), - binary:encode_hex(PaddedBin). - -base16_decode(String) -> - try - {ok, binary:decode_hex(String)} - catch - _:_ -> {error, nil} - end. - -string_replace(String, Pattern, Replacement) -> - string:replace(String, Pattern, Replacement, all). - -slice(String, Index, Length) -> - case string:slice(String, Index, Length) of - X when is_binary(X) -> X; - X when is_list(X) -> unicode:characters_to_binary(X) - end. - -index([X | _], 0) -> - {ok, {some, X}}; -index([_, X | _], 1) -> - {ok, {some, X}}; -index([_, _, X | _], 2) -> - {ok, {some, X}}; -index([_, _, _, X | _], 3) -> - {ok, {some, X}}; -index([_, _, _, _, X | _], 4) -> - {ok, {some, X}}; -index([_, _, _, _, _, X | _], 5) -> - {ok, {some, X}}; -index([_, _, _, _, _, _, X | _], 6) -> - {ok, {some, X}}; -index([_, _, _, _, _, _, _, X | _], 7) -> - {ok, {some, X}}; -index(Tuple, Index) when is_tuple(Tuple) andalso is_integer(Index) -> - {ok, try - {some, element(Index + 1, Tuple)} - catch _:_ -> - none - end}; -index(Map, Key) when is_map(Map) -> - {ok, try - {some, maps:get(Key, Map)} - catch _:_ -> - none - end}; -index(_, Index) when is_integer(Index) -> - {error, <<"Indexable">>}; -index(_, _) -> - {error, <<"Dict">>}. - -list(T, A, B, C, D) when is_tuple(T) -> - list(tuple_to_list(T), A, B, C, D); -list([], _, _, _, Acc) -> - {lists:reverse(Acc), []}; -list([X | Xs], Decode, PushPath, Index, Acc) -> - {Out, Errors} = Decode(X), - case Errors of - [] -> list(Xs, Decode, PushPath, Index + 1, [Out | Acc]); - _ -> PushPath({[], Errors}, integer_to_binary(Index)) - end; -list(Unexpected, _, _, _, []) -> - Found = gleam@dynamic:classify(Unexpected), - Error = {decode_error, <<"List"/utf8>>, Found, []}, - {[], [Error]}; -list(_, _, _, _, Acc) -> - {lists:reverse(Acc), []}. - -dict(#{} = Data) -> {ok, Data}; -dict(_) -> {error, nil}. - -int(I) when is_integer(I) -> {ok, I}; -int(_) -> {error, 0}. - -float(F) when is_float(F) -> {ok, F}; -float(_) -> {error, 0.0}. - -bit_array(B) when is_bitstring(B) -> {ok, B}; -bit_array(_) -> {error, <<>>}. - -is_null(X) -> - X =:= undefined orelse X =:= null orelse X =:= nil. - -string_remove_prefix(String, Prefix) -> - PrefixSize = byte_size(Prefix), - case String of - <> -> Suffix; - _ -> String - end. - -string_remove_suffix(String, Suffix) -> - StringSize = byte_size(String), - SuffixSize = byte_size(Suffix), - Offset = StringSize - SuffixSize, - case String of - <> -> Prefix; - _ -> String - end. diff --git a/ui/javascript/gleam_stdlib/gleam_stdlib.mjs b/ui/javascript/gleam_stdlib/gleam_stdlib.mjs deleted file mode 100644 index 96582b1..0000000 --- a/ui/javascript/gleam_stdlib/gleam_stdlib.mjs +++ /dev/null @@ -1,1150 +0,0 @@ -import { - BitArray, - List$Empty, - List$NonEmpty, - List$isEmpty, - List$isNonEmpty, - Result$Ok, - Result$Error, - Result$isOk, - Result$isError, - UtfCodepoint, - stringBits, - toBitArray, - bitArraySlice, - CustomType, -} from "./gleam.mjs"; -import { Some, None } from "./gleam/option.mjs"; -import { - default as Dict, - fold as dict_fold, - get as dict_get, - from as dict_from_iterable, -} from "./dict.mjs"; -import { classify } from "./gleam/dynamic.mjs"; -import { DecodeError$DecodeError } from "./gleam/dynamic/decode.mjs"; - -const Nil = undefined; - -export function identity(x) { - return x; -} - -export function parse_int(value) { - if (/^[-+]?(\d+)$/.test(value)) { - return Result$Ok(parseInt(value)); - } else { - return Result$Error(Nil); - } -} - -export function parse_float(value) { - if (/^[-+]?(\d+)\.(\d+)([eE][-+]?\d+)?$/.test(value)) { - return Result$Ok(parseFloat(value)); - } else { - return Result$Error(Nil); - } -} - -export function to_string(term) { - return term.toString(); -} - -export function int_to_base_string(int, base) { - return int.toString(base).toUpperCase(); -} - -const int_base_patterns = { - 2: /[^0-1]/, - 3: /[^0-2]/, - 4: /[^0-3]/, - 5: /[^0-4]/, - 6: /[^0-5]/, - 7: /[^0-6]/, - 8: /[^0-7]/, - 9: /[^0-8]/, - 10: /[^0-9]/, - 11: /[^0-9a]/, - 12: /[^0-9a-b]/, - 13: /[^0-9a-c]/, - 14: /[^0-9a-d]/, - 15: /[^0-9a-e]/, - 16: /[^0-9a-f]/, - 17: /[^0-9a-g]/, - 18: /[^0-9a-h]/, - 19: /[^0-9a-i]/, - 20: /[^0-9a-j]/, - 21: /[^0-9a-k]/, - 22: /[^0-9a-l]/, - 23: /[^0-9a-m]/, - 24: /[^0-9a-n]/, - 25: /[^0-9a-o]/, - 26: /[^0-9a-p]/, - 27: /[^0-9a-q]/, - 28: /[^0-9a-r]/, - 29: /[^0-9a-s]/, - 30: /[^0-9a-t]/, - 31: /[^0-9a-u]/, - 32: /[^0-9a-v]/, - 33: /[^0-9a-w]/, - 34: /[^0-9a-x]/, - 35: /[^0-9a-y]/, - 36: /[^0-9a-z]/, -}; - -export function int_from_base_string(string, base) { - if (int_base_patterns[base].test(string.replace(/^-/, "").toLowerCase())) { - return Result$Error(Nil); - } - - const result = parseInt(string, base); - - if (isNaN(result)) { - return Result$Error(Nil); - } - - return Result$Ok(result); -} - -export function string_replace(string, target, substitute) { - return string.replaceAll(target, substitute); -} - -export function string_reverse(string) { - return [...string].reverse().join(""); -} - -export function string_length(string) { - if (string === "") { - return 0; - } - const iterator = graphemes_iterator(string); - if (iterator) { - let i = 0; - for (const _ of iterator) { - i++; - } - return i; - } else { - return string.match(/./gsu).length; - } -} - -export function graphemes(string) { - const iterator = graphemes_iterator(string); - if (iterator) { - return arrayToList(Array.from(iterator).map((item) => item.segment)); - } else { - return arrayToList(string.match(/./gsu)); - } -} - -let segmenter = undefined; - -function graphemes_iterator(string) { - if (globalThis.Intl && Intl.Segmenter) { - segmenter ||= new Intl.Segmenter(); - return segmenter.segment(string)[Symbol.iterator](); - } -} - -export function pop_grapheme(string) { - let first; - const iterator = graphemes_iterator(string); - if (iterator) { - first = iterator.next().value?.segment; - } else { - first = string.match(/./su)?.[0]; - } - if (first) { - return Result$Ok([first, string.slice(first.length)]); - } else { - return Result$Error(Nil); - } -} - -export function pop_codeunit(str) { - return [str.charCodeAt(0) | 0, str.slice(1)]; -} - -export function lowercase(string) { - return string.toLowerCase(); -} - -export function uppercase(string) { - return string.toUpperCase(); -} - -export function less_than(a, b) { - return a < b; -} - -export function add(a, b) { - return a + b; -} - -export function split(xs, pattern) { - return arrayToList(xs.split(pattern)); -} - -export function concat(xs) { - let result = ""; - for (const x of xs) { - result = result + x; - } - return result; -} - -export function length(data) { - return data.length; -} - -export function string_byte_slice(string, index, length) { - return string.slice(index, index + length); -} - -export function string_grapheme_slice(string, idx, len) { - if (len <= 0 || idx >= string.length) { - return ""; - } - - const iterator = graphemes_iterator(string); - if (iterator) { - while (idx-- > 0) { - iterator.next(); - } - - let result = ""; - - while (len-- > 0) { - const v = iterator.next().value; - if (v === undefined) { - break; - } - - result += v.segment; - } - - return result; - } else { - return string - .match(/./gsu) - .slice(idx, idx + len) - .join(""); - } -} - -export function string_codeunit_slice(str, from, length) { - return str.slice(from, from + length); -} -export function crop_string(string, substring) { - return string.substring(string.indexOf(substring)); -} - -export function contains_string(haystack, needle) { - return haystack.indexOf(needle) >= 0; -} - -export function starts_with(haystack, needle) { - return haystack.startsWith(needle); -} - -export function ends_with(haystack, needle) { - return haystack.endsWith(needle); -} - -export function split_once(haystack, needle) { - const index = haystack.indexOf(needle); - if (index >= 0) { - const before = haystack.slice(0, index); - const after = haystack.slice(index + needle.length); - return Result$Ok([before, after]); - } else { - return Result$Error(Nil); - } -} - -const unicode_whitespaces = [ - "\u0020", // Space - "\u0009", // Horizontal tab - "\u000A", // Line feed - "\u000B", // Vertical tab - "\u000C", // Form feed - "\u000D", // Carriage return - "\u0085", // Next line - "\u2028", // Line separator - "\u2029", // Paragraph separator -].join(""); - -const trim_start_regex = /* @__PURE__ */ new RegExp( - `^[${unicode_whitespaces}]*`, -); -const trim_end_regex = /* @__PURE__ */ new RegExp(`[${unicode_whitespaces}]*$`); - -export function trim_start(string) { - return string.replace(trim_start_regex, ""); -} - -export function trim_end(string) { - return string.replace(trim_end_regex, ""); -} - -export function bit_array_from_string(string) { - return toBitArray([stringBits(string)]); -} - -export function bit_array_bit_size(bit_array) { - return bit_array.bitSize; -} - -export function bit_array_byte_size(bit_array) { - return bit_array.byteSize; -} - -export function bit_array_pad_to_bytes(bit_array) { - const trailingBitsCount = bit_array.bitSize % 8; - - // If the bit array is a whole number of bytes it can be returned unchanged - if (trailingBitsCount === 0) { - return bit_array; - } - - const finalByte = bit_array.byteAt(bit_array.byteSize - 1); - - // The required final byte has its unused trailing bits set to zero - const unusedBitsCount = 8 - trailingBitsCount; - const correctFinalByte = (finalByte >> unusedBitsCount) << unusedBitsCount; - - // If the unused bits in the final byte are already set to zero then the - // existing buffer can be re-used, avoiding a copy - if (finalByte === correctFinalByte) { - return new BitArray( - bit_array.rawBuffer, - bit_array.byteSize * 8, - bit_array.bitOffset, - ); - } - - // Copy the bit array into a new aligned buffer and set the correct final byte - const buffer = new Uint8Array(bit_array.byteSize); - for (let i = 0; i < buffer.length - 1; i++) { - buffer[i] = bit_array.byteAt(i); - } - buffer[buffer.length - 1] = correctFinalByte; - - return new BitArray(buffer); -} - -export function bit_array_concat(bit_arrays) { - return toBitArray(bit_arrays.toArray()); -} - -export function console_log(term) { - console.log(term); -} - -export function console_error(term) { - console.error(term); -} - -export function crash(message) { - throw new globalThis.Error(message); -} - -export function bit_array_to_string(bit_array) { - // If the bit array isn't a whole number of bytes then return an error - if (bit_array.bitSize % 8 !== 0) { - return Result$Error(Nil); - } - - try { - const decoder = new TextDecoder("utf-8", { fatal: true }); - - if (bit_array.bitOffset === 0) { - return Result$Ok(decoder.decode(bit_array.rawBuffer)); - } else { - // The input data isn't aligned, so copy it into a new aligned buffer so - // that TextDecoder can be used - const buffer = new Uint8Array(bit_array.byteSize); - for (let i = 0; i < buffer.length; i++) { - buffer[i] = bit_array.byteAt(i); - } - return Result$Ok(decoder.decode(buffer)); - } - } catch { - return Result$Error(Nil); - } -} - -export function print(string) { - if (typeof process === "object" && process.stdout?.write) { - process.stdout.write(string); // We can write without a trailing newline - } else if (typeof Deno === "object") { - Deno.stdout.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline - } else { - console.log(string); // We're in a browser. Newlines are mandated - } -} - -export function print_error(string) { - if (typeof process === "object" && process.stderr?.write) { - process.stderr.write(string); // We can write without a trailing newline - } else if (typeof Deno === "object") { - Deno.stderr.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline - } else { - console.error(string); // We're in a browser. Newlines are mandated - } -} - -export function print_debug(string) { - if (typeof process === "object" && process.stderr?.write) { - process.stderr.write(string + "\n"); // If we're in Node.js, use `stderr` - } else if (typeof Deno === "object") { - Deno.stderr.writeSync(new TextEncoder().encode(string + "\n")); // If we're in Deno, use `stderr` - } else { - console.log(string); // Otherwise, use `console.log` (so that it doesn't look like an error) - } -} - -export function ceiling(float) { - return Math.ceil(float); -} - -export function floor(float) { - return Math.floor(float); -} - -export function round(float) { - return Math.round(float); -} - -export function truncate(float) { - return Math.trunc(float); -} - -export function power(base, exponent) { - // It is checked in Gleam that: - // - The base is non-negative and that the exponent is not fractional. - // - The base is non-zero and the exponent is non-negative (otherwise - // the result will essentially be division by zero). - // It can thus be assumed that valid input is passed to the Math.pow - // function and a NaN or Infinity value will not be produced. - return Math.pow(base, exponent); -} - -export function random_uniform() { - const random_uniform_result = Math.random(); - // With round-to-nearest-even behavior, the ranges claimed for the functions below - // (excluding the one for Math.random() itself) aren't exact. - // If extremely large bounds are chosen (2^53 or higher), - // it's possible in extremely rare cases to calculate the usually-excluded upper bound. - // Note that as numbers in JavaScript are IEEE 754 floating point numbers - // See: - // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: - if (random_uniform_result === 1.0) { - return random_uniform(); - } - return random_uniform_result; -} - -export function bit_array_slice(bits, position, length) { - const start = Math.min(position, position + length); - const end = Math.max(position, position + length); - - if (start < 0 || end * 8 > bits.bitSize) { - return Result$Error(Nil); - } - - return Result$Ok(bitArraySlice(bits, start * 8, end * 8)); -} - -export function codepoint(int) { - return new UtfCodepoint(int); -} - -export function string_to_codepoint_integer_list(string) { - return arrayToList(Array.from(string).map((item) => item.codePointAt(0))); -} - -export function utf_codepoint_list_to_string(utf_codepoint_integer_list) { - return utf_codepoint_integer_list - .toArray() - .map((x) => String.fromCodePoint(x.value)) - .join(""); -} - -export function utf_codepoint_to_int(utf_codepoint) { - return utf_codepoint.value; -} - -function unsafe_percent_decode(string) { - return decodeURIComponent(string || ""); -} - -function unsafe_percent_decode_query(string) { - return decodeURIComponent((string || "").replaceAll("+", " ")); -} - -export function percent_decode(string) { - try { - return Result$Ok(unsafe_percent_decode(string)); - } catch { - return Result$Error(Nil); - } -} - -export function percent_encode(string) { - return encodeURIComponent(string).replaceAll("%2B", "+"); -} - -export function parse_query(query) { - try { - const pairs = []; - for (const section of query.split("&")) { - const [key, value] = section.split("="); - if (!key) continue; - - const decodedKey = unsafe_percent_decode_query(key); - const decodedValue = unsafe_percent_decode_query(value); - pairs.push([decodedKey, decodedValue]); - } - return Result$Ok(arrayToList(pairs)); - } catch { - return Result$Error(Nil); - } -} - -const b64EncodeLookup = [ - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, -]; - -let b64TextDecoder; - -// Implementation based on https://github.com/mitschabaude/fast-base64/blob/main/js.js -export function base64_encode(bit_array, padding) { - b64TextDecoder ??= new TextDecoder(); - - bit_array = bit_array_pad_to_bytes(bit_array); - - const m = bit_array.byteSize; - const k = m % 3; - const n = Math.floor(m / 3) * 4 + (k && k + 1); - const N = Math.ceil(m / 3) * 4; - const encoded = new Uint8Array(N); - - for (let i = 0, j = 0; j < m; i += 4, j += 3) { - const y = - (bit_array.byteAt(j) << 16) + - (bit_array.byteAt(j + 1) << 8) + - (bit_array.byteAt(j + 2) | 0); - - encoded[i] = b64EncodeLookup[y >> 18]; - encoded[i + 1] = b64EncodeLookup[(y >> 12) & 0x3f]; - encoded[i + 2] = b64EncodeLookup[(y >> 6) & 0x3f]; - encoded[i + 3] = b64EncodeLookup[y & 0x3f]; - } - - let base64 = b64TextDecoder.decode(new Uint8Array(encoded.buffer, 0, n)); - - if (padding) { - if (k === 1) { - base64 += "=="; - } else if (k === 2) { - base64 += "="; - } - } - - return base64; -} - -// From https://developer.mozilla.org/en-US/docs/Glossary/Base64 -export function base64_decode(sBase64) { - try { - const binString = atob(sBase64); - const length = binString.length; - const array = new Uint8Array(length); - for (let i = 0; i < length; i++) { - array[i] = binString.charCodeAt(i); - } - return Result$Ok(new BitArray(array)); - } catch { - return Result$Error(Nil); - } -} - -export function classify_dynamic(data) { - if (typeof data === "string") { - return "String"; - } else if (typeof data === "boolean") { - return "Bool"; - } else if (isResult(data)) { - return "Result"; - } else if (isList(data)) { - return "List"; - } else if (data instanceof BitArray) { - return "BitArray"; - } else if (data instanceof Dict) { - return "Dict"; - } else if (Number.isInteger(data)) { - return "Int"; - } else if (Array.isArray(data)) { - return `Array`; - } else if (typeof data === "number") { - return "Float"; - } else if (data === null) { - return "Nil"; - } else if (data === undefined) { - return "Nil"; - } else { - const type = typeof data; - return type.charAt(0).toUpperCase() + type.slice(1); - } -} - -export function byte_size(string) { - return new TextEncoder().encode(string).length; -} - -// In JavaScript, bitwise operations convert numbers to a sequence of 32 bits, -// while Erlang uses arbitrary precision integers. -// -// To get around this, every function here follows this pattern: -// -// 1. If both values fit in the 32-bit signed integer range, use the standard -// JavaScript bitwise operators directly. -// -// Note: For bitwise_shift_left, the result also needs to fit in 32 bits, -// so we use floating-point multiplication instead. -// -// 2. If either value falls outside the safe integer range (-2^53, 2^53), -// fall back to BigInt arithmetic, then downcast the result back to a Number. -// -// 3. Otherwise (safe integers outside the 32-bit range), we split the operation -// across the high 21 bits and low 32 bits individually: -// -// x1 $ x2 = ((hi(x1) $ hi(x2)) << 32) | (lo(x1) $ lo(x2)) -// -// where `$` is a bitwise operator. -// -// We split both values into a `hi` and a `lo` part: -// -// hi(x) = Math.floor(x / 2^32) the upper 21 bits -// lo(x) = x >>> 0 the lower 32 bits (as unsigned) -// -// For `hi`, we use that shifts are equal to multiplication/division with -// powers of two to get around the 32-bit range limitation. Math.floor is -// used instead of truncation since arithmetic right shift fills with the -// sign bit. For negative numbers, the discarded bits were non-zero -// (representing a positive fractional part), so discarding them makes the -// result strictly more negative, i.e. rounding away from 0. -// -// This works because bitwise operators are distributive across bit ranges: -// -// x1 $ x2 = (hi(x1) $ hi(x2)) << 32 | (lo(x1) $ lo(x2)) -// = (hi(x1) $ hi(x2)) * 2^32 + (lo(x1) $ lo(x2)) -// -// JavaScript bitwise operators truncate inputs to signed 32-bit integers, -// so `x1 $ x2` already computes `lo(x1) $ lo(x2)` — we just need to -// reinterpret the signed result as unsigned using `>>> 0`: -// -// lo(x1) $ lo(x2) = (x1 $ x2) >>> 0 = lo(x1 $ x2) -// => x1 $ x2 = (hi(x1) $ hi(x2)) * 2^32 + lo(x1 $ x2). -// -const MIN_I32 = -(2 ** 31); // -2147483648 -const MAX_I32 = 2 ** 31 - 1; // 2147483647 -const U32 = 2 ** 32; -const MAX_SAFE = Number.MAX_SAFE_INTEGER; -const MIN_SAFE = Number.MIN_SAFE_INTEGER; - -export function bitwise_and(x, y) { - if (x >= MIN_I32 && x <= MAX_I32 && y >= MIN_I32 && y <= MAX_I32) - return x & y; - if (x < MIN_SAFE || x > MAX_SAFE || y < MIN_SAFE || y > MAX_SAFE) - return Number(BigInt(x) & BigInt(y)); - - return (Math.floor(x / U32) & Math.floor(y / U32)) * U32 + ((x & y) >>> 0); -} - -export function bitwise_or(x, y) { - if (x >= MIN_I32 && x <= MAX_I32 && y >= MIN_I32 && y <= MAX_I32) - return x | y; - if (x < MIN_SAFE || x > MAX_SAFE || y < MIN_SAFE || y > MAX_SAFE) - return Number(BigInt(x) | BigInt(y)); - - return (Math.floor(x / U32) | Math.floor(y / U32)) * U32 + ((x | y) >>> 0); -} - -export function bitwise_exclusive_or(x, y) { - if (x >= MIN_I32 && x <= MAX_I32 && y >= MIN_I32 && y <= MAX_I32) - return x ^ y; - if (x < MIN_SAFE || x > MAX_SAFE || y < MIN_SAFE || y > MAX_SAFE) - return Number(BigInt(x) ^ BigInt(y)); - - return (Math.floor(x / U32) ^ Math.floor(y / U32)) * U32 + ((x ^ y) >>> 0); -} - -export function bitwise_not(x) { - if (x >= MIN_I32 && x <= MAX_I32) return ~x; - if (x < MIN_SAFE || x > MAX_SAFE) return Number(~BigInt(x)); - - return ~Math.floor(x / U32) * U32 + (~x >>> 0); -} - -export function bitwise_shift_right(x, y) { - if (y === 0) return x; - if (y < 0) return bitwise_shift_left(x, -y); - if (y < 32 && x >= MIN_I32 && x <= MAX_I32) return x >> y; - if (x < MIN_SAFE || x > MAX_SAFE) return Number(BigInt(x) >> BigInt(y)); - - const ahi = Math.floor(x / U32); - - // Shifting right by y < 32 moves bits across the hi/lo boundary: - // - // before: [ hi (21 bits) | lo (32 bits) ] - // after: [ hi >> y | (hi's low y bits) ++ (lo >> y) ] - // - // The new low word has two sources: - // - lo's bits shifted down: x >>> y (>>> treats x as unsigned 32-bit) - // - hi's bottom y bits shifted up: ahi << (32 - y). - if (y < 32) return (ahi >> y) * U32 + (((x >>> y) | (ahi << (32 - y))) >>> 0); - - // Shifting by >= 32 wipes out the entire low word. The result is just the - // high word shifted right by the remaining amount. - return ahi >> (y - 32); -} - -export function bitwise_shift_left(x, y) { - if (y === 0) return x; - if (y < 0) return bitwise_shift_right(x, -y); - if (y < 31) return x * (1 << y); - return x * 2 ** y; -} - -export function inspect(v) { - return new Inspector().inspect(v); -} - -export function float_to_string(float) { - const string = float.toString().replace("+", ""); - if (string.indexOf(".") >= 0) { - return string; - } else { - const index = string.indexOf("e"); - if (index >= 0) { - return string.slice(0, index) + ".0" + string.slice(index); - } else { - return string + ".0"; - } - } -} - -class Inspector { - #references = new Set(); - - inspect(v) { - const t = typeof v; - if (v === true) return "True"; - if (v === false) return "False"; - if (v === null) return "//js(null)"; - if (v === undefined) return "Nil"; - if (t === "string") return this.#string(v); - if (t === "bigint" || Number.isInteger(v)) return v.toString(); - if (t === "number") return float_to_string(v); - if (v instanceof UtfCodepoint) return this.#utfCodepoint(v); - if (v instanceof BitArray) return this.#bit_array(v); - if (v instanceof RegExp) return `//js(${v})`; - if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; - if (v instanceof globalThis.Error) return `//js(${v.toString()})`; - if (v instanceof Function) { - const args = []; - for (const i of Array(v.length).keys()) - args.push(String.fromCharCode(i + 97)); - return `//fn(${args.join(", ")}) { ... }`; - } - - if (this.#references.size === this.#references.add(v).size) { - return "//js(circular reference)"; - } - - let printed; - if (Array.isArray(v)) { - printed = `#(${v.map((v) => this.inspect(v)).join(", ")})`; - } else if (isList(v)) { - printed = this.#list(v); - } else if (v instanceof CustomType) { - printed = this.#customType(v); - } else if (v instanceof Dict) { - printed = this.#dict(v); - } else if (v instanceof Set) { - return `//js(Set(${[...v].map((v) => this.inspect(v)).join(", ")}))`; - } else { - printed = this.#object(v); - } - this.#references.delete(v); - return printed; - } - - #object(v) { - const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; - const props = []; - for (const k of Object.keys(v)) { - props.push(`${this.inspect(k)}: ${this.inspect(v[k])}`); - } - const body = props.length ? " " + props.join(", ") + " " : ""; - const head = name === "Object" ? "" : name + " "; - return `//js(${head}{${body}})`; - } - - #dict(map) { - let body = "dict.from_list(["; - let first = true; - - body = dict_fold(map, body, (body, key, value) => { - if (!first) body = body + ", "; - first = false; - return body + "#(" + this.inspect(key) + ", " + this.inspect(value) + ")"; - }); - - return body + "])"; - } - - #customType(record) { - const props = Object.keys(record) - .map((label) => { - const value = this.inspect(record[label]); - return isNaN(parseInt(label)) ? `${label}: ${value}` : value; - }) - .join(", "); - return props - ? `${record.constructor.name}(${props})` - : record.constructor.name; - } - - #list(list) { - if (List$isEmpty(list)) { - return "[]"; - } - - let char_out = 'charlist.from_string("'; - let list_out = "["; - - let current = list; - while (List$isNonEmpty(current)) { - let element = current.head; - current = current.tail; - - if (list_out !== "[") { - list_out += ", "; - } - list_out += this.inspect(element); - - if (char_out) { - if (Number.isInteger(element) && element >= 32 && element <= 126) { - char_out += String.fromCharCode(element); - } else { - char_out = null; - } - } - } - - if (char_out) { - return char_out + '")'; - } else { - return list_out + "]"; - } - } - - #string(str) { - let new_str = '"'; - for (let i = 0; i < str.length; i++) { - const char = str[i]; - switch (char) { - case "\n": - new_str += "\\n"; - break; - case "\r": - new_str += "\\r"; - break; - case "\t": - new_str += "\\t"; - break; - case "\f": - new_str += "\\f"; - break; - case "\\": - new_str += "\\\\"; - break; - case '"': - new_str += '\\"'; - break; - default: - if (char < " " || (char > "~" && char < "\u{00A0}")) { - new_str += - "\\u{" + - char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + - "}"; - } else { - new_str += char; - } - } - } - new_str += '"'; - return new_str; - } - - #utfCodepoint(codepoint) { - return `//utfcodepoint(${String.fromCodePoint(codepoint.value)})`; - } - - #bit_array(bits) { - if (bits.bitSize === 0) { - return "<<>>"; - } - - let acc = "<<"; - - for (let i = 0; i < bits.byteSize - 1; i++) { - acc += bits.byteAt(i).toString(); - acc += ", "; - } - - if (bits.byteSize * 8 === bits.bitSize) { - acc += bits.byteAt(bits.byteSize - 1).toString(); - } else { - const trailingBitsCount = bits.bitSize % 8; - acc += bits.byteAt(bits.byteSize - 1) >> (8 - trailingBitsCount); - acc += `:size(${trailingBitsCount})`; - } - - acc += ">>"; - return acc; - } -} - -export function base16_encode(bit_array) { - const trailingBitsCount = bit_array.bitSize % 8; - - let result = ""; - - for (let i = 0; i < bit_array.byteSize; i++) { - let byte = bit_array.byteAt(i); - - if (i === bit_array.byteSize - 1 && trailingBitsCount !== 0) { - const unusedBitsCount = 8 - trailingBitsCount; - byte = (byte >> unusedBitsCount) << unusedBitsCount; - } - - result += byte.toString(16).padStart(2, "0").toUpperCase(); - } - - return result; -} - -export function base16_decode(string) { - const bytes = new Uint8Array(string.length / 2); - for (let i = 0; i < string.length; i += 2) { - const a = parseInt(string[i], 16); - const b = parseInt(string[i + 1], 16); - if (isNaN(a) || isNaN(b)) return Result$Error(Nil); - bytes[i / 2] = a * 16 + b; - } - return Result$Ok(new BitArray(bytes)); -} - -export function bit_array_to_int_and_size(bits) { - const trailingBitsCount = bits.bitSize % 8; - const unusedBitsCount = trailingBitsCount === 0 ? 0 : 8 - trailingBitsCount; - - return [bits.byteAt(0) >> unusedBitsCount, bits.bitSize]; -} - -export function bit_array_starts_with(bits, prefix) { - if (prefix.bitSize > bits.bitSize) { - return false; - } - - // Check any whole bytes - const byteCount = Math.trunc(prefix.bitSize / 8); - for (let i = 0; i < byteCount; i++) { - if (bits.byteAt(i) !== prefix.byteAt(i)) { - return false; - } - } - - // Check any trailing bits at the end of the prefix - if (prefix.bitSize % 8 !== 0) { - const unusedBitsCount = 8 - (prefix.bitSize % 8); - if ( - bits.byteAt(byteCount) >> unusedBitsCount !== - prefix.byteAt(byteCount) >> unusedBitsCount - ) { - return false; - } - } - - return true; -} - -export function log(x) { - // It is checked in Gleam that: - // - The input is strictly positive (x > 0) - // - This ensures that Math.log will never return NaN or -Infinity - // The function can thus safely pass the input to Math.log - // and a valid finite float will always be produced. - return Math.log(x); -} - -export function exp(x) { - return Math.exp(x); -} - -export function list_to_array(list) { - let current = list; - let array = []; - while (List$isNonEmpty(current)) { - array.push(current.head); - current = current.tail; - } - return array; -} - -export function index(data, key) { - // Dictionaries and dictionary-like objects can be indexed - if (data instanceof Dict) { - const result = dict_get(data, key); - return Result$Ok(result.isOk() ? new Some(result[0]) : new None()); - } - - if (data instanceof WeakMap || data instanceof Map) { - const token = {}; - const entry = data.get(key, token); - if (entry === token) return Result$Ok(new None()); - return Result$Ok(new Some(entry)); - } - - const key_is_int = Number.isInteger(key); - - // Only elements 0-7 of lists can be indexed, negative indices are not allowed - if (key_is_int && key >= 0 && key < 8 && isList(data)) { - let i = 0; - for (const value of data) { - if (i === key) return Result$Ok(new Some(value)); - i++; - } - return Result$Error("Indexable"); - } - - // Arrays and objects can be indexed - if ( - (key_is_int && Array.isArray(data)) || - (data && typeof data === "object") || - (data && Object.getPrototypeOf(data) === Object.prototype) - ) { - if (key in data) return Result$Ok(new Some(data[key])); - return Result$Ok(new None()); - } - - return Result$Error(key_is_int ? "Indexable" : "Dict"); -} - -export function list(data, decode, pushPath, index, emptyList) { - if (!(isList(data) || Array.isArray(data))) { - const error = DecodeError$DecodeError("List", classify(data), emptyList); - return [emptyList, arrayToList([error])]; - } - - const decoded = []; - - for (const element of data) { - const layer = decode(element); - const [out, errors] = layer; - - if (List$isNonEmpty(errors)) { - const [_, errors] = pushPath(layer, index.toString()); - return [emptyList, errors]; - } - decoded.push(out); - index++; - } - - return [arrayToList(decoded), emptyList]; -} - -export function dict(data) { - if (data instanceof Dict) { - return Result$Ok(data); - } - if (data instanceof Map || data instanceof WeakMap) { - return Result$Ok(dict_from_iterable(data)); - } - if (data == null) { - return Result$Error("Dict"); - } - if (typeof data !== "object") { - return Result$Error("Dict"); - } - const proto = Object.getPrototypeOf(data); - if (proto === Object.prototype || proto === null) { - return Result$Ok(dict_from_iterable(Object.entries(data))); - } - return Result$Error("Dict"); -} - -export function bit_array(data) { - if (data instanceof BitArray) return Result$Ok(data); - if (data instanceof Uint8Array) return Result$Ok(new BitArray(data)); - return Result$Error(new BitArray(new Uint8Array())); -} - -export function float(data) { - if (typeof data === "number") return Result$Ok(data); - return Result$Error(0.0); -} - -export function int(data) { - if (Number.isInteger(data)) return Result$Ok(data); - return Result$Error(0); -} - -export function string(data) { - if (typeof data === "string") return Result$Ok(data); - return Result$Error(""); -} - -export function is_null(data) { - return data === null || data === undefined; -} - -function arrayToList(array) { - let list = List$Empty(); - let i = array.length; - while (i--) { - list = List$NonEmpty(array[i], list); - } - return list; -} - -function isList(data) { - return List$isEmpty(data) || List$isNonEmpty(data); -} - -function isResult(data) { - return Result$isOk(data) || Result$isError(data); -} - -export function string_remove_prefix(string, prefix) { - if (string.startsWith(prefix)) { - return string.slice(prefix.length); - } - return string; -} - -export function string_remove_suffix(string, suffix) { - if (string.endsWith(suffix)) { - return string.slice(0, string.length - suffix.length); - } - return string; -} diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit.cache b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit.cache deleted file mode 100644 index 3f2b8f1..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit.cache and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_meta b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_meta deleted file mode 100644 index 5c75cc9..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit.cache_meta and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache deleted file mode 100644 index d41b76e..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta deleted file mode 100644 index cbface3..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@gleam_panic.cache_meta and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache deleted file mode 100644 index 58f98ad..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta deleted file mode 100644 index e33b0da..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@internal@reporting.cache_meta and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache deleted file mode 100644 index a759bef..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache and /dev/null differ diff --git a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta b/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta deleted file mode 100644 index 1cab53c..0000000 Binary files a/ui/javascript/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta and /dev/null differ diff --git a/ui/javascript/gleeunit/gleam.mjs b/ui/javascript/gleeunit/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/ui/javascript/gleeunit/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/ui/javascript/gleeunit/gleeunit.erl b/ui/javascript/gleeunit/gleeunit.erl deleted file mode 100644 index bcb58b6..0000000 --- a/ui/javascript/gleeunit/gleeunit.erl +++ /dev/null @@ -1,89 +0,0 @@ --module(gleeunit). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit.gleam"). --export([main/0]). --export_type([atom_/0, encoding/0, report_module_name/0, gleeunit_progress_option/0, eunit_option/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type atom_() :: any(). - --type encoding() :: utf8. - --type report_module_name() :: gleeunit_progress. - --type gleeunit_progress_option() :: {colored, boolean()}. - --type eunit_option() :: verbose | - no_tty | - {report, {report_module_name(), list(gleeunit_progress_option())}} | - {scale_timeouts, integer()}. - --file("src/gleeunit.gleam", 42). --spec gleam_to_erlang_module_name(binary()) -> binary(). -gleam_to_erlang_module_name(Path) -> - case gleam_stdlib:string_ends_with(Path, <<".gleam"/utf8>>) of - true -> - _pipe = Path, - _pipe@1 = gleam@string:replace( - _pipe, - <<".gleam"/utf8>>, - <<""/utf8>> - ), - gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"@"/utf8>>); - - false -> - _pipe@2 = Path, - _pipe@3 = gleam@string:split(_pipe@2, <<"/"/utf8>>), - _pipe@4 = gleam@list:last(_pipe@3), - _pipe@5 = gleam@result:unwrap(_pipe@4, Path), - gleam@string:replace(_pipe@5, <<".erl"/utf8>>, <<""/utf8>>) - end. - --file("src/gleeunit.gleam", 18). --spec do_main() -> nil. -do_main() -> - Options = [verbose, - no_tty, - {report, {gleeunit_progress, [{colored, true}]}}, - {scale_timeouts, 10}], - Result = begin - _pipe = gleeunit_ffi:find_files( - <<"**/*.{erl,gleam}"/utf8>>, - <<"test"/utf8>> - ), - _pipe@1 = gleam@list:map(_pipe, fun gleam_to_erlang_module_name/1), - _pipe@2 = gleam@list:map( - _pipe@1, - fun(_capture) -> erlang:binary_to_atom(_capture, utf8) end - ), - gleeunit_ffi:run_eunit(_pipe@2, Options) - end, - Code = case Result of - {ok, _} -> - 0; - - {error, _} -> - 1 - end, - erlang:halt(Code). - --file("src/gleeunit.gleam", 13). -?DOC( - " Find and run all test functions for the current project using Erlang's EUnit\n" - " test framework, or a custom JavaScript test runner.\n" - "\n" - " Any Erlang or Gleam function in the `test` directory with a name ending in\n" - " `_test` is considered a test function and will be run.\n" - "\n" - " A test that panics is considered a failure.\n" -). --spec main() -> nil. -main() -> - do_main(). diff --git a/ui/javascript/gleeunit/gleeunit.mjs b/ui/javascript/gleeunit/gleeunit.mjs deleted file mode 100644 index 83018dd..0000000 --- a/ui/javascript/gleeunit/gleeunit.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $result from "../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../gleam_stdlib/gleam/string.mjs"; -import { CustomType as $CustomType } from "./gleam.mjs"; -import { main as do_main } from "./gleeunit_ffi.mjs"; - -class Utf8 extends $CustomType {} - -class GleeunitProgress extends $CustomType {} - -class Colored extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class Verbose extends $CustomType {} - -class NoTty extends $CustomType {} - -class Report extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -class ScaleTimeouts extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} - -function gleam_to_erlang_module_name(path) { - let $ = $string.ends_with(path, ".gleam"); - if ($) { - let _pipe = path; - let _pipe$1 = $string.replace(_pipe, ".gleam", ""); - return $string.replace(_pipe$1, "/", "@"); - } else { - let _pipe = path; - let _pipe$1 = $string.split(_pipe, "/"); - let _pipe$2 = $list.last(_pipe$1); - let _pipe$3 = $result.unwrap(_pipe$2, path); - return $string.replace(_pipe$3, ".erl", ""); - } -} - -/** - * Find and run all test functions for the current project using Erlang's EUnit - * test framework, or a custom JavaScript test runner. - * - * Any Erlang or Gleam function in the `test` directory with a name ending in - * `_test` is considered a test function and will be run. - * - * A test that panics is considered a failure. - */ -export function main() { - return do_main(); -} diff --git a/ui/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs b/ui/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs deleted file mode 100644 index f6af89d..0000000 --- a/ui/javascript/gleeunit/gleeunit/internal/gleam_panic.mjs +++ /dev/null @@ -1,180 +0,0 @@ -import * as $dynamic from "../../../gleam_stdlib/gleam/dynamic.mjs"; -import { CustomType as $CustomType } from "../../gleam.mjs"; -import { from_dynamic } from "./gleeunit_gleam_panic_ffi.mjs"; - -export { from_dynamic }; - -export class GleamPanic extends $CustomType { - constructor(message, file, module, function$, line, kind) { - super(); - this.message = message; - this.file = file; - this.module = module; - this.function = function$; - this.line = line; - this.kind = kind; - } -} -export const GleamPanic$GleamPanic = (message, file, module, function$, line, kind) => - new GleamPanic(message, file, module, function$, line, kind); -export const GleamPanic$isGleamPanic = (value) => value instanceof GleamPanic; -export const GleamPanic$GleamPanic$message = (value) => value.message; -export const GleamPanic$GleamPanic$0 = (value) => value.message; -export const GleamPanic$GleamPanic$file = (value) => value.file; -export const GleamPanic$GleamPanic$1 = (value) => value.file; -export const GleamPanic$GleamPanic$module = (value) => value.module; -export const GleamPanic$GleamPanic$2 = (value) => value.module; -export const GleamPanic$GleamPanic$function = (value) => value.function; -export const GleamPanic$GleamPanic$3 = (value) => value.function; -export const GleamPanic$GleamPanic$line = (value) => value.line; -export const GleamPanic$GleamPanic$4 = (value) => value.line; -export const GleamPanic$GleamPanic$kind = (value) => value.kind; -export const GleamPanic$GleamPanic$5 = (value) => value.kind; - -export class Todo extends $CustomType {} -export const PanicKind$Todo = () => new Todo(); -export const PanicKind$isTodo = (value) => value instanceof Todo; - -export class Panic extends $CustomType {} -export const PanicKind$Panic = () => new Panic(); -export const PanicKind$isPanic = (value) => value instanceof Panic; - -export class LetAssert extends $CustomType { - constructor(start, end, pattern_start, pattern_end, value) { - super(); - this.start = start; - this.end = end; - this.pattern_start = pattern_start; - this.pattern_end = pattern_end; - this.value = value; - } -} -export const PanicKind$LetAssert = (start, end, pattern_start, pattern_end, value) => - new LetAssert(start, end, pattern_start, pattern_end, value); -export const PanicKind$isLetAssert = (value) => value instanceof LetAssert; -export const PanicKind$LetAssert$start = (value) => value.start; -export const PanicKind$LetAssert$0 = (value) => value.start; -export const PanicKind$LetAssert$end = (value) => value.end; -export const PanicKind$LetAssert$1 = (value) => value.end; -export const PanicKind$LetAssert$pattern_start = (value) => value.pattern_start; -export const PanicKind$LetAssert$2 = (value) => value.pattern_start; -export const PanicKind$LetAssert$pattern_end = (value) => value.pattern_end; -export const PanicKind$LetAssert$3 = (value) => value.pattern_end; -export const PanicKind$LetAssert$value = (value) => value.value; -export const PanicKind$LetAssert$4 = (value) => value.value; - -export class Assert extends $CustomType { - constructor(start, end, expression_start, kind) { - super(); - this.start = start; - this.end = end; - this.expression_start = expression_start; - this.kind = kind; - } -} -export const PanicKind$Assert = (start, end, expression_start, kind) => - new Assert(start, end, expression_start, kind); -export const PanicKind$isAssert = (value) => value instanceof Assert; -export const PanicKind$Assert$start = (value) => value.start; -export const PanicKind$Assert$0 = (value) => value.start; -export const PanicKind$Assert$end = (value) => value.end; -export const PanicKind$Assert$1 = (value) => value.end; -export const PanicKind$Assert$expression_start = (value) => - value.expression_start; -export const PanicKind$Assert$2 = (value) => value.expression_start; -export const PanicKind$Assert$kind = (value) => value.kind; -export const PanicKind$Assert$3 = (value) => value.kind; - -export class BinaryOperator extends $CustomType { - constructor(operator, left, right) { - super(); - this.operator = operator; - this.left = left; - this.right = right; - } -} -export const AssertKind$BinaryOperator = (operator, left, right) => - new BinaryOperator(operator, left, right); -export const AssertKind$isBinaryOperator = (value) => - value instanceof BinaryOperator; -export const AssertKind$BinaryOperator$operator = (value) => value.operator; -export const AssertKind$BinaryOperator$0 = (value) => value.operator; -export const AssertKind$BinaryOperator$left = (value) => value.left; -export const AssertKind$BinaryOperator$1 = (value) => value.left; -export const AssertKind$BinaryOperator$right = (value) => value.right; -export const AssertKind$BinaryOperator$2 = (value) => value.right; - -export class FunctionCall extends $CustomType { - constructor(arguments$) { - super(); - this.arguments = arguments$; - } -} -export const AssertKind$FunctionCall = (arguments$) => - new FunctionCall(arguments$); -export const AssertKind$isFunctionCall = (value) => - value instanceof FunctionCall; -export const AssertKind$FunctionCall$arguments = (value) => value.arguments; -export const AssertKind$FunctionCall$0 = (value) => value.arguments; - -export class OtherExpression extends $CustomType { - constructor(expression) { - super(); - this.expression = expression; - } -} -export const AssertKind$OtherExpression = (expression) => - new OtherExpression(expression); -export const AssertKind$isOtherExpression = (value) => - value instanceof OtherExpression; -export const AssertKind$OtherExpression$expression = (value) => - value.expression; -export const AssertKind$OtherExpression$0 = (value) => value.expression; - -export class AssertedExpression extends $CustomType { - constructor(start, end, kind) { - super(); - this.start = start; - this.end = end; - this.kind = kind; - } -} -export const AssertedExpression$AssertedExpression = (start, end, kind) => - new AssertedExpression(start, end, kind); -export const AssertedExpression$isAssertedExpression = (value) => - value instanceof AssertedExpression; -export const AssertedExpression$AssertedExpression$start = (value) => - value.start; -export const AssertedExpression$AssertedExpression$0 = (value) => value.start; -export const AssertedExpression$AssertedExpression$end = (value) => value.end; -export const AssertedExpression$AssertedExpression$1 = (value) => value.end; -export const AssertedExpression$AssertedExpression$kind = (value) => value.kind; -export const AssertedExpression$AssertedExpression$2 = (value) => value.kind; - -export class Literal extends $CustomType { - constructor(value) { - super(); - this.value = value; - } -} -export const ExpressionKind$Literal = (value) => new Literal(value); -export const ExpressionKind$isLiteral = (value) => value instanceof Literal; -export const ExpressionKind$Literal$value = (value) => value.value; -export const ExpressionKind$Literal$0 = (value) => value.value; - -export class Expression extends $CustomType { - constructor(value) { - super(); - this.value = value; - } -} -export const ExpressionKind$Expression = (value) => new Expression(value); -export const ExpressionKind$isExpression = (value) => - value instanceof Expression; -export const ExpressionKind$Expression$value = (value) => value.value; -export const ExpressionKind$Expression$0 = (value) => value.value; - -export class Unevaluated extends $CustomType {} -export const ExpressionKind$Unevaluated = () => new Unevaluated(); -export const ExpressionKind$isUnevaluated = (value) => - value instanceof Unevaluated; diff --git a/ui/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl b/ui/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl deleted file mode 100644 index d78f5e5..0000000 --- a/ui/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(gleeunit_gleam_panic_ffi). --export([from_dynamic/1]). - -from_dynamic(#{ - gleam_error := assert, - start := Start, - 'end' := End, - expression_start := EStart -} = E) -> - wrap(E, {assert, Start, End, EStart, assert_kind(E)}); -from_dynamic(#{ - gleam_error := let_assert, - start := Start, - 'end' := End, - pattern_start := PStart, - pattern_end := PEnd, - value := Value -} = E) -> - wrap(E, {let_assert, Start, End, PStart, PEnd, Value}); -from_dynamic(#{gleam_error := panic} = E) -> - wrap(E, panic); -from_dynamic(#{gleam_error := todo} = E) -> - wrap(E, todo); -from_dynamic(_) -> - {error, nil}. - -assert_kind(#{kind := binary_operator, left := L, right := R, operator := O}) -> - {binary_operator, atom_to_binary(O), expression(L), expression(R)}; -assert_kind(#{kind := function_call, arguments := Arguments}) -> - {function_call, lists:map(fun expression/1, Arguments)}; -assert_kind(#{kind := expression, expression := Expression}) -> - {other_expression, expression(Expression)}. - -expression(#{start := S, 'end' := E, kind := literal, value := Value}) -> - {asserted_expression, S, E, {literal, Value}}; -expression(#{start := S, 'end' := E, kind := expression, value := Value}) -> - {asserted_expression, S, E, {expression, Value}}; -expression(#{start := S, 'end' := E, kind := unevaluated}) -> - {asserted_expression, S, E, unevaluated}. - -wrap(#{ - gleam_error := _, - file := File, - message := Message, - module := Module, - function := Function, - line := Line -}, Kind) -> - {ok, {gleam_panic, Message, File, Module, Function, Line, Kind}}. diff --git a/ui/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs b/ui/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs deleted file mode 100644 index 03f6025..0000000 --- a/ui/javascript/gleeunit/gleeunit/internal/gleeunit_gleam_panic_ffi.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import { Result$Ok, Result$Error, List$Empty, List$NonEmpty } from "../../gleam.mjs"; -import { - GleamPanic$GleamPanic, - PanicKind$Todo, - PanicKind$Panic, - PanicKind$LetAssert, - PanicKind$Assert, - AssertKind$BinaryOperator, - AssertKind$FunctionCall, - AssertKind$OtherExpression, - AssertedExpression$AssertedExpression, - ExpressionKind$Literal, - ExpressionKind$Expression, - ExpressionKind$Unevaluated, -} from "./gleam_panic.mjs"; - -export function from_dynamic(error) { - if (!(error instanceof globalThis.Error) || !error.gleam_error) { - return Result$Error(undefined); - } - - if (error.gleam_error === "todo") { - return wrap(error, PanicKind$Todo()); - } - - if (error.gleam_error === "panic") { - return wrap(error, PanicKind$Panic()); - } - - if (error.gleam_error === "let_assert") { - let kind = PanicKind$LetAssert( - error.start, - error.end, - error.pattern_start, - error.pattern_end, - error.value, - ); - return wrap(error, kind); - } - - if (error.gleam_error === "assert") { - let kind = PanicKind$Assert( - error.start, - error.end, - error.expression_start, - assert_kind(error), - ); - return wrap(error, kind); - } - - return Result$Error(undefined); -} - -function assert_kind(error) { - if (error.kind == "binary_operator") { - return AssertKind$BinaryOperator( - error.operator, - expression(error.left), - expression(error.right), - ); - } - - if (error.kind == "function_call") { - let list = List$Empty(); - let i = error.arguments.length; - while (i--) { - list = List$NonEmpty(expression(error.arguments[i]), list); - } - return AssertKind$FunctionCall(list); - } - - return AssertKind$OtherExpression(expression(error.expression)); -} - -function expression(data) { - const expression = AssertedExpression$AssertedExpression(data.start, data.end, undefined); - if (data.kind == "literal") { - expression.kind = ExpressionKind$Literal(data.value); - } else if (data.kind == "expression") { - expression.kind = ExpressionKind$Expression(data.value); - } else { - expression.kind = ExpressionKind$Unevaluated(); - } - return expression; -} - -function wrap(e, kind) { - return Result$Ok( - GleamPanic$GleamPanic(e.message, e.file, e.module, e.function, e.line, kind), - ); -} diff --git a/ui/javascript/gleeunit/gleeunit/internal/reporting.mjs b/ui/javascript/gleeunit/gleeunit/internal/reporting.mjs deleted file mode 100644 index 636c3e2..0000000 --- a/ui/javascript/gleeunit/gleeunit/internal/reporting.mjs +++ /dev/null @@ -1,257 +0,0 @@ -import * as $bit_array from "../../../gleam_stdlib/gleam/bit_array.mjs"; -import * as $dynamic from "../../../gleam_stdlib/gleam/dynamic.mjs"; -import * as $int from "../../../gleam_stdlib/gleam/int.mjs"; -import * as $io from "../../../gleam_stdlib/gleam/io.mjs"; -import * as $list from "../../../gleam_stdlib/gleam/list.mjs"; -import * as $option from "../../../gleam_stdlib/gleam/option.mjs"; -import * as $result from "../../../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../../../gleam_stdlib/gleam/string.mjs"; -import { Ok, Error, toList, CustomType as $CustomType } from "../../gleam.mjs"; -import * as $gleam_panic from "../../gleeunit/internal/gleam_panic.mjs"; -import { read_file as read_file_text } from "../../gleeunit_ffi.mjs"; - -export class State extends $CustomType { - constructor(passed, failed, skipped) { - super(); - this.passed = passed; - this.failed = failed; - this.skipped = skipped; - } -} -export const State$State = (passed, failed, skipped) => - new State(passed, failed, skipped); -export const State$isState = (value) => value instanceof State; -export const State$State$passed = (value) => value.passed; -export const State$State$0 = (value) => value.passed; -export const State$State$failed = (value) => value.failed; -export const State$State$1 = (value) => value.failed; -export const State$State$skipped = (value) => value.skipped; -export const State$State$2 = (value) => value.skipped; - -export function new_state() { - return new State(0, 0, 0); -} - -function red(text) { - return ("\u{001b}[31m" + text) + "\u{001b}[39m"; -} - -function yellow(text) { - return ("\u{001b}[33m" + text) + "\u{001b}[39m"; -} - -function green(text) { - return ("\u{001b}[32m" + text) + "\u{001b}[39m"; -} - -export function finished(state) { - let $ = state.failed; - if ($ === 0) { - let $1 = state.skipped; - if ($1 === 0) { - let $2 = state.passed; - if ($2 === 0) { - $io.println("\nNo tests found!"); - return 1; - } else { - let message = ("\n" + $int.to_string(state.passed)) + " passed, no failures"; - $io.println(green(message)); - return 0; - } - } else { - let message = ((("\n" + $int.to_string(state.passed)) + " passed, 0 failures, ") + $int.to_string( - state.skipped, - )) + " skipped"; - $io.println(yellow(message)); - return 1; - } - } else { - let $1 = state.skipped; - if ($1 === 0) { - let message = ((("\n" + $int.to_string(state.passed)) + " passed, ") + $int.to_string( - state.failed, - )) + " failures"; - $io.println(red(message)); - return 1; - } else { - let message = ((((("\n" + $int.to_string(state.passed)) + " passed, ") + $int.to_string( - state.failed, - )) + " failures, ") + $int.to_string(state.skipped)) + " skipped"; - $io.println(red(message)); - return 1; - } - } -} - -export function test_passed(state) { - $io.print(green(".")); - return new State(state.passed + 1, state.failed, state.skipped); -} - -function grey(text) { - return ("\u{001b}[90m" + text) + "\u{001b}[39m"; -} - -function format_unknown(module, function$, error) { - return $string.concat( - toList([ - grey((module + ".") + function$) + "\n", - "An unexpected error occurred:\n", - "\n", - (" " + $string.inspect(error)) + "\n", - ]), - ); -} - -function cyan(text) { - return ("\u{001b}[36m" + text) + "\u{001b}[39m"; -} - -function code_snippet(src, start, end) { - let _pipe = $result.try$( - $option.to_result(src, undefined), - (src) => { - return $result.try$( - $bit_array.slice(src, start, end - start), - (snippet) => { - return $result.try$( - $bit_array.to_string(snippet), - (snippet) => { - let snippet$1 = ((cyan(" code") + ": ") + snippet) + "\n"; - return new Ok(snippet$1); - }, - ); - }, - ); - }, - ); - return $result.unwrap(_pipe, ""); -} - -function bold(text) { - return ("\u{001b}[1m" + text) + "\u{001b}[22m"; -} - -function inspect_value(value) { - let $ = value.kind; - if ($ instanceof $gleam_panic.Literal) { - let value$1 = $.value; - return $string.inspect(value$1); - } else if ($ instanceof $gleam_panic.Expression) { - let value$1 = $.value; - return $string.inspect(value$1); - } else { - return grey("unevaluated"); - } -} - -function assert_value(name, value) { - return ((cyan(name) + ": ") + inspect_value(value)) + "\n"; -} - -function assert_info(kind) { - if (kind instanceof $gleam_panic.BinaryOperator) { - let left = kind.left; - let right = kind.right; - return $string.concat( - toList([assert_value(" left", left), assert_value("right", right)]), - ); - } else if (kind instanceof $gleam_panic.FunctionCall) { - let arguments$ = kind.arguments; - let _pipe = arguments$; - let _pipe$1 = $list.index_map( - _pipe, - (e, i) => { - let number = $string.pad_start($int.to_string(i), 5, " "); - return assert_value(number, e); - }, - ); - return $string.concat(_pipe$1); - } else { - return ""; - } -} - -function format_gleam_error(error, module, function$, src) { - let location = grey((error.file + ":") + $int.to_string(error.line)); - let $ = error.kind; - if ($ instanceof $gleam_panic.Todo) { - return $string.concat( - toList([ - ((bold(yellow("todo")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } else if ($ instanceof $gleam_panic.Panic) { - return $string.concat( - toList([ - ((bold(red("panic")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } else if ($ instanceof $gleam_panic.LetAssert) { - let start = $.start; - let end = $.end; - let value = $.value; - return $string.concat( - toList([ - ((bold(red("let assert")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - code_snippet(src, start, end), - ((cyan("value") + ": ") + $string.inspect(value)) + "\n", - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } else { - let start = $.start; - let end = $.end; - let kind = $.kind; - return $string.concat( - toList([ - ((bold(red("assert")) + " ") + location) + "\n", - ((((cyan(" test") + ": ") + module) + ".") + function$) + "\n", - code_snippet(src, start, end), - assert_info(kind), - ((cyan(" info") + ": ") + error.message) + "\n", - ]), - ); - } -} - -function read_file(path) { - let $ = read_file_text(path); - if ($ instanceof Ok) { - let text = $[0]; - return new Ok($bit_array.from_string(text)); - } else { - return $; - } -} - -export function test_failed(state, module, function$, error) { - let _block; - let $ = $gleam_panic.from_dynamic(error); - if ($ instanceof Ok) { - let error$1 = $[0]; - let src = $option.from_result(read_file(error$1.file)); - _block = format_gleam_error(error$1, module, function$, src); - } else { - _block = format_unknown(module, function$, error); - } - let message = _block; - $io.print("\n" + message); - return new State(state.passed, state.failed + 1, state.skipped); -} - -export function eunit_missing() { - let message = bold(red("Error")) + ": EUnit libraries not found.\n\nYour Erlang installation seems to be incomplete. If you installed Erlang using\na package manager ensure that you have installed the full Erlang\ndistribution instead of a stripped-down version.\n"; - $io.print_error(message); - return new Error(undefined); -} - -export function test_skipped(state, module, function$) { - $io.print(((("\n" + module) + ".") + function$) + yellow(" skipped")); - return new State(state.passed, state.failed, state.skipped + 1); -} diff --git a/ui/javascript/gleeunit/gleeunit/should.mjs b/ui/javascript/gleeunit/gleeunit/should.mjs deleted file mode 100644 index c34c700..0000000 --- a/ui/javascript/gleeunit/gleeunit/should.mjs +++ /dev/null @@ -1,135 +0,0 @@ -import * as $option from "../../gleam_stdlib/gleam/option.mjs"; -import { None, Some } from "../../gleam_stdlib/gleam/option.mjs"; -import * as $string from "../../gleam_stdlib/gleam/string.mjs"; -import { Ok, Error, toList, makeError, isEqual } from "../gleam.mjs"; - -const FILEPATH = "src/gleeunit/should.gleam"; - -export function equal(a, b) { - let $ = isEqual(a, b); - if ($) { - return undefined; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 10, - "equal", - $string.concat( - toList([ - "\n", - $string.inspect(a), - "\nshould equal\n", - $string.inspect(b), - ]), - ), - {} - ) - } -} - -export function not_equal(a, b) { - let $ = !isEqual(a, b); - if ($) { - return undefined; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 23, - "not_equal", - $string.concat( - toList([ - "\n", - $string.inspect(a), - "\nshould not equal\n", - $string.inspect(b), - ]), - ), - {} - ) - } -} - -export function be_ok(a) { - if (a instanceof Ok) { - let value = a[0]; - return value; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 35, - "be_ok", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be ok"])), - {} - ) - } -} - -export function be_error(a) { - if (a instanceof Error) { - let error = a[0]; - return error; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 42, - "be_error", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be error"])), - {} - ) - } -} - -export function be_some(a) { - if (a instanceof Some) { - let value = a[0]; - return value; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 49, - "be_some", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be some"])), - {} - ) - } -} - -export function be_none(a) { - if (a instanceof None) { - return undefined; - } else { - throw makeError( - "panic", - FILEPATH, - "gleeunit/should", - 56, - "be_none", - $string.concat(toList(["\n", $string.inspect(a), "\nshould be none"])), - {} - ) - } -} - -export function be_true(actual) { - let _pipe = actual; - return equal(_pipe, true); -} - -export function be_false(actual) { - let _pipe = actual; - return equal(_pipe, false); -} - -export function fail() { - return be_true(false); -} diff --git a/ui/javascript/gleeunit/gleeunit@internal@gleam_panic.erl b/ui/javascript/gleeunit/gleeunit@internal@gleam_panic.erl deleted file mode 100644 index 398ea7d..0000000 --- a/ui/javascript/gleeunit/gleeunit@internal@gleam_panic.erl +++ /dev/null @@ -1,56 +0,0 @@ --module(gleeunit@internal@gleam_panic). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/internal/gleam_panic.gleam"). --export([from_dynamic/1]). --export_type([gleam_panic/0, panic_kind/0, assert_kind/0, asserted_expression/0, expression_kind/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(false). - --type gleam_panic() :: {gleam_panic, - binary(), - binary(), - binary(), - binary(), - integer(), - panic_kind()}. - --type panic_kind() :: todo | - panic | - {let_assert, - integer(), - integer(), - integer(), - integer(), - gleam@dynamic:dynamic_()} | - {assert, integer(), integer(), integer(), assert_kind()}. - --type assert_kind() :: {binary_operator, - binary(), - asserted_expression(), - asserted_expression()} | - {function_call, list(asserted_expression())} | - {other_expression, asserted_expression()}. - --type asserted_expression() :: {asserted_expression, - integer(), - integer(), - expression_kind()}. - --type expression_kind() :: {literal, gleam@dynamic:dynamic_()} | - {expression, gleam@dynamic:dynamic_()} | - unevaluated. - --file("src/gleeunit/internal/gleam_panic.gleam", 49). -?DOC(false). --spec from_dynamic(gleam@dynamic:dynamic_()) -> {ok, gleam_panic()} | - {error, nil}. -from_dynamic(Data) -> - gleeunit_gleam_panic_ffi:from_dynamic(Data). diff --git a/ui/javascript/gleeunit/gleeunit@internal@reporting.erl b/ui/javascript/gleeunit/gleeunit@internal@reporting.erl deleted file mode 100644 index 0b290a7..0000000 --- a/ui/javascript/gleeunit/gleeunit@internal@reporting.erl +++ /dev/null @@ -1,343 +0,0 @@ --module(gleeunit@internal@reporting). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/internal/reporting.gleam"). --export([new_state/0, finished/1, test_passed/1, test_failed/4, eunit_missing/0, test_skipped/3]). --export_type([state/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(false). - --type state() :: {state, integer(), integer(), integer()}. - --file("src/gleeunit/internal/reporting.gleam", 15). -?DOC(false). --spec new_state() -> state(). -new_state() -> - {state, 0, 0, 0}. - --file("src/gleeunit/internal/reporting.gleam", 223). -?DOC(false). --spec red(binary()) -> binary(). -red(Text) -> - <<<<"\x{001b}[31m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 215). -?DOC(false). --spec yellow(binary()) -> binary(). -yellow(Text) -> - <<<<"\x{001b}[33m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 219). -?DOC(false). --spec green(binary()) -> binary(). -green(Text) -> - <<<<"\x{001b}[32m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 19). -?DOC(false). --spec finished(state()) -> integer(). -finished(State) -> - case State of - {state, 0, 0, 0} -> - gleam_stdlib:println(<<"\nNo tests found!"/utf8>>), - 1; - - {state, _, 0, 0} -> - Message = <<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, no failures"/utf8>>, - gleam_stdlib:println(green(Message)), - 0; - - {state, _, _, 0} -> - Message@1 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures"/utf8>>, - gleam_stdlib:println(red(Message@1)), - 1; - - {state, _, 0, _} -> - Message@2 = <<<<<<<<"\n"/utf8, - (erlang:integer_to_binary(erlang:element(2, State)))/binary>>/binary, - " passed, 0 failures, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(4, State)))/binary>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(yellow(Message@2)), - 1; - - {state, _, _, _} -> - Message@3 = <<<<<<<<<<<<"\n"/utf8, - (erlang:integer_to_binary( - erlang:element(2, State) - ))/binary>>/binary, - " passed, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(3, State)))/binary>>/binary, - " failures, "/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(4, State)))/binary>>/binary, - " skipped"/utf8>>, - gleam_stdlib:println(red(Message@3)), - 1 - end. - --file("src/gleeunit/internal/reporting.gleam", 66). -?DOC(false). --spec test_passed(state()) -> state(). -test_passed(State) -> - gleam_stdlib:print(green(<<"."/utf8>>)), - {state, - erlang:element(2, State) + 1, - erlang:element(3, State), - erlang:element(4, State)}. - --file("src/gleeunit/internal/reporting.gleam", 227). -?DOC(false). --spec grey(binary()) -> binary(). -grey(Text) -> - <<<<"\x{001b}[90m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 100). -?DOC(false). --spec format_unknown(binary(), binary(), gleam@dynamic:dynamic_()) -> binary(). -format_unknown(Module, Function, Error) -> - erlang:list_to_binary( - [<<(grey(<<<>/binary, Function/binary>>))/binary, - "\n"/utf8>>, - <<"An unexpected error occurred:\n"/utf8>>, - <<"\n"/utf8>>, - <<<<" "/utf8, (gleam@string:inspect(Error))/binary>>/binary, - "\n"/utf8>>] - ). - --file("src/gleeunit/internal/reporting.gleam", 211). -?DOC(false). --spec cyan(binary()) -> binary(). -cyan(Text) -> - <<<<"\x{001b}[36m"/utf8, Text/binary>>/binary, "\x{001b}[39m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 191). -?DOC(false). --spec code_snippet(gleam@option:option(bitstring()), integer(), integer()) -> binary(). -code_snippet(Src, Start, End) -> - _pipe = begin - gleam@result:'try'( - gleam@option:to_result(Src, nil), - fun(Src@1) -> - gleam@result:'try'( - gleam_stdlib:bit_array_slice(Src@1, Start, End - Start), - fun(Snippet) -> - gleam@result:'try'( - gleam@bit_array:to_string(Snippet), - fun(Snippet@1) -> - Snippet@2 = <<<<<<(cyan(<<" code"/utf8>>))/binary, - ": "/utf8>>/binary, - Snippet@1/binary>>/binary, - "\n"/utf8>>, - {ok, Snippet@2} - end - ) - end - ) - end - ) - end, - gleam@result:unwrap(_pipe, <<""/utf8>>). - --file("src/gleeunit/internal/reporting.gleam", 207). -?DOC(false). --spec bold(binary()) -> binary(). -bold(Text) -> - <<<<"\x{001b}[1m"/utf8, Text/binary>>/binary, "\x{001b}[22m"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 183). -?DOC(false). --spec inspect_value(gleeunit@internal@gleam_panic:asserted_expression()) -> binary(). -inspect_value(Value) -> - case erlang:element(4, Value) of - unevaluated -> - grey(<<"unevaluated"/utf8>>); - - {literal, Value@1} -> - gleam@string:inspect(Value@1); - - {expression, Value@2} -> - gleam@string:inspect(Value@2) - end. - --file("src/gleeunit/internal/reporting.gleam", 179). -?DOC(false). --spec assert_value( - binary(), - gleeunit@internal@gleam_panic:asserted_expression() -) -> binary(). -assert_value(Name, Value) -> - <<<<<<(cyan(Name))/binary, ": "/utf8>>/binary, - (inspect_value(Value))/binary>>/binary, - "\n"/utf8>>. - --file("src/gleeunit/internal/reporting.gleam", 160). -?DOC(false). --spec assert_info(gleeunit@internal@gleam_panic:assert_kind()) -> binary(). -assert_info(Kind) -> - case Kind of - {binary_operator, _, Left, Right} -> - erlang:list_to_binary( - [assert_value(<<" left"/utf8>>, Left), - assert_value(<<"right"/utf8>>, Right)] - ); - - {function_call, Arguments} -> - _pipe = Arguments, - _pipe@1 = gleam@list:index_map( - _pipe, - fun(E, I) -> - Number = gleam@string:pad_start( - erlang:integer_to_binary(I), - 5, - <<" "/utf8>> - ), - assert_value(Number, E) - end - ), - erlang:list_to_binary(_pipe@1); - - {other_expression, _} -> - <<""/utf8>> - end. - --file("src/gleeunit/internal/reporting.gleam", 113). -?DOC(false). --spec format_gleam_error( - gleeunit@internal@gleam_panic:gleam_panic(), - binary(), - binary(), - gleam@option:option(bitstring()) -) -> binary(). -format_gleam_error(Error, Module, Function, Src) -> - Location = grey( - <<<<(erlang:element(3, Error))/binary, ":"/utf8>>/binary, - (erlang:integer_to_binary(erlang:element(6, Error)))/binary>> - ), - case erlang:element(7, Error) of - panic -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"panic"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - todo -> - erlang:list_to_binary( - [<<<<<<(bold(yellow(<<"todo"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - {assert, Start, End, _, Kind} -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"assert"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - code_snippet(Src, Start, End), - assert_info(Kind), - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ); - - {let_assert, Start@1, End@1, _, _, Value} -> - erlang:list_to_binary( - [<<<<<<(bold(red(<<"let assert"/utf8>>)))/binary, " "/utf8>>/binary, - Location/binary>>/binary, - "\n"/utf8>>, - <<<<<<<<<<(cyan(<<" test"/utf8>>))/binary, ": "/utf8>>/binary, - Module/binary>>/binary, - "."/utf8>>/binary, - Function/binary>>/binary, - "\n"/utf8>>, - code_snippet(Src, Start@1, End@1), - <<<<<<(cyan(<<"value"/utf8>>))/binary, ": "/utf8>>/binary, - (gleam@string:inspect(Value))/binary>>/binary, - "\n"/utf8>>, - <<<<<<(cyan(<<" info"/utf8>>))/binary, ": "/utf8>>/binary, - (erlang:element(2, Error))/binary>>/binary, - "\n"/utf8>>] - ) - end. - --file("src/gleeunit/internal/reporting.gleam", 71). -?DOC(false). --spec test_failed(state(), binary(), binary(), gleam@dynamic:dynamic_()) -> state(). -test_failed(State, Module, Function, Error) -> - Message = case gleeunit_gleam_panic_ffi:from_dynamic(Error) of - {ok, Error@1} -> - Src = gleam@option:from_result( - file:read_file(erlang:element(3, Error@1)) - ), - format_gleam_error(Error@1, Module, Function, Src); - - {error, _} -> - format_unknown(Module, Function, Error) - end, - gleam_stdlib:print(<<"\n"/utf8, Message/binary>>), - {state, - erlang:element(2, State), - erlang:element(3, State) + 1, - erlang:element(4, State)}. - --file("src/gleeunit/internal/reporting.gleam", 89). -?DOC(false). --spec eunit_missing() -> {ok, any()} | {error, nil}. -eunit_missing() -> - Message = <<(bold(red(<<"Error"/utf8>>)))/binary, - ": EUnit libraries not found. - -Your Erlang installation seems to be incomplete. If you installed Erlang using -a package manager ensure that you have installed the full Erlang -distribution instead of a stripped-down version. -"/utf8>>, - gleam_stdlib:print_error(Message), - {error, nil}. - --file("src/gleeunit/internal/reporting.gleam", 202). -?DOC(false). --spec test_skipped(state(), binary(), binary()) -> state(). -test_skipped(State, Module, Function) -> - gleam_stdlib:print( - <<<<<<<<"\n"/utf8, Module/binary>>/binary, "."/utf8>>/binary, - Function/binary>>/binary, - (yellow(<<" skipped"/utf8>>))/binary>> - ), - {state, - erlang:element(2, State), - erlang:element(3, State), - erlang:element(4, State) + 1}. diff --git a/ui/javascript/gleeunit/gleeunit@should.erl b/ui/javascript/gleeunit/gleeunit@should.erl deleted file mode 100644 index fca394b..0000000 --- a/ui/javascript/gleeunit/gleeunit@should.erl +++ /dev/null @@ -1,153 +0,0 @@ --module(gleeunit@should). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/gleeunit/should.gleam"). --export([equal/2, not_equal/2, be_ok/1, be_error/1, be_some/1, be_none/1, be_true/1, be_false/1, fail/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - -?MODULEDOC(" Use the `assert` keyword instead of this module.\n"). - --file("src/gleeunit/should.gleam", 6). --spec equal(DOK, DOK) -> nil. -equal(A, B) -> - case A =:= B of - true -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould equal\n"/utf8>>, - gleam@string:inspect(B)] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"equal"/utf8>>, - line => 10}) - end. - --file("src/gleeunit/should.gleam", 19). --spec not_equal(DOL, DOL) -> nil. -not_equal(A, B) -> - case A /= B of - true -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould not equal\n"/utf8>>, - gleam@string:inspect(B)] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"not_equal"/utf8>>, - line => 23}) - end. - --file("src/gleeunit/should.gleam", 32). --spec be_ok({ok, DOM} | {error, any()}) -> DOM. -be_ok(A) -> - case A of - {ok, Value} -> - Value; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be ok"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_ok"/utf8>>, - line => 35}) - end. - --file("src/gleeunit/should.gleam", 39). --spec be_error({ok, any()} | {error, DOR}) -> DOR. -be_error(A) -> - case A of - {error, Error} -> - Error; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be error"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_error"/utf8>>, - line => 42}) - end. - --file("src/gleeunit/should.gleam", 46). --spec be_some(gleam@option:option(DOU)) -> DOU. -be_some(A) -> - case A of - {some, Value} -> - Value; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be some"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_some"/utf8>>, - line => 49}) - end. - --file("src/gleeunit/should.gleam", 53). --spec be_none(gleam@option:option(any())) -> nil. -be_none(A) -> - case A of - none -> - nil; - - _ -> - erlang:error(#{gleam_error => panic, - message => erlang:list_to_binary( - [<<"\n"/utf8>>, - gleam@string:inspect(A), - <<"\nshould be none"/utf8>>] - ), - file => <>, - module => <<"gleeunit/should"/utf8>>, - function => <<"be_none"/utf8>>, - line => 56}) - end. - --file("src/gleeunit/should.gleam", 60). --spec be_true(boolean()) -> nil. -be_true(Actual) -> - _pipe = Actual, - equal(_pipe, true). - --file("src/gleeunit/should.gleam", 65). --spec be_false(boolean()) -> nil. -be_false(Actual) -> - _pipe = Actual, - equal(_pipe, false). - --file("src/gleeunit/should.gleam", 70). --spec fail() -> nil. -fail() -> - be_true(false). diff --git a/ui/javascript/gleeunit/gleeunit_ffi.erl b/ui/javascript/gleeunit/gleeunit_ffi.erl deleted file mode 100644 index 05c7490..0000000 --- a/ui/javascript/gleeunit/gleeunit_ffi.erl +++ /dev/null @@ -1,21 +0,0 @@ --module(gleeunit_ffi). - --export([find_files/2, run_eunit/2]). - -find_files(Pattern, In) -> - Results = filelib:wildcard(binary_to_list(Pattern), binary_to_list(In)), - lists:map(fun list_to_binary/1, Results). - -run_eunit(Tests, Options) -> - case code:which(eunit) of - non_existing -> - gleeunit@internal@reporting:eunit_missing(); - - _ -> - case eunit:test(Tests, Options) of - ok -> {ok, nil}; - error -> {error, nil}; - {error, Term} -> {error, Term} - end - end. - diff --git a/ui/javascript/gleeunit/gleeunit_ffi.mjs b/ui/javascript/gleeunit/gleeunit_ffi.mjs deleted file mode 100644 index 7bdc071..0000000 --- a/ui/javascript/gleeunit/gleeunit_ffi.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import { readFileSync } from "node:fs"; -import { Result$Ok, Result$Error } from "./gleam.mjs"; -import * as reporting from "./gleeunit/internal/reporting.mjs"; - -export function read_file(path) { - try { - return Result$Ok(readFileSync(path)); - } catch { - return Result$Error(undefined); - } -} - -async function* gleamFiles(directory) { - for (let entry of await read_dir(directory)) { - let path = join_path(directory, entry); - if (path.endsWith(".gleam")) { - yield path; - } else { - try { - yield* gleamFiles(path); - } catch (error) { - // Could not read directory, assume it's a file - } - } - } -} - -async function readRootPackageName() { - let toml = await async_read_file("gleam.toml", "utf-8"); - for (let line of toml.split("\n")) { - let matches = line.match(/\s*name\s*=\s*"([a-z][a-z0-9_]*)"/); // Match regexp in compiler-cli/src/new.rs in validate_name() - if (matches) return matches[1]; - } - throw new Error("Could not determine package name from gleam.toml"); -} - -export async function main() { - let state = reporting.new_state(); - - let packageName = await readRootPackageName(); - let dist = `../${packageName}/`; - - for await (let path of await gleamFiles("test")) { - let js_path = path.slice("test/".length).replace(".gleam", ".mjs"); - let module = await import(join_path(dist, js_path)); - for (let fnName of Object.keys(module)) { - if (!fnName.endsWith("_test")) continue; - try { - await module[fnName](); - state = reporting.test_passed(state); - } catch (error) { - let moduleName = js_path.slice(0, -4); - state = reporting.test_failed(state, moduleName, fnName, error); - } - } - } - - const status = reporting.finished(state); - exit(status); -} - -export function crash(message) { - throw new Error(message); -} - -function exit(code) { - if (globalThis.Deno) { - Deno.exit(code); - } else { - process.exit(code); - } -} - -async function read_dir(path) { - if (globalThis.Deno) { - let items = []; - for await (let item of Deno.readDir(path, { withFileTypes: true })) { - items.push(item.name); - } - return items; - } else { - let { readdir } = await import("node:fs/promises"); - return readdir(path); - } -} - -function join_path(a, b) { - if (a.endsWith("/")) return a + b; - return a + "/" + b; -} - -async function async_read_file(path) { - if (globalThis.Deno) { - return Deno.readTextFile(path); - } else { - let { readFile } = await import("node:fs/promises"); - let contents = await readFile(path); - return contents.toString(); - } -} diff --git a/ui/javascript/gleeunit/gleeunit_progress.erl b/ui/javascript/gleeunit/gleeunit_progress.erl deleted file mode 100644 index e6576a5..0000000 --- a/ui/javascript/gleeunit/gleeunit_progress.erl +++ /dev/null @@ -1,72 +0,0 @@ -%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters - --module(gleeunit_progress). --define(NOTEST, true). - -%% eunit_listener callbacks --export([ - init/1, handle_begin/3, handle_end/3, handle_cancel/3, terminate/2, - start/0, start/1 -]). - --define(reporting, gleeunit@internal@reporting). - -start() -> - start([]). - -start(Options) -> - eunit_listener:start(?MODULE, Options). - -init(_Options) -> - ?reporting:new_state(). - -handle_begin(_test_or_group, _data, State) -> - State. - -handle_end(group, _data, State) -> - State; -handle_end(test, Data, State) -> - {AtomModule, AtomFunction, _Arity} = proplists:get_value(source, Data), - Module = erlang:atom_to_binary(AtomModule), - Function = erlang:atom_to_binary(AtomFunction), - - % EUnit swallows stdout, so print it to make debugging easier. - case proplists:get_value(output, Data) of - undefined -> ok; - <<>> -> ok; - Out -> gleam@io:print(Out) - end, - - case proplists:get_value(status, Data) of - ok -> - ?reporting:test_passed(State); - {skipped, _Reason} -> - ?reporting:test_skipped(State, Module, Function); - {error, {_, Exception, _Stack}} -> - ?reporting:test_failed(State, Module, Function, Exception) - end. - - -handle_cancel(_test_or_group, Data, State) -> - ?reporting:test_failed(State, <<"gleeunit">>, <<"main">>, Data). - -terminate({ok, _Data}, State) -> - ?reporting:finished(State), - ok; -terminate({error, Reason}, State) -> - ?reporting:finished(State), - io:fwrite(" -Eunit failed: - -~80p - -This is probably a bug in gleeunit. Please report it. -", [Reason]), - sync_end(error). - -sync_end(Result) -> - receive - {stop, Reference, ReplyTo} -> - ReplyTo ! {result, Reference, Result}, - ok - end. diff --git a/ui/javascript/markdown2/_gleam_artefacts/definition.cache b/ui/javascript/markdown2/_gleam_artefacts/definition.cache deleted file mode 100644 index 25a82c1..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/definition.cache and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/definition.cache_meta b/ui/javascript/markdown2/_gleam_artefacts/definition.cache_meta deleted file mode 100644 index 8631eed..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/definition.cache_meta and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/markdown2.cache b/ui/javascript/markdown2/_gleam_artefacts/markdown2.cache deleted file mode 100644 index 9d72fd2..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/markdown2.cache and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/markdown2.cache_meta b/ui/javascript/markdown2/_gleam_artefacts/markdown2.cache_meta deleted file mode 100644 index ec7708f..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/markdown2.cache_meta and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/markdown2_test.cache b/ui/javascript/markdown2/_gleam_artefacts/markdown2_test.cache deleted file mode 100644 index b46ee53..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/markdown2_test.cache and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/markdown2_test.cache_meta b/ui/javascript/markdown2/_gleam_artefacts/markdown2_test.cache_meta deleted file mode 100644 index a47e28d..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/markdown2_test.cache_meta and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/mode.cache b/ui/javascript/markdown2/_gleam_artefacts/mode.cache deleted file mode 100644 index 2919d32..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/mode.cache and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/mode.cache_meta b/ui/javascript/markdown2/_gleam_artefacts/mode.cache_meta deleted file mode 100644 index c414e03..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/mode.cache_meta and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/parser.cache b/ui/javascript/markdown2/_gleam_artefacts/parser.cache deleted file mode 100644 index e9b4c1a..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/parser.cache and /dev/null differ diff --git a/ui/javascript/markdown2/_gleam_artefacts/parser.cache_meta b/ui/javascript/markdown2/_gleam_artefacts/parser.cache_meta deleted file mode 100644 index 9703df7..0000000 Binary files a/ui/javascript/markdown2/_gleam_artefacts/parser.cache_meta and /dev/null differ diff --git a/ui/javascript/markdown2/definition.mjs b/ui/javascript/markdown2/definition.mjs deleted file mode 100644 index 611061f..0000000 --- a/ui/javascript/markdown2/definition.mjs +++ /dev/null @@ -1,103 +0,0 @@ -import { CustomType as $CustomType } from "./gleam.mjs"; -import * as $mode from "./mode.mjs"; - -export class Line extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Line$Line = ($0) => new Line($0); -export const Line$isLine = (value) => value instanceof Line; -export const Line$Line$0 = (value) => value[0]; - -export class Text extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Inline$Text = ($0) => new Text($0); -export const Inline$isText = (value) => value instanceof Text; -export const Inline$Text$0 = (value) => value[0]; - -export class Push extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Inline$Push = ($0) => new Push($0); -export const Inline$isPush = (value) => value instanceof Push; -export const Inline$Push$0 = (value) => value[0]; - -export class Pop extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Inline$Pop = ($0) => new Pop($0); -export const Inline$isPop = (value) => value instanceof Pop; -export const Inline$Pop$0 = (value) => value[0]; - -export class Hirachy extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Feeling$Hirachy = ($0) => new Hirachy($0); -export const Feeling$isHirachy = (value) => value instanceof Hirachy; -export const Feeling$Hirachy$0 = (value) => value[0]; - -export class Truth extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Feeling$Truth = ($0) => new Truth($0); -export const Feeling$isTruth = (value) => value instanceof Truth; -export const Feeling$Truth$0 = (value) => value[0]; - -export class Marking extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Feeling$Marking = ($0) => new Marking($0); -export const Feeling$isMarking = (value) => value instanceof Marking; -export const Feeling$Marking$0 = (value) => value[0]; - -export class Quote extends $CustomType { - constructor($0) { - super(); - this[0] = $0; - } -} -export const Feeling$Quote = ($0) => new Quote($0); -export const Feeling$isQuote = (value) => value instanceof Quote; -export const Feeling$Quote$0 = (value) => value[0]; - -export class State extends $CustomType { - constructor(hirachystate, truthstate, markingstate, quotestate) { - super(); - this.hirachystate = hirachystate; - this.truthstate = truthstate; - this.markingstate = markingstate; - this.quotestate = quotestate; - } -} -export const State$State = (hirachystate, truthstate, markingstate, quotestate) => - new State(hirachystate, truthstate, markingstate, quotestate); -export const State$isState = (value) => value instanceof State; -export const State$State$hirachystate = (value) => value.hirachystate; -export const State$State$0 = (value) => value.hirachystate; -export const State$State$truthstate = (value) => value.truthstate; -export const State$State$1 = (value) => value.truthstate; -export const State$State$markingstate = (value) => value.markingstate; -export const State$State$2 = (value) => value.markingstate; -export const State$State$quotestate = (value) => value.quotestate; -export const State$State$3 = (value) => value.quotestate; diff --git a/ui/javascript/markdown2/gleam.mjs b/ui/javascript/markdown2/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/ui/javascript/markdown2/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/ui/javascript/markdown2/markdown2.mjs b/ui/javascript/markdown2/markdown2.mjs deleted file mode 100644 index 1ff5827..0000000 --- a/ui/javascript/markdown2/markdown2.mjs +++ /dev/null @@ -1,77 +0,0 @@ -import * as $json from "../gleam_json/gleam/json.mjs"; -import * as $int from "../gleam_stdlib/gleam/int.mjs"; -import * as $io from "../gleam_stdlib/gleam/io.mjs"; -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $definition from "./definition.mjs"; -import { toList } from "./gleam.mjs"; -import * as $mode from "./mode.mjs"; -import * as $parser from "./parser.mjs"; - -function inline_to_json(inline) { - if (inline instanceof $definition.Text) { - let text = inline[0]; - return $json.object( - toList([["type", $json.string("text")], ["value", $json.string(text)]]), - ); - } else if (inline instanceof $definition.Push) { - let feeling = inline[0]; - if (feeling instanceof $definition.Hirachy) { - let level = feeling[0]; - return $json.object( - toList([["type", $json.string("hirachy")], ["value", $json.int(level)]]), - ); - } else if (feeling instanceof $definition.Truth) { - let level = feeling[0]; - return $json.object( - toList([["type", $json.string("truth")], ["value", $json.int(level)]]), - ); - } else if (feeling instanceof $definition.Marking) { - let level = feeling[0]; - return $json.object( - toList([["type", $json.string("marking")], ["value", $json.int(level)]]), - ); - } else { - let level = feeling[0]; - return $json.object( - toList([["type", $json.string("quote")], ["value", $json.int(level)]]), - ); - } - } else { - let text = inline[0]; - return $json.object( - toList([ - ["type", $json.string("pop")], - [ - "value", - (() => { - if (text instanceof $mode.Hirachy) { - return $json.string("Hirachy"); - } else if (text instanceof $mode.Truth) { - return $json.string("Truth"); - } else if (text instanceof $mode.Marking) { - return $json.string("Marking"); - } else { - return $json.string("Quote"); - } - })(), - ], - ]), - ); - } -} - -function line_to_json(line) { - let inlines = line[0]; - let _pipe = $json.array(inlines, inline_to_json); - return $json.to_string(_pipe); -} - -export function main() { - let input = "ljiosfgdjiosdfgj\n @2! A slightly important statement !1 I believe is wrong, !- quoted inside another quote.\n !3 A slightly important statement I believe is wrong, quoted inside another quote.\n #3!2@2 A slightly important statement I believe is wrong, quoted inside another quote.\n\n !2@3 important trusted but @- important !5 more important !- 2 important and !- normal"; - $io.print(line_to_json($parser.handler(input))); - return undefined; -} - -export function testing(input) { - return line_to_json($parser.handler(input)); -} diff --git a/ui/javascript/markdown2/markdown2_test.mjs b/ui/javascript/markdown2/markdown2_test.mjs deleted file mode 100644 index 83e2af9..0000000 --- a/ui/javascript/markdown2/markdown2_test.mjs +++ /dev/null @@ -1,34 +0,0 @@ -import * as $gleeunit from "../gleeunit/gleeunit.mjs"; -import { makeError } from "./gleam.mjs"; - -const FILEPATH = "test/markdown2_test.gleam"; - -export function main() { - return $gleeunit.main(); -} - -export function hello_world_test() { - let name = "Joe"; - let greeting = ("Hello, " + name) + "!"; - let $ = "Hello, Joe!"; - if (!(greeting === $)) { - throw makeError( - "assert", - FILEPATH, - "markdown2_test", - 12, - "hello_world_test", - "Assertion failed.", - { - kind: "binary_operator", - operator: "==", - left: { kind: "expression", value: greeting, start: 202, end: 210 }, - right: { kind: "literal", value: $, start: 214, end: 227 }, - start: 195, - end: 227, - expression_start: 202 - } - ) - } - return undefined; -} diff --git a/ui/javascript/markdown2/mode.mjs b/ui/javascript/markdown2/mode.mjs deleted file mode 100644 index c74b587..0000000 --- a/ui/javascript/markdown2/mode.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import { CustomType as $CustomType } from "./gleam.mjs"; - -export class Hirachy extends $CustomType {} -export const Type$Hirachy = () => new Hirachy(); -export const Type$isHirachy = (value) => value instanceof Hirachy; - -export class Truth extends $CustomType {} -export const Type$Truth = () => new Truth(); -export const Type$isTruth = (value) => value instanceof Truth; - -export class Marking extends $CustomType {} -export const Type$Marking = () => new Marking(); -export const Type$isMarking = (value) => value instanceof Marking; - -export class Quote extends $CustomType {} -export const Type$Quote = () => new Quote(); -export const Type$isQuote = (value) => value instanceof Quote; diff --git a/ui/javascript/markdown2/parser.mjs b/ui/javascript/markdown2/parser.mjs deleted file mode 100644 index 420ae5b..0000000 --- a/ui/javascript/markdown2/parser.mjs +++ /dev/null @@ -1,367 +0,0 @@ -import * as $dict from "../gleam_stdlib/gleam/dict.mjs"; -import * as $stdlib$dict from "../gleam_stdlib/gleam/dict.mjs"; -import * as $int from "../gleam_stdlib/gleam/int.mjs"; -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $result from "../gleam_stdlib/gleam/result.mjs"; -import * as $string from "../gleam_stdlib/gleam/string.mjs"; -import * as $definition from "./definition.mjs"; -import { - Ok, - toList, - Empty as $Empty, - NonEmpty as $NonEmpty, - CustomType as $CustomType, - bitArraySlice, - bitArraySliceToInt, - BitArray as $BitArray, - List as $List, - UtfCodepoint as $UtfCodepoint, -} from "./gleam.mjs"; -import * as $mode from "./mode.mjs"; - -function whatsthat(mod) { - let modes = $dict.from_list( - toList([ - [ - "!", - [ - new $mode.Marking(), - (var0) => { return new $definition.Marking(var0); }, - ], - ], - [ - "@", - [new $mode.Truth(), (var0) => { return new $definition.Truth(var0); }], - ], - [ - ">", - [new $mode.Quote(), (var0) => { return new $definition.Quote(var0); }], - ], - [ - "#", - [ - new $mode.Hirachy(), - (var0) => { return new $definition.Hirachy(var0); }, - ], - ], - ]), - ); - let $ = $string.pop_grapheme(mod); - if ($ instanceof Ok) { - let prefix = $[0][0]; - let rest = $[0][1]; - let $1 = $dict.get(modes, prefix); - if ($1 instanceof Ok) { - let m = $1[0][0]; - let make_definition = $1[0][1]; - if (rest === "-") { - return new $definition.Pop(m); - } else { - let _block; - let _pipe = $int.parse(rest); - _block = $result.unwrap(_pipe, 1); - let value = _block; - return new $definition.Push(make_definition(value)); - } - } else { - return new $definition.Text(mod); - } - } else { - return new $definition.Text(mod); - } -} - -function parse(modificators) { - let _pipe = modificators; - let _pipe$1 = $string.replace(_pipe, "#", " |#"); - let _pipe$2 = $string.replace(_pipe$1, "@", " |@"); - let _pipe$3 = $string.replace(_pipe$2, "!", " |!"); - let _pipe$4 = $string.replace(_pipe$3, ">", " |>"); - let _pipe$5 = $string.split(_pipe$4, " |"); - let _pipe$6 = $list.flat_map( - _pipe$5, - (block) => { - let $ = (($string.starts_with(block, "#") || $string.starts_with( - block, - "@", - )) || $string.starts_with(block, "!")) || $string.starts_with(block, ">"); - if ($) { - let $1 = $string.split_once(block, " "); - if ($1 instanceof Ok) { - let tag = $1[0][0]; - let rest = $1[0][1]; - return toList([tag, rest]); - } else { - return toList([block]); - } - } else { - return toList([block]); - } - }, - ); - let _pipe$7 = $list.map(_pipe$6, $string.trim); - return $list.filter(_pipe$7, (x) => { return x !== ""; }); -} - -export function handler(line) { - let result = parse(line); - let result$1 = echo( - $list.map(result, whatsthat), - undefined, - "src/parser.gleam", - 10, - ); - return new $definition.Line(result$1); -} - -function echo(value, message, file, line) { - const grey = "\u001b[90m"; - const reset_color = "\u001b[39m"; - const file_line = `${file}:${line}`; - const inspector = new Echo$Inspector(); - const string_value = inspector.inspect(value); - const string_message = message === undefined ? "" : " " + message; - - if (globalThis.process?.stderr?.write) { - // If we're in Node.js, use `stderr` - const string = `${grey}${file_line}${reset_color}${string_message}\n${string_value}\n`; - globalThis.process.stderr.write(string); - } else if (globalThis.Deno) { - // If we're in Deno, use `stderr` - const string = `${grey}${file_line}${reset_color}${string_message}\n${string_value}\n`; - globalThis.Deno.stderr.writeSync(new TextEncoder().encode(string)); - } else { - // Otherwise, use `console.log` - // The browser's console.log doesn't support ansi escape codes - const string = `${file_line}${string_message}\n${string_value}`; - globalThis.console.log(string); - } - - return value; -} - -class Echo$Inspector { - #references = new globalThis.Set(); - - #isDict(value) { - try { - // We can only check if an object is a stdlib Dict if it is one of the - // project's dependencies. - // We import the public gleam/dict module, so to check if something is a - // dict we compare the `constructor` field on the object with that of a - // new dict. - const empty_dict = $stdlib$dict.new$(); - const dict_class = empty_dict.constructor; - return value instanceof dict_class; - } catch { - // If stdlib is not one of the project's dependencies then `$stdlib$dict` - // will not have been imported and the check will throw an exception meaning - // we can't check if something is actually a `Dict`. - return false; - } - } - - #float(float) { - const string = float.toString().replace("+", ""); - if (string.indexOf(".") >= 0) { - return string; - } else { - const index = string.indexOf("e"); - if (index >= 0) { - return string.slice(0, index) + ".0" + string.slice(index); - } else { - return string + ".0"; - } - } - } - - inspect(v) { - const t = typeof v; - if (v === true) return "True"; - if (v === false) return "False"; - if (v === null) return "//js(null)"; - if (v === undefined) return "Nil"; - if (t === "string") return this.#string(v); - if (t === "bigint" || globalThis.Number.isInteger(v)) return v.toString(); - if (t === "number") return this.#float(v); - if (v instanceof $UtfCodepoint) return this.#utfCodepoint(v); - if (v instanceof $BitArray) return this.#bit_array(v); - if (v instanceof globalThis.RegExp) return `//js(${v})`; - if (v instanceof globalThis.Date) return `//js(Date("${v.toISOString()}"))`; - if (v instanceof globalThis.Error) return `//js(${v.toString()})`; - if (v instanceof globalThis.Function) { - const args = []; - for (const i of globalThis.Array(v.length).keys()) - args.push(globalThis.String.fromCharCode(i + 97)); - return `//fn(${args.join(", ")}) { ... }`; - } - - if (this.#references.size === this.#references.add(v).size) { - return "//js(circular reference)"; - } - - let printed; - if (globalThis.Array.isArray(v)) { - printed = `#(${v.map((v) => this.inspect(v)).join(", ")})`; - } else if (v instanceof $List) { - printed = this.#list(v); - } else if (v instanceof $CustomType) { - printed = this.#customType(v); - } else if (this.#isDict(v)) { - printed = this.#dict(v); - } else if (v instanceof Set) { - return `//js(Set(${[...v].map((v) => this.inspect(v)).join(", ")}))`; - } else { - printed = this.#object(v); - } - this.#references.delete(v); - return printed; - } - - #object(v) { - const name = - globalThis.Object.getPrototypeOf(v)?.constructor?.name || "Object"; - const props = []; - for (const k of globalThis.Object.keys(v)) { - props.push(`${this.inspect(k)}: ${this.inspect(v[k])}`); - } - const body = props.length ? " " + props.join(", ") + " " : ""; - const head = name === "Object" ? "" : name + " "; - return `//js(${head}{${body}})`; - } - - #dict(map) { - let body = "dict.from_list(["; - let first = true; - - let key_value_pairs = $stdlib$dict.fold(map, [], (pairs, key, value) => { - pairs.push([key, value]); - return pairs; - }); - - key_value_pairs.sort(); - key_value_pairs.forEach(([key, value]) => { - if (!first) body = body + ", "; - body = body + "#(" + this.inspect(key) + ", " + this.inspect(value) + ")"; - first = false; - }); - return body + "])"; - } - - #customType(record) { - const props = globalThis.Object.keys(record) - .map((label) => { - const value = this.inspect(record[label]); - return isNaN(parseInt(label)) ? `${label}: ${value}` : value; - }) - .join(", "); - return props - ? `${record.constructor.name}(${props})` - : record.constructor.name; - } - - #list(list) { - if (list instanceof $Empty) { - return "[]"; - } - - let char_out = 'charlist.from_string("'; - let list_out = "["; - - let current = list; - while (current instanceof $NonEmpty) { - let element = current.head; - current = current.tail; - - if (list_out !== "[") { - list_out += ", "; - } - list_out += this.inspect(element); - - if (char_out) { - if ( - globalThis.Number.isInteger(element) && - element >= 32 && - element <= 126 - ) { - char_out += globalThis.String.fromCharCode(element); - } else { - char_out = null; - } - } - } - - if (char_out) { - return char_out + '")'; - } else { - return list_out + "]"; - } - } - - #string(str) { - let new_str = '"'; - for (let i = 0; i < str.length; i++) { - const char = str[i]; - switch (char) { - case "\n": - new_str += "\\n"; - break; - case "\r": - new_str += "\\r"; - break; - case "\t": - new_str += "\\t"; - break; - case "\f": - new_str += "\\f"; - break; - case "\\": - new_str += "\\\\"; - break; - case '"': - new_str += '\\"'; - break; - default: - if (char < " " || (char > "~" && char < "\u{00A0}")) { - new_str += - "\\u{" + - char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + - "}"; - } else { - new_str += char; - } - } - } - new_str += '"'; - return new_str; - } - - #utfCodepoint(codepoint) { - return `//utfcodepoint(${globalThis.String.fromCodePoint(codepoint.value)})`; - } - - #bit_array(bits) { - if (bits.bitSize === 0) { - return "<<>>"; - } - - let acc = "<<"; - - for (let i = 0; i < bits.byteSize - 1; i++) { - acc += bits.byteAt(i).toString(); - acc += ", "; - } - - if (bits.byteSize * 8 === bits.bitSize) { - acc += bits.byteAt(bits.byteSize - 1).toString(); - } else { - const trailingBitsCount = bits.bitSize % 8; - acc += bits.byteAt(bits.byteSize - 1) >> (8 - trailingBitsCount); - acc += `:size(${trailingBitsCount})`; - } - - acc += ">>"; - return acc; - } -} - diff --git a/ui/javascript/prelude.mjs b/ui/javascript/prelude.mjs deleted file mode 100644 index 0f9f8d8..0000000 --- a/ui/javascript/prelude.mjs +++ /dev/null @@ -1,1561 +0,0 @@ -export class CustomType { - withFields(fields) { - let properties = Object.keys(this).map((label) => - label in fields ? fields[label] : this[label], - ); - return new this.constructor(...properties); - } -} - -export class List { - static fromArray(array, tail) { - let t = tail || new Empty(); - for (let i = array.length - 1; i >= 0; --i) { - t = new NonEmpty(array[i], t); - } - return t; - } - - [Symbol.iterator]() { - return new ListIterator(this); - } - - toArray() { - return [...this]; - } - - atLeastLength(desired) { - let current = this; - while (desired-- > 0 && current) current = current.tail; - return current !== undefined; - } - - hasLength(desired) { - let current = this; - while (desired-- > 0 && current) current = current.tail; - return desired === -1 && current instanceof Empty; - } - - countLength() { - let current = this; - let length = 0; - while (current) { - current = current.tail; - length++; - } - return length - 1; - } -} - -export function prepend(element, tail) { - return new NonEmpty(element, tail); -} - -export function toList(elements, tail) { - return List.fromArray(elements, tail); -} - -class ListIterator { - #current; - - constructor(current) { - this.#current = current; - } - - next() { - if (this.#current instanceof Empty) { - return { done: true }; - } else { - let { head, tail } = this.#current; - this.#current = tail; - return { value: head, done: false }; - } - } -} - -export class Empty extends List {} -export const List$Empty = () => new Empty(); -export const List$isEmpty = (value) => value instanceof Empty; - -export class NonEmpty extends List { - constructor(head, tail) { - super(); - this.head = head; - this.tail = tail; - } -} -export const List$NonEmpty = (head, tail) => new NonEmpty(head, tail); -export const List$isNonEmpty = (value) => value instanceof NonEmpty; - -export const List$NonEmpty$first = (value) => value.head; -export const List$NonEmpty$rest = (value) => value.tail; - -/** - * A bit array is a contiguous sequence of bits similar to Erlang's Binary type. - */ -export class BitArray { - /** - * The size in bits of this bit array's data. - * - * @type {number} - */ - bitSize; - - /** - * The size in bytes of this bit array's data. If this bit array doesn't store - * a whole number of bytes then this value is rounded up. - * - * @type {number} - */ - byteSize; - - /** - * The number of unused high bits in the first byte of this bit array's - * buffer prior to the start of its data. The value of any unused high bits is - * undefined. - * - * The bit offset will be in the range 0-7. - * - * @type {number} - */ - bitOffset; - - /** - * The raw bytes that hold this bit array's data. - * - * If `bitOffset` is not zero then there are unused high bits in the first - * byte of this buffer. - * - * If `bitOffset + bitSize` is not a multiple of 8 then there are unused low - * bits in the last byte of this buffer. - * - * @type {Uint8Array} - */ - rawBuffer; - - /** - * Constructs a new bit array from a `Uint8Array`, an optional size in - * bits, and an optional bit offset. - * - * If no bit size is specified it is taken as `buffer.length * 8`, i.e. all - * bytes in the buffer make up the new bit array's data. - * - * If no bit offset is specified it defaults to zero, i.e. there are no unused - * high bits in the first byte of the buffer. - * - * @param {Uint8Array} buffer - * @param {number} [bitSize] - * @param {number} [bitOffset] - */ - constructor(buffer, bitSize, bitOffset) { - if (!(buffer instanceof Uint8Array)) { - throw globalThis.Error( - "BitArray can only be constructed from a Uint8Array", - ); - } - - this.bitSize = bitSize ?? buffer.length * 8; - this.byteSize = Math.trunc((this.bitSize + 7) / 8); - this.bitOffset = bitOffset ?? 0; - - // Validate the bit size - if (this.bitSize < 0) { - throw globalThis.Error(`BitArray bit size is invalid: ${this.bitSize}`); - } - - // Validate the bit offset - if (this.bitOffset < 0 || this.bitOffset > 7) { - throw globalThis.Error( - `BitArray bit offset is invalid: ${this.bitOffset}`, - ); - } - - // Validate the length of the buffer - if (buffer.length !== Math.trunc((this.bitOffset + this.bitSize + 7) / 8)) { - throw globalThis.Error("BitArray buffer length is invalid"); - } - - this.rawBuffer = buffer; - } - - /** - * Returns a specific byte in this bit array. If the byte index is out of - * range then `undefined` is returned. - * - * When returning the final byte of a bit array with a bit size that's not a - * multiple of 8, the content of the unused low bits are undefined. - * - * @param {number} index - * @returns {number | undefined} - */ - byteAt(index) { - if (index < 0 || index >= this.byteSize) { - return undefined; - } - - return bitArrayByteAt(this.rawBuffer, this.bitOffset, index); - } - - equals(other) { - if (this.bitSize !== other.bitSize) { - return false; - } - - const wholeByteCount = Math.trunc(this.bitSize / 8); - - // If both bit offsets are zero do a byte-aligned equality check which is - // faster - if (this.bitOffset === 0 && other.bitOffset === 0) { - // Compare any whole bytes - for (let i = 0; i < wholeByteCount; i++) { - if (this.rawBuffer[i] !== other.rawBuffer[i]) { - return false; - } - } - - // Compare any trailing bits, excluding unused low bits - const trailingBitsCount = this.bitSize % 8; - if (trailingBitsCount) { - const unusedLowBitCount = 8 - trailingBitsCount; - if ( - this.rawBuffer[wholeByteCount] >> unusedLowBitCount !== - other.rawBuffer[wholeByteCount] >> unusedLowBitCount - ) { - return false; - } - } - } else { - // Compare any whole bytes - for (let i = 0; i < wholeByteCount; i++) { - const a = bitArrayByteAt(this.rawBuffer, this.bitOffset, i); - const b = bitArrayByteAt(other.rawBuffer, other.bitOffset, i); - - if (a !== b) { - return false; - } - } - - // Compare any trailing bits - const trailingBitsCount = this.bitSize % 8; - if (trailingBitsCount) { - const a = bitArrayByteAt( - this.rawBuffer, - this.bitOffset, - wholeByteCount, - ); - const b = bitArrayByteAt( - other.rawBuffer, - other.bitOffset, - wholeByteCount, - ); - - const unusedLowBitCount = 8 - trailingBitsCount; - if (a >> unusedLowBitCount !== b >> unusedLowBitCount) { - return false; - } - } - } - - return true; - } - - /** - * Returns this bit array's internal buffer. - * - * @deprecated - * - * @returns {Uint8Array} - */ - get buffer() { - if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) { - throw new globalThis.Error( - "BitArray.buffer does not support unaligned bit arrays", - ); - } - - return this.rawBuffer; - } - - /** - * Returns the length in bytes of this bit array's internal buffer. - * - * @deprecated - * - * @returns {number} - */ - get length() { - if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) { - throw new globalThis.Error( - "BitArray.length does not support unaligned bit arrays", - ); - } - - return this.rawBuffer.length; - } -} - -export const BitArray$BitArray = (buffer, bitSize, bitOffset) => - new BitArray(buffer, bitSize, bitOffset); -export const BitArray$isBitArray = (value) => value instanceof BitArray; -export const BitArray$BitArray$data = (bitArray) => { - if (bitArray.bitSize % 8 !== 0) - throw new globalThis.Error( - "BitArray$BitArray$data called on un-aligned bit array", - ); - const array = bitArray.rawBuffer; - return new DataView(array.buffer, array.byteOffset, bitArray.byteSize); -}; - -/** - * Returns the nth byte in the given buffer, after applying the specified bit - * offset. If the index is out of bounds then zero is returned. - * - * @param {Uint8Array} buffer - * @param {number} bitOffset - * @param {number} index - * @returns {number} - */ -function bitArrayByteAt(buffer, bitOffset, index) { - if (bitOffset === 0) { - return buffer[index] ?? 0; - } else { - const a = (buffer[index] << bitOffset) & 0xff; - const b = buffer[index + 1] >> (8 - bitOffset); - - return a | b; - } -} - -export class UtfCodepoint { - constructor(value) { - this.value = value; - } -} - -/** - * Slices a bit array to produce a new bit array. If `end` is not supplied then - * all bits from `start` onward are returned. - * - * If the slice is out of bounds then an exception is thrown. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} [end] - * @returns {BitArray} - */ -export function bitArraySlice(bitArray, start, end) { - end ??= bitArray.bitSize; - - bitArrayValidateRange(bitArray, start, end); - - // Handle zero-length slices - if (start === end) { - return new BitArray(new Uint8Array()); - } - - // Early return for slices that cover the whole bit array - if (start === 0 && end === bitArray.bitSize) { - return bitArray; - } - - start += bitArray.bitOffset; - end += bitArray.bitOffset; - - const startByteIndex = Math.trunc(start / 8); - const endByteIndex = Math.trunc((end + 7) / 8); - const byteLength = endByteIndex - startByteIndex; - - // Avoid creating a new Uint8Array if the view of the underlying ArrayBuffer - // is the same. This can occur when slicing off just the first or last bit of - // a bit array, i.e. when only the bit offset or bit size need to be updated. - let buffer; - if (startByteIndex === 0 && byteLength === bitArray.rawBuffer.byteLength) { - buffer = bitArray.rawBuffer; - } else { - buffer = new Uint8Array( - bitArray.rawBuffer.buffer, - bitArray.rawBuffer.byteOffset + startByteIndex, - byteLength, - ); - } - - return new BitArray(buffer, end - start, start % 8); -} - -/** - * Interprets a slice of this bit array as a floating point number, either - * 32-bit or 64-bit, with the specified endianness. - * - * The value of `end - start` must be exactly 32 or 64, otherwise an exception - * will be thrown. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @returns {number} - */ -export function bitArraySliceToFloat(bitArray, start, end, isBigEndian) { - bitArrayValidateRange(bitArray, start, end); - - const floatSize = end - start; - - // Check size is valid - if (floatSize !== 16 && floatSize !== 32 && floatSize !== 64) { - const msg = - `Sized floats must be 16-bit, 32-bit or 64-bit, got size of ` + - `${floatSize} bits`; - throw new globalThis.Error(msg); - } - - start += bitArray.bitOffset; - - const isStartByteAligned = start % 8 === 0; - - // If the bit range is byte aligned then the float can be read directly out - // of the existing buffer - if (isStartByteAligned) { - const view = new DataView( - bitArray.rawBuffer.buffer, - bitArray.rawBuffer.byteOffset + start / 8, - ); - - if (floatSize === 64) { - return view.getFloat64(0, !isBigEndian); - } else if (floatSize === 32) { - return view.getFloat32(0, !isBigEndian); - } else if (floatSize === 16) { - return fp16UintToNumber(view.getUint16(0, !isBigEndian)); - } - } - - // Copy the unaligned bytes into an aligned array so a DataView can be used - const alignedBytes = new Uint8Array(floatSize / 8); - const byteOffset = Math.trunc(start / 8); - for (let i = 0; i < alignedBytes.length; i++) { - alignedBytes[i] = bitArrayByteAt( - bitArray.rawBuffer, - start % 8, - byteOffset + i, - ); - } - - // Read the float out of the aligned buffer - const view = new DataView(alignedBytes.buffer); - if (floatSize === 64) { - return view.getFloat64(0, !isBigEndian); - } else if (floatSize === 32) { - return view.getFloat32(0, !isBigEndian); - } else { - return fp16UintToNumber(view.getUint16(0, !isBigEndian)); - } -} - -/** - * Interprets a slice of this bit array as a signed or unsigned integer with the - * specified endianness. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -export function bitArraySliceToInt( - bitArray, - start, - end, - isBigEndian, - isSigned, -) { - bitArrayValidateRange(bitArray, start, end); - - if (start === end) { - return 0; - } - - start += bitArray.bitOffset; - end += bitArray.bitOffset; - - const isStartByteAligned = start % 8 === 0; - const isEndByteAligned = end % 8 === 0; - - // If the slice is byte-aligned then there is no need to handle unaligned - // slices, meaning a simpler and faster implementation can be used instead - if (isStartByteAligned && isEndByteAligned) { - return intFromAlignedSlice( - bitArray, - start / 8, - end / 8, - isBigEndian, - isSigned, - ); - } - - const size = end - start; - - const startByteIndex = Math.trunc(start / 8); - const endByteIndex = Math.trunc((end - 1) / 8); - - // Handle the case of the slice being completely contained in a single byte - if (startByteIndex == endByteIndex) { - const mask = 0xff >> (start % 8); - const unusedLowBitCount = (8 - (end % 8)) % 8; - - let value = - (bitArray.rawBuffer[startByteIndex] & mask) >> unusedLowBitCount; - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2 ** (size - 1); - if (value >= highBit) { - value -= highBit * 2; - } - } - - return value; - } - - // The integer value to be read is not aligned and crosses at least one byte - // boundary in the input array - - if (size <= 53) { - return intFromUnalignedSliceUsingNumber( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } else { - return intFromUnalignedSliceUsingBigInt( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } -} - -/** - * Joins the given segments into a new bit array, tightly packing them together. - * Each segment must be one of the following types: - * - * - A `number`: A single byte value in the range 0-255. Values outside this - * range will be wrapped. - * - A `Uint8Array`: A sequence of byte values of any length. - * - A `BitArray`: A sequence of bits of any length, which may not be byte - * aligned. - * - * The bit size of the returned bit array will be the sum of the size in bits - * of the input segments. - * - * @param {(number | Uint8Array | BitArray)[]} segments - * @returns {BitArray} - */ -export function toBitArray(segments) { - if (segments.length === 0) { - return new BitArray(new Uint8Array()); - } - - if (segments.length === 1) { - const segment = segments[0]; - - // When there is a single BitArray segment it can be returned as-is - if (segment instanceof BitArray) { - return segment; - } - - // When there is a single Uint8Array segment, pass it directly to the bit - // array constructor to avoid a copy - if (segment instanceof Uint8Array) { - return new BitArray(segment); - } - - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); - } - - // Count the total number of bits and check if all segments are numbers, i.e. - // single bytes - let bitSize = 0; - let areAllSegmentsNumbers = true; - for (const segment of segments) { - if (segment instanceof BitArray) { - bitSize += segment.bitSize; - areAllSegmentsNumbers = false; - } else if (segment instanceof Uint8Array) { - bitSize += segment.byteLength * 8; - areAllSegmentsNumbers = false; - } else { - bitSize += 8; - } - } - - // If all segments are numbers then pass the segments array directly to the - // Uint8Array constructor - if (areAllSegmentsNumbers) { - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); - } - - // Pack the segments into a Uint8Array - const buffer = new Uint8Array(Math.trunc((bitSize + 7) / 8)); - - // The current write position in bits into the above array. Byte-aligned - // segments, i.e. when the cursor is a multiple of 8, are able to be processed - // faster due to being able to copy bytes directly. - let cursor = 0; - - for (let segment of segments) { - const isCursorByteAligned = cursor % 8 === 0; - - if (segment instanceof BitArray) { - if (isCursorByteAligned && segment.bitOffset === 0) { - buffer.set(segment.rawBuffer, cursor / 8); - cursor += segment.bitSize; - - // Zero any unused bits in the last byte of the buffer. Their content is - // undefined and shouldn't be included in the output. - const trailingBitsCount = segment.bitSize % 8; - if (trailingBitsCount !== 0) { - const lastByteIndex = Math.trunc(cursor / 8); - buffer[lastByteIndex] >>= 8 - trailingBitsCount; - buffer[lastByteIndex] <<= 8 - trailingBitsCount; - } - } else { - appendUnalignedBits( - segment.rawBuffer, - segment.bitSize, - segment.bitOffset, - ); - } - } else if (segment instanceof Uint8Array) { - if (isCursorByteAligned) { - buffer.set(segment, cursor / 8); - cursor += segment.byteLength * 8; - } else { - appendUnalignedBits(segment, segment.byteLength * 8, 0); - } - } else { - if (isCursorByteAligned) { - buffer[cursor / 8] = segment; - cursor += 8; - } else { - appendUnalignedBits(new Uint8Array([segment]), 8, 0); - } - } - } - - function appendUnalignedBits(unalignedBits, size, offset) { - if (size === 0) { - return; - } - - const byteSize = Math.trunc(size + 7 / 8); - - const highBitsCount = cursor % 8; - const lowBitsCount = 8 - highBitsCount; - - let byteIndex = Math.trunc(cursor / 8); - - for (let i = 0; i < byteSize; i++) { - let byte = bitArrayByteAt(unalignedBits, offset, i); - - // If this is a partial byte then zero out the trailing bits as their - // content is undefined and shouldn't be included in the output - if (size < 8) { - byte >>= 8 - size; - byte <<= 8 - size; - } - - // Copy the high bits of the input byte to the low bits of the current - // output byte - buffer[byteIndex] |= byte >> highBitsCount; - - let appendedBitsCount = size - Math.max(0, size - lowBitsCount); - size -= appendedBitsCount; - cursor += appendedBitsCount; - - if (size === 0) { - break; - } - - // Copy the low bits of the input byte to the high bits of the next output - // byte - buffer[++byteIndex] = byte << lowBitsCount; - appendedBitsCount = size - Math.max(0, size - highBitsCount); - size -= appendedBitsCount; - cursor += appendedBitsCount; - } - } - - return new BitArray(buffer, bitSize); -} - -/** - * Encodes a floating point value into a `Uint8Array`. This is used to create - * float segments that are part of bit array expressions. - * - * @param {number} value - * @param {number} size - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function sizedFloat(value, size, isBigEndian) { - if (size !== 16 && size !== 32 && size !== 64) { - const msg = `Sized floats must be 16-bit, 32-bit or 64-bit, got size of ${size} bits`; - throw new globalThis.Error(msg); - } - - if (size === 16) { - return numberToFp16Uint(value, isBigEndian); - } - - const buffer = new Uint8Array(size / 8); - - const view = new DataView(buffer.buffer); - - if (size == 64) { - view.setFloat64(0, value, !isBigEndian); - } else { - view.setFloat32(0, value, !isBigEndian); - } - - return buffer; -} - -/** - * Encodes an integer value into a `Uint8Array`, or a `BitArray` if the size in - * bits is not a multiple of 8. This is used to create integer segments used in - * bit array expressions. - * - * @param {number} value - * @param {number} size - * @param {boolean} isBigEndian - * @returns {Uint8Array | BitArray} - */ -export function sizedInt(value, size, isBigEndian) { - if (size <= 0) { - return new Uint8Array(); - } - - // Fast path when size is 8 bits. This relies on the rounding behavior of the - // Uint8Array constructor. - if (size === 8) { - return new Uint8Array([value]); - } - - // Fast path when size is less than 8 bits: shift the value up to the high - // bits - if (size < 8) { - value <<= 8 - size; - return new BitArray(new Uint8Array([value]), size); - } - - // Allocate output buffer - const buffer = new Uint8Array(Math.trunc((size + 7) / 8)); - - // The number of trailing bits in the final byte. Will be zero if the size is - // an exact number of bytes. - const trailingBitsCount = size % 8; - - // The number of unused bits in the final byte of the buffer - const unusedBitsCount = 8 - trailingBitsCount; - - // For output sizes not exceeding 32 bits the number type is used. For larger - // output sizes the BigInt type is needed. - // - // The code in each of these two paths must be kept in sync. - if (size <= 32) { - if (isBigEndian) { - let i = buffer.length - 1; - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i--] = (value << unusedBitsCount) & 0xff; - value >>= trailingBitsCount; - } - - for (; i >= 0; i--) { - buffer[i] = value; - value >>= 8; - } - } else { - let i = 0; - - const wholeByteCount = Math.trunc(size / 8); - for (; i < wholeByteCount; i++) { - buffer[i] = value; - value >>= 8; - } - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i] = value << unusedBitsCount; - } - } - } else { - const bigTrailingBitsCount = BigInt(trailingBitsCount); - const bigUnusedBitsCount = BigInt(unusedBitsCount); - - let bigValue = BigInt(value); - - if (isBigEndian) { - let i = buffer.length - 1; - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i--] = Number(bigValue << bigUnusedBitsCount); - bigValue >>= bigTrailingBitsCount; - } - - for (; i >= 0; i--) { - buffer[i] = Number(bigValue); - bigValue >>= 8n; - } - } else { - let i = 0; - - const wholeByteCount = Math.trunc(size / 8); - for (; i < wholeByteCount; i++) { - buffer[i] = Number(bigValue); - bigValue >>= 8n; - } - - // Set the trailing bits at the end of the output buffer - if (trailingBitsCount) { - buffer[i] = Number(bigValue << bigUnusedBitsCount); - } - } - } - - // Integers that aren't a whole number of bytes are returned as a BitArray so - // their size in bits is tracked - if (trailingBitsCount) { - return new BitArray(buffer, size); - } - - return buffer; -} - -/** - * Reads an aligned slice of any size as an integer. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromAlignedSlice(bitArray, start, end, isBigEndian, isSigned) { - const byteSize = end - start; - - if (byteSize <= 6) { - return intFromAlignedSliceUsingNumber( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } else { - return intFromAlignedSliceUsingBigInt( - bitArray.rawBuffer, - start, - end, - isBigEndian, - isSigned, - ); - } -} - -/** - * Reads an aligned slice up to 48 bits in size as an integer. Uses the - * JavaScript `number` type internally. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromAlignedSliceUsingNumber( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const byteSize = end - start; - - let value = 0; - - // Read bytes as an unsigned integer - if (isBigEndian) { - for (let i = start; i < end; i++) { - value *= 256; - value += buffer[i]; - } - } else { - for (let i = end - 1; i >= start; i--) { - value *= 256; - value += buffer[i]; - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2 ** (byteSize * 8 - 1); - if (value >= highBit) { - value -= highBit * 2; - } - } - - return value; -} - -/** - * Reads an aligned slice of any size as an integer. Uses the JavaScript - * `BigInt` type internally. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromAlignedSliceUsingBigInt( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const byteSize = end - start; - - let value = 0n; - - // Read bytes as an unsigned integer value - if (isBigEndian) { - for (let i = start; i < end; i++) { - value *= 256n; - value += BigInt(buffer[i]); - } - } else { - for (let i = end - 1; i >= start; i--) { - value *= 256n; - value += BigInt(buffer[i]); - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 1n << BigInt(byteSize * 8 - 1); - if (value >= highBit) { - value -= highBit * 2n; - } - } - - // Convert the result into a JS number. This may cause quantizing/error on - // values outside JavaScript's safe integer range. - return Number(value); -} - -/** - * Reads an unaligned slice up to 53 bits in size as an integer. Uses the - * JavaScript `number` type internally. - * - * This function assumes that the slice crosses at least one byte boundary in - * the input. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromUnalignedSliceUsingNumber( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const isStartByteAligned = start % 8 === 0; - - let size = end - start; - let byteIndex = Math.trunc(start / 8); - - let value = 0; - - if (isBigEndian) { - // Read any leading bits - if (!isStartByteAligned) { - const leadingBitsCount = 8 - (start % 8); - value = buffer[byteIndex++] & ((1 << leadingBitsCount) - 1); - size -= leadingBitsCount; - } - - // Read any whole bytes - while (size >= 8) { - value *= 256; - value += buffer[byteIndex++]; - size -= 8; - } - - // Read any trailing bits - if (size > 0) { - value *= 2 ** size; - value += buffer[byteIndex] >> (8 - size); - } - } else { - // For little endian, if the start is aligned then whole bytes can be read - // directly out of the input array, with the trailing bits handled at the - // end - if (isStartByteAligned) { - let size = end - start; - let scale = 1; - - // Read whole bytes - while (size >= 8) { - value += buffer[byteIndex++] * scale; - scale *= 256; - size -= 8; - } - - // Read trailing bits - value += (buffer[byteIndex] >> (8 - size)) * scale; - } else { - // Read little endian data where the start is not byte-aligned. This is - // done by reading whole bytes that cross a byte boundary in the input - // data, then reading any trailing bits. - - const highBitsCount = start % 8; - const lowBitsCount = 8 - highBitsCount; - - let size = end - start; - let scale = 1; - - // Extract whole bytes - while (size >= 8) { - const byte = - (buffer[byteIndex] << highBitsCount) | - (buffer[byteIndex + 1] >> lowBitsCount); - - value += (byte & 0xff) * scale; - - scale *= 256; - size -= 8; - byteIndex++; - } - - // Read any trailing bits. These trailing bits may cross a byte boundary - // in the input buffer. - if (size > 0) { - const lowBitsUsed = size - Math.max(0, size - lowBitsCount); - - let trailingByte = - (buffer[byteIndex] & ((1 << lowBitsCount) - 1)) >> - (lowBitsCount - lowBitsUsed); - - size -= lowBitsUsed; - - if (size > 0) { - trailingByte *= 2 ** size; - trailingByte += buffer[byteIndex + 1] >> (8 - size); - } - - value += trailingByte * scale; - } - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2 ** (end - start - 1); - if (value >= highBit) { - value -= highBit * 2; - } - } - - return value; -} - -/** - * Reads an unaligned slice of any size as an integer. Uses the JavaScript - * `BigInt` type internally. - * - * This function assumes that the slice crosses at least one byte boundary in - * the input. - * - * @param {Uint8Array} buffer - * @param {number} start - * @param {number} end - * @param {boolean} isBigEndian - * @param {boolean} isSigned - * @returns {number} - */ -function intFromUnalignedSliceUsingBigInt( - buffer, - start, - end, - isBigEndian, - isSigned, -) { - const isStartByteAligned = start % 8 === 0; - - let size = end - start; - let byteIndex = Math.trunc(start / 8); - - let value = 0n; - - if (isBigEndian) { - // Read any leading bits - if (!isStartByteAligned) { - const leadingBitsCount = 8 - (start % 8); - value = BigInt(buffer[byteIndex++] & ((1 << leadingBitsCount) - 1)); - size -= leadingBitsCount; - } - - // Read any whole bytes - while (size >= 8) { - value *= 256n; - value += BigInt(buffer[byteIndex++]); - size -= 8; - } - - // Read any trailing bits - if (size > 0) { - value <<= BigInt(size); - value += BigInt(buffer[byteIndex] >> (8 - size)); - } - } else { - // For little endian, if the start is aligned then whole bytes can be read - // directly out of the input array, with the trailing bits handled at the - // end - if (isStartByteAligned) { - let size = end - start; - let shift = 0n; - - // Read whole bytes - while (size >= 8) { - value += BigInt(buffer[byteIndex++]) << shift; - shift += 8n; - size -= 8; - } - - // Read trailing bits - value += BigInt(buffer[byteIndex] >> (8 - size)) << shift; - } else { - // Read little endian data where the start is not byte-aligned. This is - // done by reading whole bytes that cross a byte boundary in the input - // data, then reading any trailing bits. - - const highBitsCount = start % 8; - const lowBitsCount = 8 - highBitsCount; - - let size = end - start; - let shift = 0n; - - // Extract whole bytes - while (size >= 8) { - const byte = - (buffer[byteIndex] << highBitsCount) | - (buffer[byteIndex + 1] >> lowBitsCount); - - value += BigInt(byte & 0xff) << shift; - - shift += 8n; - size -= 8; - byteIndex++; - } - - // Read any trailing bits. These trailing bits may cross a byte boundary - // in the input buffer. - if (size > 0) { - const lowBitsUsed = size - Math.max(0, size - lowBitsCount); - - let trailingByte = - (buffer[byteIndex] & ((1 << lowBitsCount) - 1)) >> - (lowBitsCount - lowBitsUsed); - - size -= lowBitsUsed; - - if (size > 0) { - trailingByte <<= size; - trailingByte += buffer[byteIndex + 1] >> (8 - size); - } - - value += BigInt(trailingByte) << shift; - } - } - } - - // For signed integers, if the high bit is set reinterpret as two's - // complement - if (isSigned) { - const highBit = 2n ** BigInt(end - start - 1); - if (value >= highBit) { - value -= highBit * 2n; - } - } - - // Convert the result into a JS number. This may cause quantizing/error on - // values outside JavaScript's safe integer range. - return Number(value); -} - -/** - * Interprets a 16-bit unsigned integer value as a 16-bit floating point value. - * - * @param {number} intValue - * @returns {number} - */ -function fp16UintToNumber(intValue) { - const sign = intValue >= 0x8000 ? -1 : 1; - const exponent = (intValue & 0x7c00) >> 10; - const fraction = intValue & 0x03ff; - - let value; - if (exponent === 0) { - value = 6.103515625e-5 * (fraction / 0x400); - } else if (exponent === 0x1f) { - value = fraction === 0 ? Infinity : NaN; - } else { - value = Math.pow(2, exponent - 15) * (1 + fraction / 0x400); - } - - return sign * value; -} - -/** - * Converts a floating point number to bytes for a 16-bit floating point value. - * - * @param {number} intValue - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -function numberToFp16Uint(value, isBigEndian) { - const buffer = new Uint8Array(2); - - if (isNaN(value)) { - buffer[1] = 0x7e; - } else if (value === Infinity) { - buffer[1] = 0x7c; - } else if (value === -Infinity) { - buffer[1] = 0xfc; - } else if (value === 0) { - // Both values are already zero - } else { - const sign = value < 0 ? 1 : 0; - value = Math.abs(value); - - let exponent = Math.floor(Math.log2(value)); - let fraction = value / Math.pow(2, exponent) - 1; - - exponent += 15; - - if (exponent <= 0) { - exponent = 0; - fraction = value / Math.pow(2, -14); - } else if (exponent >= 31) { - exponent = 31; - fraction = 0; - } - - fraction = Math.round(fraction * 1024); - - buffer[1] = - (sign << 7) | ((exponent & 0x1f) << 2) | ((fraction >> 8) & 0x03); - buffer[0] = fraction & 0xff; - } - - if (isBigEndian) { - const a = buffer[0]; - buffer[0] = buffer[1]; - buffer[1] = a; - } - - return buffer; -} - -/** - * Throws an exception if the given start and end values are out of bounds for - * a bit array. - * - * @param {BitArray} bitArray - * @param {number} start - * @param {number} end - */ -function bitArrayValidateRange(bitArray, start, end) { - if ( - start < 0 || - start > bitArray.bitSize || - end < start || - end > bitArray.bitSize - ) { - const msg = - `Invalid bit array slice: start = ${start}, end = ${end}, ` + - `bit size = ${bitArray.bitSize}`; - throw new globalThis.Error(msg); - } -} - -/** @type {TextEncoder | undefined} */ -let utf8Encoder; - -/** - * Returns the UTF-8 bytes for a string. - * - * @param {string} string - * @returns {Uint8Array} - */ -export function stringBits(string) { - utf8Encoder ??= new TextEncoder(); - return utf8Encoder.encode(string); -} - -/** - * Returns the UTF-8 bytes for a single UTF codepoint. - * - * @param {UtfCodepoint} codepoint - * @returns {Uint8Array} - */ -export function codepointBits(codepoint) { - return stringBits(String.fromCodePoint(codepoint.value)); -} - -/** - * Returns the UTF-16 bytes for a string. - * - * @param {string} string - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function stringToUtf16(string, isBigEndian) { - const buffer = new ArrayBuffer(string.length * 2); - const bufferView = new DataView(buffer); - - for (let i = 0; i < string.length; i++) { - bufferView.setUint16(i * 2, string.charCodeAt(i), !isBigEndian); - } - - return new Uint8Array(buffer); -} - -/** - * Returns the UTF-16 bytes for a single UTF codepoint. - * - * @param {UtfCodepoint} codepoint - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function codepointToUtf16(codepoint, isBigEndian) { - return stringToUtf16(String.fromCodePoint(codepoint.value), isBigEndian); -} - -/** - * Returns the UTF-32 bytes for a string. - * - * @param {string} string - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function stringToUtf32(string, isBigEndian) { - const buffer = new ArrayBuffer(string.length * 4); - const bufferView = new DataView(buffer); - let length = 0; - - for (let i = 0; i < string.length; i++) { - const codepoint = string.codePointAt(i); - - bufferView.setUint32(length * 4, codepoint, !isBigEndian); - length++; - - if (codepoint > 0xffff) { - i++; - } - } - - return new Uint8Array(buffer.slice(0, length * 4)); -} - -/** - * Returns the UTF-32 bytes for a single UTF codepoint. - * - * @param {UtfCodepoint} codepoint - * @param {boolean} isBigEndian - * @returns {Uint8Array} - */ -export function codepointToUtf32(codepoint, isBigEndian) { - return stringToUtf32(String.fromCodePoint(codepoint.value), isBigEndian); -} - -export class Result extends CustomType { - static isResult(data) { - return data instanceof Result; - } -} - -export class Ok extends Result { - constructor(value) { - super(); - this[0] = value; - } - - isOk() { - return true; - } -} -export const Result$Ok = (value) => new Ok(value); -export const Result$isOk = (value) => value instanceof Ok; -export const Result$Ok$0 = (value) => value[0]; - -export class Error extends Result { - constructor(detail) { - super(); - this[0] = detail; - } - - isOk() { - return false; - } -} -export const Result$Error = (detail) => new Error(detail); -export const Result$isError = (value) => value instanceof Error; -export const Result$Error$0 = (value) => value[0]; - -export function isEqual(x, y) { - let values = [x, y]; - - while (values.length) { - let a = values.pop(); - let b = values.pop(); - if (a === b) continue; - - if (!isObject(a) || !isObject(b)) return false; - let unequal = - !structurallyCompatibleObjects(a, b) || - unequalDates(a, b) || - unequalBuffers(a, b) || - unequalArrays(a, b) || - unequalMaps(a, b) || - unequalSets(a, b) || - unequalRegExps(a, b); - if (unequal) return false; - - const proto = Object.getPrototypeOf(a); - if (proto !== null && typeof proto.equals === "function") { - try { - if (a.equals(b)) continue; - else return false; - } catch {} - } - - let [keys, get] = getters(a); - const ka = keys(a); - const kb = keys(b); - if (ka.length !== kb.length) return false; - for (let k of ka) { - values.push(get(a, k), get(b, k)); - } - } - - return true; -} - -function getters(object) { - if (object instanceof Map) { - return [(x) => x.keys(), (x, y) => x.get(y)]; - } else { - let extra = object instanceof globalThis.Error ? ["message"] : []; - return [(x) => [...extra, ...Object.keys(x)], (x, y) => x[y]]; - } -} - -function unequalDates(a, b) { - return a instanceof Date && (a > b || a < b); -} - -function unequalBuffers(a, b) { - return ( - !(a instanceof BitArray) && - a.buffer instanceof ArrayBuffer && - a.BYTES_PER_ELEMENT && - !(a.byteLength === b.byteLength && a.every((n, i) => n === b[i])) - ); -} - -function unequalArrays(a, b) { - return Array.isArray(a) && a.length !== b.length; -} - -function unequalMaps(a, b) { - return a instanceof Map && a.size !== b.size; -} - -function unequalSets(a, b) { - return ( - a instanceof Set && (a.size != b.size || [...a].some((e) => !b.has(e))) - ); -} - -function unequalRegExps(a, b) { - return a instanceof RegExp && (a.source !== b.source || a.flags !== b.flags); -} - -function isObject(a) { - return typeof a === "object" && a !== null; -} - -function structurallyCompatibleObjects(a, b) { - if (typeof a !== "object" && typeof b !== "object" && (!a || !b)) - return false; - - let nonstructural = [Promise, WeakSet, WeakMap, Function]; - if (nonstructural.some((c) => a instanceof c)) return false; - - return a.constructor === b.constructor; -} - -export function remainderInt(a, b) { - if (b === 0) { - return 0; - } else { - return a % b; - } -} - -export function divideInt(a, b) { - return Math.trunc(divideFloat(a, b)); -} - -export function divideFloat(a, b) { - if (b === 0) { - return 0; - } else { - return a / b; - } -} - -export function makeError(variant, file, module, line, fn, message, extra) { - let error = new globalThis.Error(message); - error.gleam_error = variant; - error.file = file; - error.module = module; - error.line = line; - error.function = fn; - // TODO: Remove this with Gleam v2.0.0 - error.fn = fn; - for (let k in extra) error[k] = extra[k]; - return error; -} diff --git a/ui/javascript/simplifile/_gleam_artefacts/simplifile.cache b/ui/javascript/simplifile/_gleam_artefacts/simplifile.cache deleted file mode 100644 index 2483b27..0000000 Binary files a/ui/javascript/simplifile/_gleam_artefacts/simplifile.cache and /dev/null differ diff --git a/ui/javascript/simplifile/_gleam_artefacts/simplifile.cache_meta b/ui/javascript/simplifile/_gleam_artefacts/simplifile.cache_meta deleted file mode 100644 index 0e4e97b..0000000 Binary files a/ui/javascript/simplifile/_gleam_artefacts/simplifile.cache_meta and /dev/null differ diff --git a/ui/javascript/simplifile/gleam.mjs b/ui/javascript/simplifile/gleam.mjs deleted file mode 100644 index 197cbbc..0000000 --- a/ui/javascript/simplifile/gleam.mjs +++ /dev/null @@ -1 +0,0 @@ -export * from "../prelude.mjs"; diff --git a/ui/javascript/simplifile/simplifile.erl b/ui/javascript/simplifile/simplifile.erl deleted file mode 100644 index 9e0596a..0000000 --- a/ui/javascript/simplifile/simplifile.erl +++ /dev/null @@ -1,903 +0,0 @@ --module(simplifile). --compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). --define(FILEPATH, "src/simplifile.gleam"). --export([describe_error/1, file_info_permissions_octal/1, file_info_type/1, file_info/1, link_info/1, delete/1, delete_file/1, delete_all/1, read_bits/1, read/1, write_bits/2, write/2, append_bits/2, append/2, is_directory/1, create_directory/1, create_symlink/2, create_link/2, read_directory/1, is_file/1, is_symlink/1, create_file/1, create_directory_all/1, copy_file/2, rename_file/2, rename/2, copy_directory/2, copy/2, rename_directory/2, clear_directory/1, get_files/1, file_permissions_to_octal/1, file_info_permissions/1, set_permissions_octal/2, set_permissions/2, current_directory/0]). --export_type([file_error/0, file_info/0, file_type/0, permission/0, file_permissions/0]). - --if(?OTP_RELEASE >= 27). --define(MODULEDOC(Str), -moduledoc(Str)). --define(DOC(Str), -doc(Str)). --else. --define(MODULEDOC(Str), -compile([])). --define(DOC(Str), -compile([])). --endif. - --type file_error() :: eacces | - eagain | - ebadf | - ebadmsg | - ebusy | - edeadlk | - edeadlock | - edquot | - eexist | - efault | - efbig | - eftype | - eintr | - einval | - eio | - eisdir | - eloop | - emfile | - emlink | - emultihop | - enametoolong | - enfile | - enobufs | - enodev | - enolck | - enolink | - enoent | - enomem | - enospc | - enosr | - enostr | - enosys | - enotblk | - enotdir | - enotsup | - enxio | - eopnotsupp | - eoverflow | - eperm | - epipe | - erange | - erofs | - espipe | - esrch | - estale | - etxtbsy | - exdev | - not_utf8 | - {unknown, binary()}. - --type file_info() :: {file_info, - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer(), - integer()}. - --type file_type() :: file | directory | symlink | other. - --type permission() :: read | write | execute. - --type file_permissions() :: {file_permissions, - gleam@set:set(permission()), - gleam@set:set(permission()), - gleam@set:set(permission())}. - --file("src/simplifile.gleam", 124). -?DOC( - " Convert an error into a human-readable description\n" - " ## Example\n" - " ```gleam\n" - " let assert \"Input/output error\" = describe_error(Eio)\n" - " ```\n" -). --spec describe_error(file_error()) -> binary(). -describe_error(Error) -> - case Error of - eperm -> - <<"Operation not permitted"/utf8>>; - - enoent -> - <<"No such file or directory"/utf8>>; - - esrch -> - <<"No such process"/utf8>>; - - eintr -> - <<"Interrupted system call"/utf8>>; - - eio -> - <<"Input/output error"/utf8>>; - - enxio -> - <<"Device not configured"/utf8>>; - - ebadf -> - <<"Bad file descriptor"/utf8>>; - - edeadlk -> - <<"Resource deadlock avoided"/utf8>>; - - edeadlock -> - <<"Resource deadlock avoided"/utf8>>; - - enomem -> - <<"Cannot allocate memory"/utf8>>; - - eacces -> - <<"Permission denied"/utf8>>; - - efault -> - <<"Bad address"/utf8>>; - - enotblk -> - <<"Block device required"/utf8>>; - - ebusy -> - <<"Resource busy"/utf8>>; - - eexist -> - <<"File exists"/utf8>>; - - exdev -> - <<"Cross-device link"/utf8>>; - - enodev -> - <<"Operation not supported by device"/utf8>>; - - enotdir -> - <<"Not a directory"/utf8>>; - - eisdir -> - <<"Is a directory"/utf8>>; - - einval -> - <<"Invalid argument"/utf8>>; - - enfile -> - <<"Too many open files in system"/utf8>>; - - emfile -> - <<"Too many open files"/utf8>>; - - etxtbsy -> - <<"Text file busy"/utf8>>; - - efbig -> - <<"File too large"/utf8>>; - - enospc -> - <<"No space left on device"/utf8>>; - - espipe -> - <<"Illegal seek"/utf8>>; - - erofs -> - <<"Read-only file system"/utf8>>; - - emlink -> - <<"Too many links"/utf8>>; - - epipe -> - <<"Broken pipe"/utf8>>; - - erange -> - <<"Result too large"/utf8>>; - - eagain -> - <<"Resource temporarily unavailable"/utf8>>; - - enotsup -> - <<"Operation not supported"/utf8>>; - - enobufs -> - <<"No buffer space available"/utf8>>; - - eloop -> - <<"Too many levels of symbolic links"/utf8>>; - - enametoolong -> - <<"File name too long"/utf8>>; - - edquot -> - <<"Disc quota exceeded"/utf8>>; - - estale -> - <<"Stale NFS file handle"/utf8>>; - - enolck -> - <<"No locks available"/utf8>>; - - enosys -> - <<"Function not implemented"/utf8>>; - - eftype -> - <<"Inappropriate file type or format"/utf8>>; - - eoverflow -> - <<"Value too large to be stored in data type"/utf8>>; - - ebadmsg -> - <<"Bad message"/utf8>>; - - emultihop -> - <<"Multihop attempted"/utf8>>; - - enolink -> - <<"Link has been severed"/utf8>>; - - enosr -> - <<"No STREAM resources"/utf8>>; - - enostr -> - <<"Not a STREAM"/utf8>>; - - eopnotsupp -> - <<"Operation not supported on socket"/utf8>>; - - not_utf8 -> - <<"File not UTF-8 encoded"/utf8>>; - - {unknown, Inner} -> - <<"Unknown error: "/utf8, Inner/binary>> - end. - --file("src/simplifile.gleam", 232). -?DOC( - " Extract the file permissions from a given FileInfo value in their octal representation.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " use info <- result.try(simplifile.file_info(\"src/app.gleam\"))\n" - " simplifile.file_info_permissions_octal(info)\n" - " // --> 0o644\n" - " ```\n" -). --spec file_info_permissions_octal(file_info()) -> integer(). -file_info_permissions_octal(File_info) -> - erlang:'band'(erlang:element(3, File_info), 8#777). - --file("src/simplifile.gleam", 261). -?DOC( - " Extract the file type from a given FileInfo value.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " use info <- result.try(simplifile.file_info(\"src/app.gleam\"))\n" - " simplifile.file_info_type(info)\n" - " // --> simplifile.File\n" - " ```\n" -). --spec file_info_type(file_info()) -> file_type(). -file_info_type(File_info) -> - case erlang:'band'(erlang:element(3, File_info), 8#170000) of - 8#100000 -> - file; - - 8#40000 -> - directory; - - 8#120000 -> - symlink; - - _ -> - other - end. - --file("src/simplifile.gleam", 281). -?DOC( - " Get information about a file at a given path\n" - "\n" - " When the given `filepath` points to a symlink, this function will follow\n" - " the symlink and return information about the target file.\n" - "\n" - " See `link_info` if you want to get information about a symlink instead.\n" -). --spec file_info(binary()) -> {ok, file_info()} | {error, file_error()}. -file_info(Filepath) -> - simplifile_erl:file_info(Filepath). - --file("src/simplifile.gleam", 291). -?DOC( - " Get information about a file at a given path\n" - "\n" - " When the given `filepath` is a symlink, this function will return\n" - " infromation about the symlink itself.\n" - "\n" - " See `file_info` if you want to follow symlinks instead.\n" -). --spec link_info(binary()) -> {ok, file_info()} | {error, file_error()}. -link_info(Filepath) -> - simplifile_erl:link_info(Filepath). - --file("src/simplifile.gleam", 335). -?DOC( - " Delete a file or directory at a given path. Performs a recursive\n" - " delete on a directory.\n" - " Throws an error if the path does not exist.\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(Nil) = delete(file_at: \"./delete_me.txt\")\n" - " ```\n" -). --spec delete(binary()) -> {ok, nil} | {error, file_error()}. -delete(Path) -> - simplifile_erl:delete(Path). - --file("src/simplifile.gleam", 342). -?DOC( - " Delete a file. \n" - " On Erlang, if you're specifically deleting a single file, this function \n" - " should be more efficient than `delete` because it can pass the raw option.\n" -). --spec delete_file(binary()) -> {ok, nil} | {error, file_error()}. -delete_file(Path) -> - simplifile_erl:delete_file(Path). - --file("src/simplifile.gleam", 349). -?DOC( - " Delete all files/directories specified in a list of paths.\n" - " Recursively deletes provided directories.\n" - " Does not return an error if one or more of the provided paths\n" - " do not exist.\n" -). --spec delete_all(list(binary())) -> {ok, nil} | {error, file_error()}. -delete_all(Paths) -> - case Paths of - [] -> - {ok, nil}; - - [Path | Rest] -> - case simplifile_erl:delete(Path) of - {ok, nil} -> - delete_all(Rest); - - {error, enoent} -> - delete_all(Rest); - - E -> - E - end - end. - --file("src/simplifile.gleam", 383). -?DOC( - " Read a files contents as a bitstring\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(records) = read_bits(from: \"./users.csv\")\n" - " ```\n" -). --spec read_bits(binary()) -> {ok, bitstring()} | {error, file_error()}. -read_bits(Filepath) -> - simplifile_erl:read_bits(Filepath). - --file("src/simplifile.gleam", 299). -?DOC( - " Read a files contents as a string\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(records) = read(from: \"./users.csv\")\n" - " ```\n" -). --spec read(binary()) -> {ok, binary()} | {error, file_error()}. -read(Filepath) -> - case simplifile_erl:read_bits(Filepath) of - {ok, Bits} -> - case gleam@bit_array:to_string(Bits) of - {ok, Str} -> - {ok, Str}; - - _ -> - {error, not_utf8} - end; - - {error, E} -> - {error, E} - end. - --file("src/simplifile.gleam", 393). -?DOC( - " Write a bitstring to a file at the given path\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(Nil) = write_bits(to: \"./hello_world.txt\", bits: <<\"Hello, World!\":utf8>>)\n" - " ```\n" -). --spec write_bits(binary(), bitstring()) -> {ok, nil} | {error, file_error()}. -write_bits(Filepath, Bits) -> - simplifile_erl:write_bits(Filepath, Bits). - --file("src/simplifile.gleam", 317). -?DOC( - " Write a string to a file at the given path\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(Nil) = write(to: \"./hello_world.txt\", contents: \"Hello, World!\")\n" - " ```\n" -). --spec write(binary(), binary()) -> {ok, nil} | {error, file_error()}. -write(Filepath, Contents) -> - _pipe = Contents, - _pipe@1 = gleam_stdlib:identity(_pipe), - simplifile_erl:write_bits(Filepath, _pipe@1). - --file("src/simplifile.gleam", 406). -?DOC( - " Append a bitstring to the contents of a file at the given path\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(Nil) = append_bits(to: \"./needs_more_text.txt\", bits: <<\"more text\":utf8>>)\n" - " ```\n" -). --spec append_bits(binary(), bitstring()) -> {ok, nil} | {error, file_error()}. -append_bits(Filepath, Bits) -> - simplifile_erl:append_bits(Filepath, Bits). - --file("src/simplifile.gleam", 367). -?DOC( - " Append a string to the contents of a file at the given path\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(Nil) = append(to: \"./needs_more_text.txt\", contents: \"more text\")\n" - " ```\n" -). --spec append(binary(), binary()) -> {ok, nil} | {error, file_error()}. -append(Filepath, Contents) -> - _pipe = Contents, - _pipe@1 = gleam_stdlib:identity(_pipe), - simplifile_erl:append_bits(Filepath, _pipe@1). - --file("src/simplifile.gleam", 420). -?DOC( - " Checks if the provided filepath exists and is a directory.\n" - " Returns an error if it lacks permissions to read the directory.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(True) = is_directory(\"./test\")\n" - " ```\n" -). --spec is_directory(binary()) -> {ok, boolean()} | {error, file_error()}. -is_directory(Filepath) -> - simplifile_erl:is_directory(Filepath). - --file("src/simplifile.gleam", 431). -?DOC( - " Create a directory at the provided filepath. Returns an error if\n" - " the directory already exists.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " create_directory(\"./test\")\n" - " ```\n" -). --spec create_directory(binary()) -> {ok, nil} | {error, file_error()}. -create_directory(Filepath) -> - simplifile_erl:create_directory(Filepath). - --file("src/simplifile.gleam", 446). -?DOC( - " Create a symbolic link called symlink pointing to target.\n" - " \n" - " ### Footgun Alert \n" - " the target path is relative to *the symlink*,\n" - " not the current working directory. I will likely be updating \n" - " the label on the next major version to reflect that.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " create_symlink(\"../target\", \"./symlink\")\n" - " ```\n" -). --spec create_symlink(binary(), binary()) -> {ok, nil} | {error, file_error()}. -create_symlink(Target, Symlink) -> - simplifile_erl:create_symlink(Target, Symlink). - --file("src/simplifile.gleam", 461). -?DOC( - " Create a \"hard link\" called symlink pointing to target.\n" - " This does not have the same relative pathing footgun as \n" - " `create_symlink`.\n" - " \n" - " ## Example\n" - " ```gleam\n" - " create_link(\"../target\", \"./link\")\n" - " ```\n" -). --spec create_link(binary(), binary()) -> {ok, nil} | {error, file_error()}. -create_link(Target, Link) -> - simplifile_erl:create_link(Target, Link). - --file("src/simplifile.gleam", 476). -?DOC( - " Lists the contents of a directory.\n" - " The list contains directory and file names, and is not recursive.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(files_and_folders) = read_directory(at: \"./Folder1\")\n" - " ```\n" -). --spec read_directory(binary()) -> {ok, list(binary())} | {error, file_error()}. -read_directory(Path) -> - simplifile_erl:read_directory(Path). - --file("src/simplifile.gleam", 488). -?DOC( - " Checks if the file at the provided filepath exists and is a file.\n" - " Returns an Error if it lacks permissions to read the file.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(True) = is_file(\"./test.txt\")\n" - " ```\n" -). --spec is_file(binary()) -> {ok, boolean()} | {error, file_error()}. -is_file(Filepath) -> - simplifile_erl:is_file(Filepath). - --file("src/simplifile.gleam", 500). -?DOC( - " Checks if the file at the provided filepath exists and is a symbolic link.\n" - " Returns an Error if it lacks permissions to read the file.\n" - "\n" - " ## Example\n" - " ```gleam\n" - " let assert Ok(True) = is_symlink(\"./symlink\")\n" - " ```\n" -). --spec is_symlink(binary()) -> {ok, boolean()} | {error, file_error()}. -is_symlink(Filepath) -> - simplifile_erl:is_symlink(Filepath). - --file("src/simplifile.gleam", 505). -?DOC( - " Creates an empty file at the given filepath. Returns an `Error(Eexist)`\n" - " if the file already exists.\n" -). --spec create_file(binary()) -> {ok, nil} | {error, file_error()}. -create_file(Filepath) -> - case {begin - _pipe = Filepath, - simplifile_erl:is_file(_pipe) - end, - begin - _pipe@1 = Filepath, - simplifile_erl:is_directory(_pipe@1) - end} of - {{ok, true}, _} -> - {error, eexist}; - - {_, {ok, true}} -> - {error, eexist}; - - {_, _} -> - simplifile_erl:write_bits(Filepath, <<>>) - end. - --file("src/simplifile.gleam", 516). -?DOC( - " Recursively creates necessary directories for a given directory\n" - " path. Note that if you pass a path that \"looks like\" a file, i.e.\n" - " `./a/b.txt`, a folder named `b.txt` will be created, so be sure\n" - " to pass only the path to the required directory.\n" -). --spec create_directory_all(binary()) -> {ok, nil} | {error, file_error()}. -create_directory_all(Dirpath) -> - simplifile_erl:create_dir_all(<>). - --file("src/simplifile.gleam", 546). -?DOC( - " Copy a file at a given path to another path.\n" - " Note: destination should include the filename, not just the directory\n" -). --spec copy_file(binary(), binary()) -> {ok, nil} | {error, file_error()}. -copy_file(Src, Dest) -> - _pipe = file:copy(Src, Dest), - gleam@result:replace(_pipe, nil). - --file("src/simplifile.gleam", 560). -?DOC( - " Rename a file at a given path to another path.\n" - " Note: destination should include the filename, not just the directory\n" -). --spec rename_file(binary(), binary()) -> {ok, nil} | {error, file_error()}. -rename_file(Src, Dest) -> - simplifile_erl:rename_file(Src, Dest). - --file("src/simplifile.gleam", 565). -?DOC(" Rename a file or directory.\n"). --spec rename(binary(), binary()) -> {ok, nil} | {error, file_error()}. -rename(Src, Dest) -> - simplifile_erl:rename_file(Src, Dest). - --file("src/simplifile.gleam", 576). --spec do_copy_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. -do_copy_directory(Src, Dest) -> - gleam@result:'try'( - simplifile_erl:read_directory(Src), - fun(Segments) -> - _pipe = Segments, - gleam@list:each( - _pipe, - fun(Segment) -> - Src_path = filepath:join(Src, Segment), - Dest_path = filepath:join(Dest, Segment), - gleam@result:'try'( - simplifile_erl:file_info(Src_path), - fun(Src_info) -> case file_info_type(Src_info) of - file -> - gleam@result:'try'( - simplifile_erl:read_bits(Src_path), - fun(Content) -> _pipe@1 = Content, - simplifile_erl:write_bits( - Dest_path, - _pipe@1 - ) end - ); - - directory -> - gleam@result:'try'( - simplifile_erl:create_directory( - Dest_path - ), - fun(_) -> - do_copy_directory( - Src_path, - Dest_path - ) - end - ); - - symlink -> - {error, - {unknown, - <<"This is an internal bug where the `file_info` is somehow returning info about a simlink. Please file an issue on the simplifile repo."/utf8>>}}; - - other -> - {error, - {unknown, - <<"Unknown file type (not file, directory, or simlink)"/utf8>>}} - end end - ) - end - ), - {ok, nil} - end - ). - --file("src/simplifile.gleam", 568). -?DOC(" Copy a directory recursively\n"). --spec copy_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. -copy_directory(Src, Dest) -> - gleam@result:'try'( - create_directory_all(Dest), - fun(_) -> do_copy_directory(Src, Dest) end - ). - --file("src/simplifile.gleam", 530). -?DOC( - " Copy a file or a directory to a new path. Copies directories recursively.\n" - " \n" - " ### Performance Note \n" - " This function does work to determine if the src path\n" - " points to a file or a directory. Consider using one of the the dedicated \n" - " functions `copy_file` or `copy_directory` if you already know which one you need.\n" -). --spec copy(binary(), binary()) -> {ok, nil} | {error, file_error()}. -copy(Src, Dest) -> - gleam@result:'try'( - simplifile_erl:file_info(Src), - fun(Src_info) -> case file_info_type(Src_info) of - file -> - copy_file(Src, Dest); - - directory -> - copy_directory(Src, Dest); - - symlink -> - {error, - {unknown, - <<"This is an internal bug where the `file_info` is somehow returning info about a simlink. Please file an issue on the simplifile repo."/utf8>>}}; - - other -> - {error, - {unknown, - <<"Unknown file type (not file, directory, or simlink)"/utf8>>}} - end end - ). - --file("src/simplifile.gleam", 612). -?DOC(" Copy a directory recursively and then delete the old one.\n"). --spec rename_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. -rename_directory(Src, Dest) -> - gleam@result:'try'( - copy_directory(Src, Dest), - fun(_) -> simplifile_erl:delete(Src) end - ). - --file("src/simplifile.gleam", 622). -?DOC( - " Clear the contents of a directory, deleting all files and directories within\n" - " but leaving the top level directory in place.\n" -). --spec clear_directory(binary()) -> {ok, nil} | {error, file_error()}. -clear_directory(Path) -> - gleam@result:'try'( - simplifile_erl:read_directory(Path), - fun(Paths) -> _pipe = Paths, - _pipe@1 = gleam@list:map( - _pipe, - fun(_capture) -> filepath:join(Path, _capture) end - ), - delete_all(_pipe@1) end - ). - --file("src/simplifile.gleam", 632). -?DOC( - " Returns a list of filepaths for every file in the directory, including nested\n" - " files.\n" -). --spec get_files(binary()) -> {ok, list(binary())} | {error, file_error()}. -get_files(Directory) -> - gleam@result:'try'( - simplifile_erl:read_directory(Directory), - fun(Contents) -> - gleam@list:try_fold( - Contents, - [], - fun(Acc, Content) -> - Path = filepath:join(Directory, Content), - gleam@result:'try'( - simplifile_erl:file_info(Path), - fun(Info) -> case file_info_type(Info) of - file -> - {ok, [Path | Acc]}; - - directory -> - gleam@result:'try'( - get_files(Path), - fun(Nested_files) -> - {ok, - lists:append(Acc, Nested_files)} - end - ); - - _ -> - {ok, Acc} - end end - ) - end - ) - end - ). - --file("src/simplifile.gleam", 655). --spec permission_to_integer(permission()) -> integer(). -permission_to_integer(Permission) -> - case Permission of - read -> - 8#4; - - write -> - 8#2; - - execute -> - 8#1 - end. - --file("src/simplifile.gleam", 663). --spec integer_to_permissions(integer()) -> gleam@set:set(permission()). -integer_to_permissions(Integer) -> - case erlang:'band'(Integer, 7) of - 7 -> - gleam@set:from_list([read, write, execute]); - - 6 -> - gleam@set:from_list([read, write]); - - 5 -> - gleam@set:from_list([read, execute]); - - 3 -> - gleam@set:from_list([write, execute]); - - 4 -> - gleam@set:from_list([read]); - - 2 -> - gleam@set:from_list([write]); - - 1 -> - gleam@set:from_list([execute]); - - 0 -> - gleam@set:new(); - - _ -> - erlang:error(#{gleam_error => panic, - message => <<"`panic` expression evaluated."/utf8>>, - file => <>, - module => <<"simplifile"/utf8>>, - function => <<"integer_to_permissions"/utf8>>, - line => 674}) - end. - --file("src/simplifile.gleam", 687). --spec file_permissions_to_octal(file_permissions()) -> integer(). -file_permissions_to_octal(Permissions) -> - Make_permission_digit = fun(Permissions@1) -> _pipe = Permissions@1, - _pipe@1 = gleam@set:to_list(_pipe), - _pipe@2 = gleam@list:map(_pipe@1, fun permission_to_integer/1), - gleam@int:sum(_pipe@2) end, - ((Make_permission_digit(erlang:element(2, Permissions)) * 64) + (Make_permission_digit( - erlang:element(3, Permissions) - ) - * 8)) - + Make_permission_digit(erlang:element(4, Permissions)). - --file("src/simplifile.gleam", 702). --spec octal_to_file_permissions(integer()) -> file_permissions(). -octal_to_file_permissions(Octal) -> - {file_permissions, - begin - _pipe = Octal, - _pipe@1 = erlang:'bsr'(_pipe, 6), - integer_to_permissions(_pipe@1) - end, - begin - _pipe@2 = Octal, - _pipe@3 = erlang:'bsr'(_pipe@2, 3), - integer_to_permissions(_pipe@3) - end, - begin - _pipe@4 = Octal, - integer_to_permissions(_pipe@4) - end}. - --file("src/simplifile.gleam", 237). -?DOC(" Extract the `FilePermissions` from a given FileInfo value.\n"). --spec file_info_permissions(file_info()) -> file_permissions(). -file_info_permissions(File_info) -> - octal_to_file_permissions(file_info_permissions_octal(File_info)). - --file("src/simplifile.gleam", 738). -?DOC( - " Sets the permissions for a given file using an octal representation\n" - "\n" - " # Example\n" - " ```gleam\n" - " set_permissions_octal(\"./script.sh\", 0o777)\n" - " ```\n" -). --spec set_permissions_octal(binary(), integer()) -> {ok, nil} | - {error, file_error()}. -set_permissions_octal(Filepath, Permissions) -> - simplifile_erl:set_permissions_octal(Filepath, Permissions). - --file("src/simplifile.gleam", 723). -?DOC( - " Sets the permissions for a given file\n" - "\n" - " # Example\n" - " ```gleam\n" - " let all = set.from_list([Read, Write, Execute])\n" - " let all = FilePermissions(user: all, group: all, other: all)\n" - " let assert Ok(Nil) = set_permissions(\"./script.sh\", all)\n" - " ```\n" -). --spec set_permissions(binary(), file_permissions()) -> {ok, nil} | - {error, file_error()}. -set_permissions(Filepath, Permissions) -> - simplifile_erl:set_permissions_octal( - Filepath, - file_permissions_to_octal(Permissions) - ). - --file("src/simplifile.gleam", 746). -?DOC(" Returns the current working directory\n"). --spec current_directory() -> {ok, binary()} | {error, file_error()}. -current_directory() -> - _pipe = file:get_cwd(), - gleam@result:map(_pipe, fun gleam_stdlib:utf_codepoint_list_to_string/1). diff --git a/ui/javascript/simplifile/simplifile.mjs b/ui/javascript/simplifile/simplifile.mjs deleted file mode 100644 index 401f48f..0000000 --- a/ui/javascript/simplifile/simplifile.mjs +++ /dev/null @@ -1,1053 +0,0 @@ -import * as $filepath from "../filepath/filepath.mjs"; -import * as $bit_array from "../gleam_stdlib/gleam/bit_array.mjs"; -import * as $int from "../gleam_stdlib/gleam/int.mjs"; -import * as $list from "../gleam_stdlib/gleam/list.mjs"; -import * as $result from "../gleam_stdlib/gleam/result.mjs"; -import * as $set from "../gleam_stdlib/gleam/set.mjs"; -import * as $string from "../gleam_stdlib/gleam/string.mjs"; -import { - Ok, - Error, - toList, - Empty as $Empty, - prepend as listPrepend, - CustomType as $CustomType, - makeError, - toBitArray, -} from "./gleam.mjs"; -import { - fileInfo as file_info, - linkInfo as link_info, - readBits as read_bits, - writeBits as write_bits, - delete_ as delete$, - deleteFile as delete_file, - appendBits as append_bits, - isDirectory as is_directory, - createDirectory as create_directory, - createSymlink as create_symlink, - createLink as create_link, - readDirectory as read_directory, - isFile as is_file, - isSymlink as is_symlink, - createDirAll as do_create_dir_all, - copyFile as do_copy_file, - renameFile as rename_file, - renameFile as rename, - setPermissionsOctal as set_permissions_octal, - currentDirectory as current_directory, -} from "./simplifile_js.mjs"; - -export { - append_bits, - create_directory, - create_link, - create_symlink, - current_directory, - delete$, - delete_file, - file_info, - is_directory, - is_file, - is_symlink, - link_info, - read_bits, - read_directory, - rename, - rename_file, - set_permissions_octal, - write_bits, -}; - -const FILEPATH = "src/simplifile.gleam"; - -/** - * Permission denied. - */ -export class Eacces extends $CustomType {} -export const FileError$Eacces = () => new Eacces(); -export const FileError$isEacces = (value) => value instanceof Eacces; - -/** - * Resource temporarily unavailable. - */ -export class Eagain extends $CustomType {} -export const FileError$Eagain = () => new Eagain(); -export const FileError$isEagain = (value) => value instanceof Eagain; - -/** - * Bad file number - */ -export class Ebadf extends $CustomType {} -export const FileError$Ebadf = () => new Ebadf(); -export const FileError$isEbadf = (value) => value instanceof Ebadf; - -/** - * Bad message. - */ -export class Ebadmsg extends $CustomType {} -export const FileError$Ebadmsg = () => new Ebadmsg(); -export const FileError$isEbadmsg = (value) => value instanceof Ebadmsg; - -/** - * File busy. - */ -export class Ebusy extends $CustomType {} -export const FileError$Ebusy = () => new Ebusy(); -export const FileError$isEbusy = (value) => value instanceof Ebusy; - -/** - * Resource deadlock avoided. - */ -export class Edeadlk extends $CustomType {} -export const FileError$Edeadlk = () => new Edeadlk(); -export const FileError$isEdeadlk = (value) => value instanceof Edeadlk; - -/** - * On most architectures, same as `Edeadlk`. On some architectures, it - * means "File locking deadlock error." - */ -export class Edeadlock extends $CustomType {} -export const FileError$Edeadlock = () => new Edeadlock(); -export const FileError$isEdeadlock = (value) => value instanceof Edeadlock; - -/** - * Disk quota exceeded. - */ -export class Edquot extends $CustomType {} -export const FileError$Edquot = () => new Edquot(); -export const FileError$isEdquot = (value) => value instanceof Edquot; - -/** - * File already exists. - */ -export class Eexist extends $CustomType {} -export const FileError$Eexist = () => new Eexist(); -export const FileError$isEexist = (value) => value instanceof Eexist; - -/** - * Bad address in system call argument. - */ -export class Efault extends $CustomType {} -export const FileError$Efault = () => new Efault(); -export const FileError$isEfault = (value) => value instanceof Efault; - -/** - * File too large. - */ -export class Efbig extends $CustomType {} -export const FileError$Efbig = () => new Efbig(); -export const FileError$isEfbig = (value) => value instanceof Efbig; - -/** - * Inappropriate file type or format. Usually caused by trying to set the - * "sticky bit" on a regular file (not a directory). - */ -export class Eftype extends $CustomType {} -export const FileError$Eftype = () => new Eftype(); -export const FileError$isEftype = (value) => value instanceof Eftype; - -/** - * Interrupted system call. - */ -export class Eintr extends $CustomType {} -export const FileError$Eintr = () => new Eintr(); -export const FileError$isEintr = (value) => value instanceof Eintr; - -/** - * Invalid argument. - */ -export class Einval extends $CustomType {} -export const FileError$Einval = () => new Einval(); -export const FileError$isEinval = (value) => value instanceof Einval; - -/** - * I/O error. - */ -export class Eio extends $CustomType {} -export const FileError$Eio = () => new Eio(); -export const FileError$isEio = (value) => value instanceof Eio; - -/** - * Illegal operation on a directory. - */ -export class Eisdir extends $CustomType {} -export const FileError$Eisdir = () => new Eisdir(); -export const FileError$isEisdir = (value) => value instanceof Eisdir; - -/** - * Too many levels of symbolic links. - */ -export class Eloop extends $CustomType {} -export const FileError$Eloop = () => new Eloop(); -export const FileError$isEloop = (value) => value instanceof Eloop; - -/** - * Too many open files. - */ -export class Emfile extends $CustomType {} -export const FileError$Emfile = () => new Emfile(); -export const FileError$isEmfile = (value) => value instanceof Emfile; - -/** - * Too many links. - */ -export class Emlink extends $CustomType {} -export const FileError$Emlink = () => new Emlink(); -export const FileError$isEmlink = (value) => value instanceof Emlink; - -/** - * Multihop attempted. - */ -export class Emultihop extends $CustomType {} -export const FileError$Emultihop = () => new Emultihop(); -export const FileError$isEmultihop = (value) => value instanceof Emultihop; - -/** - * Filename too long - */ -export class Enametoolong extends $CustomType {} -export const FileError$Enametoolong = () => new Enametoolong(); -export const FileError$isEnametoolong = (value) => - value instanceof Enametoolong; - -/** - * File table overflow - */ -export class Enfile extends $CustomType {} -export const FileError$Enfile = () => new Enfile(); -export const FileError$isEnfile = (value) => value instanceof Enfile; - -/** - * No buffer space available. - */ -export class Enobufs extends $CustomType {} -export const FileError$Enobufs = () => new Enobufs(); -export const FileError$isEnobufs = (value) => value instanceof Enobufs; - -/** - * No such device. - */ -export class Enodev extends $CustomType {} -export const FileError$Enodev = () => new Enodev(); -export const FileError$isEnodev = (value) => value instanceof Enodev; - -/** - * No locks available. - */ -export class Enolck extends $CustomType {} -export const FileError$Enolck = () => new Enolck(); -export const FileError$isEnolck = (value) => value instanceof Enolck; - -/** - * Link has been severed. - */ -export class Enolink extends $CustomType {} -export const FileError$Enolink = () => new Enolink(); -export const FileError$isEnolink = (value) => value instanceof Enolink; - -/** - * No such file or directory. - */ -export class Enoent extends $CustomType {} -export const FileError$Enoent = () => new Enoent(); -export const FileError$isEnoent = (value) => value instanceof Enoent; - -/** - * Not enough memory. - */ -export class Enomem extends $CustomType {} -export const FileError$Enomem = () => new Enomem(); -export const FileError$isEnomem = (value) => value instanceof Enomem; - -/** - * No space left on device. - */ -export class Enospc extends $CustomType {} -export const FileError$Enospc = () => new Enospc(); -export const FileError$isEnospc = (value) => value instanceof Enospc; - -/** - * No STREAM resources. - */ -export class Enosr extends $CustomType {} -export const FileError$Enosr = () => new Enosr(); -export const FileError$isEnosr = (value) => value instanceof Enosr; - -/** - * Not a STREAM. - */ -export class Enostr extends $CustomType {} -export const FileError$Enostr = () => new Enostr(); -export const FileError$isEnostr = (value) => value instanceof Enostr; - -/** - * Function not implemented. - */ -export class Enosys extends $CustomType {} -export const FileError$Enosys = () => new Enosys(); -export const FileError$isEnosys = (value) => value instanceof Enosys; - -/** - * Block device required. - */ -export class Enotblk extends $CustomType {} -export const FileError$Enotblk = () => new Enotblk(); -export const FileError$isEnotblk = (value) => value instanceof Enotblk; - -/** - * Not a directory. - */ -export class Enotdir extends $CustomType {} -export const FileError$Enotdir = () => new Enotdir(); -export const FileError$isEnotdir = (value) => value instanceof Enotdir; - -/** - * Operation not supported. - */ -export class Enotsup extends $CustomType {} -export const FileError$Enotsup = () => new Enotsup(); -export const FileError$isEnotsup = (value) => value instanceof Enotsup; - -/** - * No such device or address. - */ -export class Enxio extends $CustomType {} -export const FileError$Enxio = () => new Enxio(); -export const FileError$isEnxio = (value) => value instanceof Enxio; - -/** - * Operation not supported on socket. - */ -export class Eopnotsupp extends $CustomType {} -export const FileError$Eopnotsupp = () => new Eopnotsupp(); -export const FileError$isEopnotsupp = (value) => value instanceof Eopnotsupp; - -/** - * Value too large to be stored in data type. - */ -export class Eoverflow extends $CustomType {} -export const FileError$Eoverflow = () => new Eoverflow(); -export const FileError$isEoverflow = (value) => value instanceof Eoverflow; - -/** - * Not owner. - */ -export class Eperm extends $CustomType {} -export const FileError$Eperm = () => new Eperm(); -export const FileError$isEperm = (value) => value instanceof Eperm; - -/** - * Broken pipe. - */ -export class Epipe extends $CustomType {} -export const FileError$Epipe = () => new Epipe(); -export const FileError$isEpipe = (value) => value instanceof Epipe; - -/** - * Result too large. - */ -export class Erange extends $CustomType {} -export const FileError$Erange = () => new Erange(); -export const FileError$isErange = (value) => value instanceof Erange; - -/** - * Read-only file system. - */ -export class Erofs extends $CustomType {} -export const FileError$Erofs = () => new Erofs(); -export const FileError$isErofs = (value) => value instanceof Erofs; - -/** - * Invalid seek. - */ -export class Espipe extends $CustomType {} -export const FileError$Espipe = () => new Espipe(); -export const FileError$isEspipe = (value) => value instanceof Espipe; - -/** - * No such process. - */ -export class Esrch extends $CustomType {} -export const FileError$Esrch = () => new Esrch(); -export const FileError$isEsrch = (value) => value instanceof Esrch; - -/** - * Stale remote file handle. - */ -export class Estale extends $CustomType {} -export const FileError$Estale = () => new Estale(); -export const FileError$isEstale = (value) => value instanceof Estale; - -/** - * Text file busy. - */ -export class Etxtbsy extends $CustomType {} -export const FileError$Etxtbsy = () => new Etxtbsy(); -export const FileError$isEtxtbsy = (value) => value instanceof Etxtbsy; - -/** - * Cross-domain link. - */ -export class Exdev extends $CustomType {} -export const FileError$Exdev = () => new Exdev(); -export const FileError$isExdev = (value) => value instanceof Exdev; - -/** - * File was requested to be read as UTF-8, but is not UTF-8 encoded. - */ -export class NotUtf8 extends $CustomType {} -export const FileError$NotUtf8 = () => new NotUtf8(); -export const FileError$isNotUtf8 = (value) => value instanceof NotUtf8; - -/** - * Any error not accounted for by this type - */ -export class Unknown extends $CustomType { - constructor(inner) { - super(); - this.inner = inner; - } -} -export const FileError$Unknown = (inner) => new Unknown(inner); -export const FileError$isUnknown = (value) => value instanceof Unknown; -export const FileError$Unknown$inner = (value) => value.inner; -export const FileError$Unknown$0 = (value) => value.inner; - -export class FileInfo extends $CustomType { - constructor(size, mode, nlinks, inode, user_id, group_id, dev, atime_seconds, mtime_seconds, ctime_seconds) { - super(); - this.size = size; - this.mode = mode; - this.nlinks = nlinks; - this.inode = inode; - this.user_id = user_id; - this.group_id = group_id; - this.dev = dev; - this.atime_seconds = atime_seconds; - this.mtime_seconds = mtime_seconds; - this.ctime_seconds = ctime_seconds; - } -} -export const FileInfo$FileInfo = (size, mode, nlinks, inode, user_id, group_id, dev, atime_seconds, mtime_seconds, ctime_seconds) => - new FileInfo(size, - mode, - nlinks, - inode, - user_id, - group_id, - dev, - atime_seconds, - mtime_seconds, - ctime_seconds); -export const FileInfo$isFileInfo = (value) => value instanceof FileInfo; -export const FileInfo$FileInfo$size = (value) => value.size; -export const FileInfo$FileInfo$0 = (value) => value.size; -export const FileInfo$FileInfo$mode = (value) => value.mode; -export const FileInfo$FileInfo$1 = (value) => value.mode; -export const FileInfo$FileInfo$nlinks = (value) => value.nlinks; -export const FileInfo$FileInfo$2 = (value) => value.nlinks; -export const FileInfo$FileInfo$inode = (value) => value.inode; -export const FileInfo$FileInfo$3 = (value) => value.inode; -export const FileInfo$FileInfo$user_id = (value) => value.user_id; -export const FileInfo$FileInfo$4 = (value) => value.user_id; -export const FileInfo$FileInfo$group_id = (value) => value.group_id; -export const FileInfo$FileInfo$5 = (value) => value.group_id; -export const FileInfo$FileInfo$dev = (value) => value.dev; -export const FileInfo$FileInfo$6 = (value) => value.dev; -export const FileInfo$FileInfo$atime_seconds = (value) => value.atime_seconds; -export const FileInfo$FileInfo$7 = (value) => value.atime_seconds; -export const FileInfo$FileInfo$mtime_seconds = (value) => value.mtime_seconds; -export const FileInfo$FileInfo$8 = (value) => value.mtime_seconds; -export const FileInfo$FileInfo$ctime_seconds = (value) => value.ctime_seconds; -export const FileInfo$FileInfo$9 = (value) => value.ctime_seconds; - -/** - * A regular file - */ -export class File extends $CustomType {} -export const FileType$File = () => new File(); -export const FileType$isFile = (value) => value instanceof File; - -/** - * A directory - */ -export class Directory extends $CustomType {} -export const FileType$Directory = () => new Directory(); -export const FileType$isDirectory = (value) => value instanceof Directory; - -/** - * A symbolic link - */ -export class Symlink extends $CustomType {} -export const FileType$Symlink = () => new Symlink(); -export const FileType$isSymlink = (value) => value instanceof Symlink; - -/** - * Another special file type present on some systems, lika a socket or device - */ -export class Other extends $CustomType {} -export const FileType$Other = () => new Other(); -export const FileType$isOther = (value) => value instanceof Other; - -export class Read extends $CustomType {} -export const Permission$Read = () => new Read(); -export const Permission$isRead = (value) => value instanceof Read; - -export class Write extends $CustomType {} -export const Permission$Write = () => new Write(); -export const Permission$isWrite = (value) => value instanceof Write; - -export class Execute extends $CustomType {} -export const Permission$Execute = () => new Execute(); -export const Permission$isExecute = (value) => value instanceof Execute; - -export class FilePermissions extends $CustomType { - constructor(user, group, other) { - super(); - this.user = user; - this.group = group; - this.other = other; - } -} -export const FilePermissions$FilePermissions = (user, group, other) => - new FilePermissions(user, group, other); -export const FilePermissions$isFilePermissions = (value) => - value instanceof FilePermissions; -export const FilePermissions$FilePermissions$user = (value) => value.user; -export const FilePermissions$FilePermissions$0 = (value) => value.user; -export const FilePermissions$FilePermissions$group = (value) => value.group; -export const FilePermissions$FilePermissions$1 = (value) => value.group; -export const FilePermissions$FilePermissions$other = (value) => value.other; -export const FilePermissions$FilePermissions$2 = (value) => value.other; - -/** - * Convert an error into a human-readable description - * ## Example - * ```gleam - * let assert "Input/output error" = describe_error(Eio) - * ``` - */ -export function describe_error(error) { - if (error instanceof Eacces) { - return "Permission denied"; - } else if (error instanceof Eagain) { - return "Resource temporarily unavailable"; - } else if (error instanceof Ebadf) { - return "Bad file descriptor"; - } else if (error instanceof Ebadmsg) { - return "Bad message"; - } else if (error instanceof Ebusy) { - return "Resource busy"; - } else if (error instanceof Edeadlk) { - return "Resource deadlock avoided"; - } else if (error instanceof Edeadlock) { - return "Resource deadlock avoided"; - } else if (error instanceof Edquot) { - return "Disc quota exceeded"; - } else if (error instanceof Eexist) { - return "File exists"; - } else if (error instanceof Efault) { - return "Bad address"; - } else if (error instanceof Efbig) { - return "File too large"; - } else if (error instanceof Eftype) { - return "Inappropriate file type or format"; - } else if (error instanceof Eintr) { - return "Interrupted system call"; - } else if (error instanceof Einval) { - return "Invalid argument"; - } else if (error instanceof Eio) { - return "Input/output error"; - } else if (error instanceof Eisdir) { - return "Is a directory"; - } else if (error instanceof Eloop) { - return "Too many levels of symbolic links"; - } else if (error instanceof Emfile) { - return "Too many open files"; - } else if (error instanceof Emlink) { - return "Too many links"; - } else if (error instanceof Emultihop) { - return "Multihop attempted"; - } else if (error instanceof Enametoolong) { - return "File name too long"; - } else if (error instanceof Enfile) { - return "Too many open files in system"; - } else if (error instanceof Enobufs) { - return "No buffer space available"; - } else if (error instanceof Enodev) { - return "Operation not supported by device"; - } else if (error instanceof Enolck) { - return "No locks available"; - } else if (error instanceof Enolink) { - return "Link has been severed"; - } else if (error instanceof Enoent) { - return "No such file or directory"; - } else if (error instanceof Enomem) { - return "Cannot allocate memory"; - } else if (error instanceof Enospc) { - return "No space left on device"; - } else if (error instanceof Enosr) { - return "No STREAM resources"; - } else if (error instanceof Enostr) { - return "Not a STREAM"; - } else if (error instanceof Enosys) { - return "Function not implemented"; - } else if (error instanceof Enotblk) { - return "Block device required"; - } else if (error instanceof Enotdir) { - return "Not a directory"; - } else if (error instanceof Enotsup) { - return "Operation not supported"; - } else if (error instanceof Enxio) { - return "Device not configured"; - } else if (error instanceof Eopnotsupp) { - return "Operation not supported on socket"; - } else if (error instanceof Eoverflow) { - return "Value too large to be stored in data type"; - } else if (error instanceof Eperm) { - return "Operation not permitted"; - } else if (error instanceof Epipe) { - return "Broken pipe"; - } else if (error instanceof Erange) { - return "Result too large"; - } else if (error instanceof Erofs) { - return "Read-only file system"; - } else if (error instanceof Espipe) { - return "Illegal seek"; - } else if (error instanceof Esrch) { - return "No such process"; - } else if (error instanceof Estale) { - return "Stale NFS file handle"; - } else if (error instanceof Etxtbsy) { - return "Text file busy"; - } else if (error instanceof Exdev) { - return "Cross-device link"; - } else if (error instanceof NotUtf8) { - return "File not UTF-8 encoded"; - } else { - let inner = error.inner; - return "Unknown error: " + inner; - } -} - -/** - * Extract the file permissions from a given FileInfo value in their octal representation. - * - * ## Example - * ```gleam - * use info <- result.try(simplifile.file_info("src/app.gleam")) - * simplifile.file_info_permissions_octal(info) - * // --> 0o644 - * ``` - */ -export function file_info_permissions_octal(file_info) { - return $int.bitwise_and(file_info.mode, 0o777); -} - -function integer_to_permissions(integer) { - let $ = $int.bitwise_and(integer, 7); - if ($ === 7) { - return $set.from_list(toList([new Read(), new Write(), new Execute()])); - } else if ($ === 6) { - return $set.from_list(toList([new Read(), new Write()])); - } else if ($ === 5) { - return $set.from_list(toList([new Read(), new Execute()])); - } else if ($ === 3) { - return $set.from_list(toList([new Write(), new Execute()])); - } else if ($ === 4) { - return $set.from_list(toList([new Read()])); - } else if ($ === 2) { - return $set.from_list(toList([new Write()])); - } else if ($ === 1) { - return $set.from_list(toList([new Execute()])); - } else if ($ === 0) { - return $set.new$(); - } else { - throw makeError( - "panic", - FILEPATH, - "simplifile", - 674, - "integer_to_permissions", - "`panic` expression evaluated.", - {} - ) - } -} - -function octal_to_file_permissions(octal) { - return new FilePermissions( - (() => { - let _pipe = octal; - let _pipe$1 = $int.bitwise_shift_right(_pipe, 6); - return integer_to_permissions(_pipe$1); - })(), - (() => { - let _pipe = octal; - let _pipe$1 = $int.bitwise_shift_right(_pipe, 3); - return integer_to_permissions(_pipe$1); - })(), - (() => { - let _pipe = octal; - return integer_to_permissions(_pipe); - })(), - ); -} - -/** - * Extract the `FilePermissions` from a given FileInfo value. - */ -export function file_info_permissions(file_info) { - return octal_to_file_permissions(file_info_permissions_octal(file_info)); -} - -/** - * Extract the file type from a given FileInfo value. - * - * ## Example - * ```gleam - * use info <- result.try(simplifile.file_info("src/app.gleam")) - * simplifile.file_info_type(info) - * // --> simplifile.File - * ``` - */ -export function file_info_type(file_info) { - let $ = $int.bitwise_and(file_info.mode, 0o170000); - if ($ === 32768) { - return new File(); - } else if ($ === 16384) { - return new Directory(); - } else if ($ === 40960) { - return new Symlink(); - } else { - return new Other(); - } -} - -/** - * Read a files contents as a string - * ## Example - * ```gleam - * let assert Ok(records) = read(from: "./users.csv") - * ``` - */ -export function read(filepath) { - let $ = read_bits(filepath); - if ($ instanceof Ok) { - let bits = $[0]; - let $1 = $bit_array.to_string(bits); - if ($1 instanceof Ok) { - return $1; - } else { - return new Error(new NotUtf8()); - } - } else { - return $; - } -} - -/** - * Write a string to a file at the given path - * ## Example - * ```gleam - * let assert Ok(Nil) = write(to: "./hello_world.txt", contents: "Hello, World!") - * ``` - */ -export function write(filepath, contents) { - let _pipe = contents; - let _pipe$1 = $bit_array.from_string(_pipe); - return write_bits(filepath, _pipe$1); -} - -/** - * Delete all files/directories specified in a list of paths. - * Recursively deletes provided directories. - * Does not return an error if one or more of the provided paths - * do not exist. - */ -export function delete_all(loop$paths) { - while (true) { - let paths = loop$paths; - if (paths instanceof $Empty) { - return new Ok(undefined); - } else { - let path = paths.head; - let rest = paths.tail; - let $ = delete$(path); - if ($ instanceof Ok) { - loop$paths = rest; - } else { - let $1 = $[0]; - if ($1 instanceof Enoent) { - loop$paths = rest; - } else { - return $; - } - } - } - } -} - -/** - * Append a string to the contents of a file at the given path - * ## Example - * ```gleam - * let assert Ok(Nil) = append(to: "./needs_more_text.txt", contents: "more text") - * ``` - */ -export function append(filepath, contents) { - let _pipe = contents; - let _pipe$1 = $bit_array.from_string(_pipe); - return append_bits(filepath, _pipe$1); -} - -/** - * Creates an empty file at the given filepath. Returns an `Error(Eexist)` - * if the file already exists. - */ -export function create_file(filepath) { - let $ = (() => { - let _pipe = filepath; - return is_file(_pipe); - })(); - let $1 = (() => { - let _pipe = filepath; - return is_directory(_pipe); - })(); - if ($ instanceof Ok) { - let $2 = $[0]; - if ($2) { - return new Error(new Eexist()); - } else if ($1 instanceof Ok) { - let $3 = $1[0]; - if ($3) { - return new Error(new Eexist()); - } else { - return write_bits(filepath, toBitArray([])); - } - } else { - return write_bits(filepath, toBitArray([])); - } - } else if ($1 instanceof Ok) { - let $2 = $1[0]; - if ($2) { - return new Error(new Eexist()); - } else { - return write_bits(filepath, toBitArray([])); - } - } else { - return write_bits(filepath, toBitArray([])); - } -} - -/** - * Recursively creates necessary directories for a given directory - * path. Note that if you pass a path that "looks like" a file, i.e. - * `./a/b.txt`, a folder named `b.txt` will be created, so be sure - * to pass only the path to the required directory. - */ -export function create_directory_all(dirpath) { - return do_create_dir_all(dirpath + "/"); -} - -function do_copy_directory(src, dest) { - return $result.try$( - read_directory(src), - (segments) => { - let _pipe = segments; - $list.each( - _pipe, - (segment) => { - let src_path = $filepath.join(src, segment); - let dest_path = $filepath.join(dest, segment); - return $result.try$( - file_info(src_path), - (src_info) => { - let $ = file_info_type(src_info); - if ($ instanceof File) { - return $result.try$( - read_bits(src_path), - (content) => { - let _pipe$1 = content; - return write_bits(dest_path, _pipe$1); - }, - ); - } else if ($ instanceof Directory) { - return $result.try$( - create_directory(dest_path), - (_) => { return do_copy_directory(src_path, dest_path); }, - ); - } else if ($ instanceof Symlink) { - return new Error( - new Unknown( - "This is an internal bug where the `file_info` is somehow returning info about a simlink. Please file an issue on the simplifile repo.", - ), - ); - } else { - return new Error( - new Unknown( - "Unknown file type (not file, directory, or simlink)", - ), - ); - } - }, - ); - }, - ); - return new Ok(undefined); - }, - ); -} - -/** - * Copy a directory recursively - */ -export function copy_directory(src, dest) { - return $result.try$( - create_directory_all(dest), - (_) => { return do_copy_directory(src, dest); }, - ); -} - -/** - * Copy a file at a given path to another path. - * Note: destination should include the filename, not just the directory - */ -export function copy_file(src, dest) { - let _pipe = do_copy_file(src, dest); - return $result.replace(_pipe, undefined); -} - -/** - * Copy a file or a directory to a new path. Copies directories recursively. - * - * ### Performance Note - * This function does work to determine if the src path - * points to a file or a directory. Consider using one of the the dedicated - * functions `copy_file` or `copy_directory` if you already know which one you need. - */ -export function copy(src, dest) { - return $result.try$( - file_info(src), - (src_info) => { - let $ = file_info_type(src_info); - if ($ instanceof File) { - return copy_file(src, dest); - } else if ($ instanceof Directory) { - return copy_directory(src, dest); - } else if ($ instanceof Symlink) { - return new Error( - new Unknown( - "This is an internal bug where the `file_info` is somehow returning info about a simlink. Please file an issue on the simplifile repo.", - ), - ); - } else { - return new Error( - new Unknown("Unknown file type (not file, directory, or simlink)"), - ); - } - }, - ); -} - -/** - * Copy a directory recursively and then delete the old one. - */ -export function rename_directory(src, dest) { - return $result.try$( - copy_directory(src, dest), - (_) => { return delete$(src); }, - ); -} - -/** - * Clear the contents of a directory, deleting all files and directories within - * but leaving the top level directory in place. - */ -export function clear_directory(path) { - return $result.try$( - read_directory(path), - (paths) => { - let _pipe = paths; - let _pipe$1 = $list.map( - _pipe, - (_capture) => { return $filepath.join(path, _capture); }, - ); - return delete_all(_pipe$1); - }, - ); -} - -/** - * Returns a list of filepaths for every file in the directory, including nested - * files. - */ -export function get_files(directory) { - return $result.try$( - read_directory(directory), - (contents) => { - return $list.try_fold( - contents, - toList([]), - (acc, content) => { - let path = $filepath.join(directory, content); - return $result.try$( - file_info(path), - (info) => { - let $ = file_info_type(info); - if ($ instanceof File) { - return new Ok(listPrepend(path, acc)); - } else if ($ instanceof Directory) { - return $result.try$( - get_files(path), - (nested_files) => { - return new Ok($list.append(acc, nested_files)); - }, - ); - } else { - return new Ok(acc); - } - }, - ); - }, - ); - }, - ); -} - -function permission_to_integer(permission) { - if (permission instanceof Read) { - return 0o4; - } else if (permission instanceof Write) { - return 0o2; - } else { - return 0o1; - } -} - -export function file_permissions_to_octal(permissions) { - let make_permission_digit = (permissions) => { - let _pipe = permissions; - let _pipe$1 = $set.to_list(_pipe); - let _pipe$2 = $list.map(_pipe$1, permission_to_integer); - return $int.sum(_pipe$2); - }; - return (make_permission_digit(permissions.user) * 64 + make_permission_digit( - permissions.group, - ) * 8) + make_permission_digit(permissions.other); -} - -/** - * Sets the permissions for a given file - * - * # Example - * ```gleam - * let all = set.from_list([Read, Write, Execute]) - * let all = FilePermissions(user: all, group: all, other: all) - * let assert Ok(Nil) = set_permissions("./script.sh", all) - * ``` - */ -export function set_permissions(filepath, permissions) { - return set_permissions_octal(filepath, file_permissions_to_octal(permissions)); -} diff --git a/ui/javascript/simplifile/simplifile_erl.erl b/ui/javascript/simplifile/simplifile_erl.erl deleted file mode 100644 index f997758..0000000 --- a/ui/javascript/simplifile/simplifile_erl.erl +++ /dev/null @@ -1,244 +0,0 @@ -%%% -------------------------------------------------- -%%% @author Benjamin Peinhardt -%%% @doc Erlang ffi glue code for the simplifile Gleam package. -%%% @end -%%% -------------------------------------------------- - --module(simplifile_erl). - --compile({no_auto_import,[link/2]}). - -%% API --export([ - append_bits/2, - create_directory/1, - create_dir_all/1, - delete_file/1, - create_link/2, - create_symlink/2, - delete/1, - delete_directory/1, - file_info/1, - link_info/1, - is_directory/1, - is_file/1, - is_symlink/1, - read_bits/1, - read_directory/1, - rename_file/2, - set_permissions_octal/2, - write_bits/2 -]). - --include_lib("kernel/include/file.hrl"). - -%% A macro for checking whether the error returned is one of the atoms for a posixe error. --define(is_posix_error(Error), - Error =:= eacces - orelse Error =:= eagain - orelse Error =:= ebadf - orelse Error =:= ebadmsg - orelse Error =:= ebusy - orelse Error =:= edeadlk - orelse Error =:= edeadlock - orelse Error =:= edquot - orelse Error =:= eexist - orelse Error =:= efault - orelse Error =:= efbig - orelse Error =:= eftype - orelse Error =:= eintr - orelse Error =:= einval - orelse Error =:= eio - orelse Error =:= eisdir - orelse Error =:= eloop - orelse Error =:= emfile - orelse Error =:= emlink - orelse Error =:= emultihop - orelse Error =:= enametoolong - orelse Error =:= enfile - orelse Error =:= enobufs - orelse Error =:= enodev - orelse Error =:= enolck - orelse Error =:= enolink - orelse Error =:= enoent - orelse Error =:= enomem - orelse Error =:= enospc - orelse Error =:= enosr - orelse Error =:= enostr - orelse Error =:= enosys - orelse Error =:= enotblk - orelse Error =:= enotdir - orelse Error =:= enotsup - orelse Error =:= enxio - orelse Error =:= eopnotsupp - orelse Error =:= eoverflow - orelse Error =:= eperm - orelse Error =:= epipe - orelse Error =:= erange - orelse Error =:= erofs - orelse Error =:= espipe - orelse Error =:= esrch - orelse Error =:= estale - orelse Error =:= etxtbsy - orelse Error =:= exdev). - -%% Only return the error if it's a posix error. Also converts ok to {ok, nil}, -%% as gleam doesn't have atoms. -posix_result(Result) -> - case Result of - ok -> - {ok, nil}; - {ok, Value} -> - {ok, Value}; - {error, Reason} when ?is_posix_error(Reason) -> - {error, Reason}; - {error, Reason} -> - {error, {unknown, string:uppercase(atom_to_binary(Reason))}} - end. - -%% Read the binary contents of a file -read_bits(Filename) -> - posix_result(file:read_file(Filename)). - -%% Write bytes to a file -write_bits(Filename, Contents) -> - case bit_size(Contents) rem 8 of - 0 -> posix_result(file:write_file(Filename, Contents, [raw])); - _ -> {error, einval} - end. - -%% Append bytes to a file -append_bits(Filename, Contents) -> - case bit_size(Contents) rem 8 of - 0 -> posix_result(file:write_file(Filename, Contents, [append, raw])); - _ -> {error, einval} - end. - -%% Delete the file at the given path -delete_file(Filename) -> - posix_result(file:delete(Filename, [raw])). - -%% Create a directory at the given path. Missing parent directories are not created. -create_directory(Dir) -> - posix_result(file:make_dir(Dir)). - -%% Create a symbolic link New to the file or directory Existing (does not need to exist). -create_symlink(Existing, New) -> - posix_result(file:make_symlink(Existing, New)). - -%% Create a "hard link" New to the file or directory Existing. -create_link(Existing, New) -> - posix_result(file:make_link(Existing, New)). - -%% List the contents of a directory -read_directory(Dir) -> - case file:list_dir(Dir) of - {ok, Filenames} -> - {ok, [unicode:characters_to_binary(Filename) || Filename <- Filenames]}; - {error, Reason} when ?is_posix_error(Reason) -> - {error, Reason} - end. - -%% Delete a directory at the given path. Directory must be empty. -delete_directory(Dir) -> - posix_result(file:del_dir(Dir)). - -%% Deletes a file/directory and everything in it. -delete(Dir) -> - posix_result(file:del_dir_r(Dir)). - -%% Creates the entire path for a given directory to exist -create_dir_all(Filename) -> - posix_result(filelib:ensure_path(Filename)). - -%% Move file from one path to another -rename_file(Source, Destination) -> - posix_result(file:rename(Source, Destination)). - -%% Set the permissions for the given file. -set_permissions_octal(Filename, Permissions) -> - posix_result(file:change_mode(Filename, Permissions)). - -is_directory(Path) -> - case file:read_file_info(Path) of - {ok, FileInfo} -> - case FileInfo#file_info.type of - directory -> - {ok, true}; - _ -> - {ok, false} - end; - {error, enoent} -> - {ok, false}; - {error, Reason} -> - posix_result({error, Reason}) - end. - -is_file(Path) -> - case file:read_file_info(Path) of - {ok, FileInfo} -> - case FileInfo#file_info.type of - regular -> - {ok, true}; - _ -> - {ok, false} - end; - {error, enoent} -> - {ok, false}; - {error, Reason} -> - posix_result({error, Reason}) - end. - -is_symlink(Path) -> - case file:read_link_info(Path) of - {ok, FileInfo} -> - case FileInfo#file_info.type of - symlink -> - {ok, true}; - _ -> - {ok, false} - end; - {error, enoent} -> - {ok, false}; - {error, Reason} -> - posix_result({error, Reason}) - end. - -file_info_result(Result) -> - case Result of - {ok, - {file_info, - Size, - _Type, - _Access, - Atime, - Mtime, - Ctime, - Mode, - Links, - MajorDevice, - _MinorDevice, - Inode, - Uid, - Gid}} -> - {ok, - {file_info, - Size, - Mode, - Links, - Inode, - Uid, - Gid, - MajorDevice, - Atime, - Mtime, - Ctime}}; - {error, Reason} when ?is_posix_error(Reason) -> - Result - end. - -file_info(Filename) -> - file_info_result(file:read_file_info(Filename, [{time, posix}])). - -link_info(Filename) -> - file_info_result(file:read_link_info(Filename, [{time, posix}])). diff --git a/ui/javascript/simplifile/simplifile_js.mjs b/ui/javascript/simplifile/simplifile_js.mjs deleted file mode 100644 index 6b82923..0000000 --- a/ui/javascript/simplifile/simplifile_js.mjs +++ /dev/null @@ -1,412 +0,0 @@ -// @ts-check - -import fs from "node:fs"; -import path from "node:path"; -import process from "node:process"; -import { BitArray, Ok, Error as GError, toList } from "./gleam.mjs"; -import * as $simplifile from "./simplifile.mjs"; - -/** - * Read the contents of a file as a BitArray - * - * @param {string} filepath - * @returns {Ok | GError} A Result with the BitArray of the file contents - */ -export function readBits(filepath) { - return gleamResult(() => { - const contents = fs.readFileSync(path.normalize(filepath)); - return new BitArray(new Uint8Array(contents)); - }); -} - -/** - * Write the given BitArray to a file - * - * @param {string} filepath - * @param {BitArray} contents - * @returns {Ok | GError} - */ -export function writeBits(filepath, contents) { - return gleamResult(() => - fs.writeFileSync(path.normalize(filepath), toUint8Array(contents)) - ); -} - -/** - * Append the given BitArray to a file - * - * @param {string} filepath - * @param {BitArray} contents - * @returns {Ok | GError} - */ -export function appendBits(filepath, contents) { - return gleamResult(() => - fs.appendFileSync(path.normalize(filepath), toUint8Array(contents)) - ); -} - -/** - * Returns a BitArray as an aligned Uint8Array. Avoids a copy when possible. - * - * @param {BitArray} contents - * @returns Uint8Array - */ -function toUint8Array(contents) { - if (contents.bitSize % 8 !== 0) { - throw new GError(new $simplifile.Einval()); - } - - let buffer = contents.rawBuffer; - if (contents.bitOffset !== 0) { - buffer = new Uint8Array(contents.byteSize); - for (let i = 0; i < buffer.length; i++) { - buffer[i] = contents.byteAt(i); - } - } - - return buffer; -} - -/** - * Check whether a file exists at the given path - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function isFile(filepath) { - try { - return new Ok(fs.statSync(path.normalize(filepath)).isFile()); - } catch (e) { - if (e.code === "ENOENT") { - return new Ok(false); - } else { - return new GError(cast_error(e.code)); - } - } -} - -/** - * Check whether a symbolic link exists at the given path - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function isSymlink(filepath) { - try { - return new Ok(fs.lstatSync(path.normalize(filepath)).isSymbolicLink()); - } catch (e) { - if (e.code === "ENOENT") { - return new Ok(false); - } else { - return new GError(cast_error(e.code)); - } - } -} - -/** - * Check whether a directory exists at the given path - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function isDirectory(filepath) { - try { - return new Ok(fs.statSync(path.normalize(filepath)).isDirectory()); - } catch (e) { - if (e.code === "ENOENT") { - return new Ok(false); - } else { - return new GError(cast_error(e.code)); - } - } -} - -/** - * Create the symbolic link called path pointing to target - * - * @param {string} target - * @param {string} path - * @returns {Ok | GError} - */ -export function createSymlink(target, path) { - return gleamResult(() => fs.symlinkSync(target, path)); -} - -/** - * Create the "hard link" called path pointing to the target - * - * @param {string} target - * @param {string} path - * returns {ok | GError} - */ -export function createLink(target, path) { - return gleamResult(() => fs.linkSync(target, path)); -} - -/** - * Create a directory at the given filepath - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function createDirectory(filepath) { - return gleamResult(() => fs.mkdirSync(path.normalize(filepath))); -} - -/** - * Recursively create a directory structure from the given path. - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function createDirAll(filepath) { - return gleamResult(() => { - fs.mkdirSync(path.normalize(filepath), { recursive: true }); - }); -} - -/** - * Recursively delete a directory or delete a file at the given path. - * - * @param {string} fileOrDirPath - * @returns {Ok | GError} - */ -export function delete_(fileOrDirPath) { - return gleamResult(() => { - const isDir = isDirectory(fileOrDirPath); - if (isDir instanceof Ok && isDir[0] === true) { - fs.rmSync(path.normalize(fileOrDirPath), { recursive: true }); - } else { - fs.unlinkSync(path.normalize(fileOrDirPath)); - } - }); -} - -/** - * Specifically delete a single file. - * - * @param {string} filePath - * @returns {Ok | GError} - */ -export function deleteFile(filePath) { - return gleamResult(() => { - fs.unlinkSync(path.normalize(filePath)); - }) -} - -/** - * List the contents of a directory. - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function readDirectory(filepath) { - return gleamResult(() => toList(fs.readdirSync(path.normalize(filepath)))); -} - -/** - * Copy a file to a new path. - * - * @param {string} srcpath - * @param {string} destpath - * @returns {Ok | GError} - */ -export function copyFile(srcpath, destpath) { - return gleamResult(() => - fs.copyFileSync(path.normalize(srcpath), path.normalize(destpath)), - ); -} - -/** - * Move a file to the new path. - * - * @param {string} srcpath - * @param {string} destpath - * @returns {Ok | GError} - */ -export function renameFile(srcpath, destpath) { - return gleamResult(() => - fs.renameSync(path.normalize(srcpath), path.normalize(destpath)), - ); -} - -/** - * Set the file permissions. Octal number should be in base 8. - * - * @param {string} filepath - * @param {number} octalNumber - * @returns {Ok | GError} - */ -export function setPermissionsOctal(filepath, octalNumber) { - return gleamResult(() => fs.chmodSync(path.normalize(filepath), octalNumber)); -} - -/** - * Return the current directory. - * - * @returns {Ok | GError} The current directory - */ -export function currentDirectory() { - return gleamResult(() => process.cwd()); -} - -/** - * - * @param {string} filepath - * @returns {Ok | GError} - */ -export function fileInfo(filepath) { - return gleamResult(() => { - const stat = fs.statSync(path.normalize(filepath)); - return new FileInfo(stat); - }); -} - -/** - * @param {string} filepath - * @returns {Ok | GError} - */ -export function linkInfo(filepath) { - return gleamResult(() => { - const stat = fs.lstatSync(path.normalize(filepath)); - return new FileInfo(stat); - }); -} - -class FileInfo { - /** - * @param {fs.Stats} stat - */ - constructor(stat) { - this.size = stat.size; - this.mode = stat.mode; - this.nlinks = stat.nlink; - this.inode = stat.ino; - this.user_id = stat.uid; - this.group_id = stat.gid; - this.dev = stat.dev; - this.atime_seconds = Math.floor(stat.atimeMs / 1000); - this.mtime_seconds = Math.floor(stat.mtimeMs / 1000); - this.ctime_seconds = Math.floor(stat.ctimeMs / 1000); - } -} - -/** - * Perform some operation and return a Gleam `Result(a, String)` - * where `a` is the type returned by the operation and the `String` - * is the error code. - * - * @param {function():any} op - * @returns {Ok | GError} - */ -function gleamResult(op) { - try { - const val = op(); - return new Ok(val); - } catch (e) { - return new GError(cast_error(e.code)); - } -} - -function cast_error(error_code) { - switch (error_code) { - case "EACCES": - return new $simplifile.Eacces(); - case "EAGAIN": - return new $simplifile.Eagain(); - case "EBADF": - return new $simplifile.Ebadf(); - case "EBADMSG": - return new $simplifile.Ebadmsg(); - case "EBUSY": - return new $simplifile.Ebusy(); - case "EDEADLK": - return new $simplifile.Edeadlk(); - case "EDEADLOCK": - return new $simplifile.Edeadlock(); - case "EDQUOT": - return new $simplifile.Edquot(); - case "EEXIST": - return new $simplifile.Eexist(); - case "EFAULT": - return new $simplifile.Efault(); - case "EFBIG": - return new $simplifile.Efbig(); - case "EFTYPE": - return new $simplifile.Eftype(); - case "EINTR": - return new $simplifile.Eintr(); - case "EINVAL": - return new $simplifile.Einval(); - case "EIO": - return new $simplifile.Eio(); - case "EISDIR": - return new $simplifile.Eisdir(); - case "ELOOP": - return new $simplifile.Eloop(); - case "EMFILE": - return new $simplifile.Emfile(); - case "EMLINK": - return new $simplifile.Emlink(); - case "EMULTIHOP": - return new $simplifile.Emultihop(); - case "ENAMETOOLONG": - return new $simplifile.Enametoolong(); - case "ENFILE": - return new $simplifile.Enfile(); - case "ENOBUFS": - return new $simplifile.Enobufs(); - case "ENODEV": - return new $simplifile.Enodev(); - case "ENOLCK": - return new $simplifile.Enolck(); - case "ENOLINK": - return new $simplifile.Enolink(); - case "ENOENT": - return new $simplifile.Enoent(); - case "ENOMEM": - return new $simplifile.Enomem(); - case "ENOSPC": - return new $simplifile.Enospc(); - case "ENOSR": - return new $simplifile.Enosr(); - case "ENOSTR": - return new $simplifile.Enostr(); - case "ENOSYS": - return new $simplifile.Enosys(); - case "ENOBLK": - return new $simplifile.Enotblk(); - case "ENOTDIR": - return new $simplifile.Enotdir(); - case "ENOTSUP": - return new $simplifile.Enotsup(); - case "ENXIO": - return new $simplifile.Enxio(); - case "EOPNOTSUPP": - return new $simplifile.Eopnotsupp(); - case "EOVERFLOW": - return new $simplifile.Eoverflow(); - case "EPERM": - return new $simplifile.Eperm(); - case "EPIPE": - return new $simplifile.Epipe(); - case "ERANGE": - return new $simplifile.Erange(); - case "EROFS": - return new $simplifile.Erofs(); - case "ESPIPE": - return new $simplifile.Espipe(); - case "ESRCH": - return new $simplifile.Esrch(); - case "ESTALE": - return new $simplifile.Estale(); - case "ETXTBSY": - return new $simplifile.Etxtbsy(); - case "EXDEV": - return new $simplifile.Exdev(); - case "NOTUTF8": - return new $simplifile.NotUtf8(); - default: - return new $simplifile.Unknown(error_code); - } -} diff --git a/ui/main.js b/ui/main.js deleted file mode 100644 index 308b596..0000000 --- a/ui/main.js +++ /dev/null @@ -1,34 +0,0 @@ -import { testing } from "./javascript/markdown2/markdown2.mjs"; - -let data = JSON.parse( - testing("#1 heading #- !1 important !- @2 true @- >3 quote >- "), -); -let output = ""; -let hirachy = []; -let marking = []; -let quote = []; -let truth = []; -for (var i = 0; i < data.length; i++) { - let item = data[i]; - //{type: 'marking', value: 2} - // console.log(item); - if (item.type == "text") { - let markingvalue = marking.at(-1) ?? 0; - console.log(markingvalue); - output = - output + - `

` + - item.value + - "

"; - } - if (item.type == "marking") { - marking.push(item.value); - } - if (item.type == "pop") { - marking.pop(); - } - // console.log(output); -} -document.addEventListener("DOMContentLoaded", () => { - document.getElementById("text").innerHTML = output; -});