X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/ecf679353a1fb5fde431eca37c70515b64eb3d05..6e6d4e3261c1c943fe44fa9e381bcf8bf1441fd6:/string.js diff --git a/string.js b/string.js index 8c858cd..eb6f6fb 100644 --- a/string.js +++ b/string.js @@ -1,7 +1,7 @@ // ♓🌟 Piscēs ∷ string.js // ==================================================================== // -// Copyright © 2022 Lady [@ Lady’s Computer]. +// Copyright © 2022–2023 Lady [@ Lady’s Computer]. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -10,10 +10,12 @@ import { bind, call, identity, makeCallable } from "./function.js"; import { defineOwnProperties, + getOwnPropertyDescriptors, getPrototype, objectCreate, setPrototype, } from "./object.js"; +import { type } from "./value.js"; export const { /** @@ -33,6 +35,8 @@ export const { const { exec: reExec, toString: reToString } = rePrototype; const getDotAll = Object.getOwnPropertyDescriptor(rePrototype, "dotAll").get; + const getFlags = + Object.getOwnPropertyDescriptor(rePrototype, "flags").get; const getGlobal = Object.getOwnPropertyDescriptor(rePrototype, "global").get; const getHasIndices = @@ -65,11 +69,11 @@ export const { * A name for the matcher may be provided as the second argument. * * A callable constraint on acceptable inputs may be provided as a - * third argument. If provided, it will be called with two + * third argument. If provided, it will be called with three * arguments whenever a match appears successful: first, the string - * being matched, and second, the Matcher object itself. If the - * return value of this call is falsey, then the match will be - * considered a failure. + * being matched, second, the match result, and third, the Matcher + * object itself. If the return value of this call is falsey, then + * the match will be considered a failure. * * ☡ If the provided source regular expression uses nongreedy * quantifiers, it may not match the whole string even if a match @@ -89,8 +93,9 @@ export const { // at a match matches the whole string and passes the // provided constraint (if present). regExp.lastIndex = 0; - return call(reExec, regExp, [$])?.[0] === $ && - (constraint === null || constraint($, this)); + const result = call(reExec, regExp, [$]); + return result?.[0] === $ && + (constraint === null || constraint($, result, this)); } }, ); @@ -148,6 +153,10 @@ export const { * * Matchers only match if they can match the entire value on the * first attempt. + * + * ☡ The match result returned by this method will be the same as + * that passed to the constraint function—and may have been + * modified by said function prior to being returned. */ exec($) { const regExp = this.#regExp; @@ -157,7 +166,7 @@ export const { const result = call(reExec, regExp, [string]); if ( result?.[0] === string && - (constraint === null || constraint(string, this)) + (constraint === null || constraint(string, result, this)) ) { // The entire string was matched and the constraint, if // present, returned a truthy value. @@ -169,6 +178,16 @@ export const { } } + /** + * Gets the flags present on this Matcher. + * + * ※ This needs to be defined because the internal RegExp object + * may have flags which are not yet recognized by ♓🌟 Piscēs. + */ + get flags() { + return call(getFlags, this.#regExp, []); + } + /** Gets whether the global flag is present on this Matcher. */ get global() { return call(getGlobal, this.#regExp, []); @@ -208,12 +227,25 @@ export const { return call(getUnicode, this.#regExp, []); } }; - const matcherPrototype = setPrototype( - Matcher.prototype, - rePrototype, + + const matcherConstructor = defineOwnProperties( + class extends RegExp { + constructor(...args) { + return new Matcher(...args); + } + }, + { + name: { value: "Matcher" }, + length: { value: 1 }, + }, + ); + const matcherPrototype = defineOwnProperties( + matcherConstructor.prototype, + getOwnPropertyDescriptors(Matcher.prototype), + { constructor: { value: matcherConstructor } }, ); - return { Matcher }; + return { Matcher: matcherConstructor }; })(); export const {