diff --git a/docs/functions.md b/docs/functions.md index 6fc1433b..540da1f2 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -1,26 +1,34 @@ -## BoolExtension -### fn **`bool_and`**(_bool_ **`a`**, _bool_ **`b`**) → _bool_ +## Stdlib\TypeExtensions\BoolTypeExtension +### fn **`and`**(_bool_ **`a`**, _bool_ **`b`**) → _bool_ Returns result of logical `AND` between two boolean values. ```js true.and(false) == false true.and(true) == true -bool_and(true, false) == false +bool.and(true, false) == false ``` --- -### fn **`bool_not`**(_bool_ **`value`**) → _bool_ +### fn **`execute`**() + + array Dict array containing Primi +function/method object that represent type/class methods. + +--- +### fn **`not`**(_bool_ **`value`**) → _bool_ Returns a negation (logical `NOT`) of a single boolean value. ```js false.not() == true -bool_not(true) == false +true.not() == false +bool.not(false) == true +bool.not(true) == false ``` --- -### fn **`bool_or`**(_bool_ **`a`**, _bool_ **`b`**) → _bool_ +### fn **`or`**(_bool_ **`a`**, _bool_ **`b`**) → _bool_ Returns an `OR` of two boolean values. @@ -30,14 +38,14 @@ true.or(false) == true false.or(true) == true false.or(false) == false -bool_or(true, true) == true -bool_or(true, false) == true -bool_or(false, true) == true -bool_or(false, false) == false +bool.or(true, true) == true +bool.or(true, false) == true +bool.or(false, true) == true +bool.or(false, false) == false ``` --- -### fn **`bool_xor`**(_bool_ **`a`**, _bool_ **`b`**) → _bool_ +### fn **`xor`**(_bool_ **`a`**, _bool_ **`b`**) → _bool_ Returns an exclusive `OR` (`XOR`) of two boolean values. @@ -47,167 +55,15 @@ true.xor(false) == true false.xor(true) == true false.xor(false) == false -bool_xor(true, true) == false -bool_xor(true, false) == true -bool_xor(false, true) == true -bool_xor(false, false) == false -``` - ---- -## CastingExtension -### fn **`to_bool`**(_any_ **`value`**) → _bool_ - -Returns a new `bool` value based on argument's truthness. - -```js -to_bool(true) == true -to_bool(false) == false -to_bool(-1) == true -to_bool(0) == false -to_bool([]) == false -to_bool(['']) == true -to_bool('') == false -to_bool(' ') == true -to_bool('0') == true -to_bool('1') == true -``` - ---- -### fn **`to_dict`**(_any_ **`value`**) → _dict_ - -Returns a new dict containing items of some iterable value. - -```js -a_list = 'máj'.to_dict() -a_list == {0: 'm', 1: 'á', 2: 'j'} - -b_list = {'a': 1, 'b': 2, 'c': []}.to_list() -b_list = [1, 2, []] - -c_list = {'a': 1, 'b': 2, 'c': []}.keys().to_list() -c_list = ['a', 'b', 'c'] -``` - ---- -### fn **`to_list`**(_any_ **`value`**) → _list_ - -Returns a new `list` containing items of some iterable value. - -```js -a_list = 'první máj'.to_list() -a_list == ["p", "r", "v", "n", "í", " ", "m", "á", "j"] - -b_list = {'a': 1, 'b': 2, 'c': []}.to_list() -b_list = [1, 2, []] - -c_list = {'a': 1, 'b': 2, 'c': []}.keys().to_list() -c_list = ['a', 'b', 'c'] -``` - ---- -### fn **`to_number`**(_any_ **`value`**) → _number_ - -Cast a `number|string|bool` value to `number`. - -```js -to_number(1) == 1 -to_number('123') == 123 -to_number('+123') == 123 -to_number('-123') == -123 -to_number(' +123.001 ') == 123.001 -to_number(' -123.00 ') == -123.0 - -to_number(true) == 1 -to_number(false) == 0 -to_number(fal) == 0 -``` - ---- -### fn **`to_regex`**(_any_ **`value`**, *[_bool_ **`escape`**]*) → _regex_ - -Convert `string` to a `regex` value. If the optional `escape` argument -is `true`, the any characters with special regex meaning will be -escaped so that they are meant literally. - -```js -"hello".to_regex() == rx"hello" -to_regex("Why so serious...?", true) == rx"Why so serious\.\.\.\?" -``` - ---- -### fn **`to_string`**(_any_ **`value`**) → _string_ - -Return a `string` representation of value. - -```js -to_string(true) == 'true' -to_string([]) == '[]' -to_string(3.14) == '3.14' -{'a': 1, 'b': 'c'}.to_string() == '{"a": 1, "b": "c"}' -"hello there!".to_string() == "hello there!" -to_string(to_string) == "" +bool.xor(true, true) == false +bool.xor(true, false) == true +bool.xor(false, true) == true +bool.xor(false, false) == false ``` --- -## CliExtension -### fn **`debugger`**() → _any_ - -_**Only in [CLI](https://w.wiki/QPE)**_. - -Injects a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) -session for debugging at the specified line. - - - - ---- -### fn **`get_traceback`**() → _list_ - -_**Only in [CLI](https://w.wiki/QPE)**_. - -Return traceback as a list. - - - - ---- -### fn **`memory_get_peak_usage`**() → _number_ - -_**Only in [CLI](https://w.wiki/QPE)**_. - -Returns memory peak usage used by Primi _(engine behind the scenes)_ in -bytes. - ---- -### fn **`memory_get_usage`**() → _number_ - -_**Only in [CLI](https://w.wiki/QPE)**_. - -Returns current memory usage used by Primi _(engine behind the scenes)_ -in bytes. - ---- -### fn **`print`**(*[_any_ **`value`**]*, *[_bool_ **`nl`**]*) → _null_ - -_**Only in [CLI](https://w.wiki/QPE)**_. - -Prints value to standard output. - ---- -## DatetimeExtension -### fn **`time_monotonic`**() → _number_ - -Returns high-resolution monotonic time. It is an arbitrary number that -keeps increasing by 1 every second. - ---- -### fn **`time_unix`**() → _number_ - -Returns high-resolution UNIX time. - ---- -## DictExtension -### fn **`dict_copy`**(_dict_ **`dict`**) → _dict_ +## Stdlib\TypeExtensions\DictTypeExtension +### fn **`copy`**(_dict_ **`dict`**) → _dict_ Returns a new shallow copy of this dict. @@ -221,7 +77,13 @@ b_dict == {'a': 1, 100: 'nope'} ``` --- -### fn **`dict_get`**(_dict_ **`dict`**, _any_ **`key`**, *[_any_ **`default`**]*) → _any_ +### fn **`execute`**() + + array Dict array containing Primi +function/method object that represent type/class methods. + +--- +### fn **`get`**(_dict_ **`dict`**, ___undefined___ **`key`**, *[___undefined___ **`default`**]*) → ___undefined___ Returns value stored under `key`, if it in dict, otherwise returns the value of the `default` argument, which is `null` by default, but can @@ -236,7 +98,7 @@ d.get('100', ['one', 'hundred']) == ['one', 'hundred'] ``` --- -### fn **`dict_has_key`**(_dict_ **`dict`**, _any_ **`key`**) → _bool_ +### fn **`has_key`**(_dict_ **`dict`**, ___undefined___ **`key`**) → _bool_ Returns `true` if the key exists in dict. Return `false` otherwise. @@ -249,7 +111,7 @@ d.has_key('yes') == false ``` --- -### fn **`dict_has_value`**(_dict_ **`dict`**, _any_ **`needle`**) → _bool_ +### fn **`has_value`**(_dict_ **`dict`**, ___undefined___ **`needle`**) → _bool_ Returns `true` if the value exists in dict. Return `false` otherwise. @@ -262,7 +124,17 @@ d.has_value(false) == false ``` --- -### fn **`dict_keys`**(_dict_ **`dict`**) → _list_ +### fn **`items`**(_dict_ **`dict`**) → _list_ + +Returns a new `list` of `tuples` of **key and value pairs** from this +`dict`. + +```js +{'a': 1, 100: 'yes'}.items() == [('a', 1), (100: 'yes')] +``` + +--- +### fn **`keys`**(_dict_ **`dict`**) → _list_ Returns a new `list` containing **keys** from this `dict`. @@ -271,7 +143,7 @@ Returns a new `list` containing **keys** from this `dict`. ``` --- -### fn **`dict_map`**(_dict_ **`dict`**, _function_ **`fn`**) → _dict_ +### fn **`map`**() → _dict_ Returns a new dict with same keys but values returned by a passed function _(callback)_ applied to each item. @@ -284,19 +156,8 @@ fn = (v, k) => { return k + "|" + v; } a_dict.map(fn) == {"key_a": "key_a|val_a", "key_b": "key_b|val_b"} ``` - - ---- -### fn **`dict_reverse`**(_dict_ **`dict`**) → _any_ - -Returns a new `dict` with original `dict`'s items in reversed order. - -```js -{'a': 1, 100: 'yes'}.reverse() == {100: 'yes', 'a': 1} -``` - --- -### fn **`dict_values`**(_dict_ **`dict`**) → _list_ +### fn **`values`**(_dict_ **`dict`**) → _list_ Returns a new `list` containing **values** from this `dict`. @@ -305,31 +166,15 @@ Returns a new `list` containing **values** from this `dict`. ``` --- -## HashExtension -### fn **`hash_md5`**(_string_ **`val`**) → _string_ - -Return [`md5` hash](https://en.wikipedia.org/wiki/MD5) representation -of a `string` value as `string`. - -```js -hash_md5('hello') == '5d41402abc4b2a76b9719d911017c592' -hash_md5('123') == '202cb962ac59075b964b07152d234b70' -``` - ---- -### fn **`hash_sha256`**(_string_ **`val`**) → _string_ - -Return [`sha256` hash](https://en.wikipedia.org/wiki/SHA-2) representation -of a `string` value as `string`. +## Stdlib\TypeExtensions\ForbiddenTypeExtension +### fn **`execute`**() -```js -hash_sha256('hello') == '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824' -hash_sha256('123') == 'a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3' -``` + array Dict array containing Primi +function/method object that represent type/class methods. --- -## ListExtension -### fn **`list_contains`**(_list_ **`list`**, _any_ **`needle`**) → _bool_ +## Stdlib\TypeExtensions\ListTypeExtension +### fn **`contains`**(_list_ **`list`**, ___undefined___ **`needle`**) → _bool_ Returns `true` if the `needle` is present in the `list` at least once. @@ -346,12 +191,12 @@ Returns `true` if the `needle` is present in the `list` at least once. ``` --- -### fn **`list_copy`**(_list_ **`list`**) → _list_ +### fn **`copy`**(_list_ **`list`**) → _list_ Returns a new copy of the `list`. --- -### fn **`list_count`**(_list_ **`list`**, _any_ **`needle`**) → _number_ +### fn **`count`**(_list_ **`list`**, ___undefined___ **`needle`**) → _number_ Returns number of occurrences of some value in the `list`. @@ -368,7 +213,13 @@ Returns number of occurrences of some value in the `list`. ``` --- -### fn **`list_get`**(_list_ **`list`**, _number_ **`index`**, *[_any_ **`default`**]*) → _any_ +### fn **`execute`**() + + array Dict array containing Primi +function/method object that represent type/class methods. + +--- +### fn **`get`**(_list_ **`list`**, _number_ **`index`**, *[___undefined___ **`default`**]*) → ___undefined___ Returns an item from `list` by its index _(starting at 0)_. Negative indexes can be used to get items from the end. @@ -393,7 +244,7 @@ by default)_ ``` --- -### fn **`list_map`**(_list_ **`list`**, _function_ **`fn`**) → _list_ +### fn **`map`**() → _list_ Returns a new `list` from results of a passed function _(callback)_ applied to each item. @@ -404,10 +255,8 @@ Callback arguments: `callback(value)`. [-1, 0, 2].map(to_bool) == [true, false, true] ``` - - --- -### fn **`list_pop`**(_list_ **`list`**, *[_number_ **`index`**]*) → _any_ +### fn **`pop`**(_list_ **`list`**, *[_number_ **`index`**]*) → ___undefined___ Remove (pop) item at specified `index` from the `list` and return it. @@ -423,7 +272,7 @@ a_list.pop(-3) == 1 // a_list == [3, 4], 1 is returned ``` --- -### fn **`list_prepend`**(_list_ **`list`**, _any_ **`value`**) → _null_ +### fn **`prepend`**(_list_ **`list`**, ___undefined___ **`value`**) → _null_ Prepend an item to the beginning of the `list`. @@ -434,7 +283,7 @@ a_list == [{'some_key': 'some_value'}, 'a', 'b', 'c'] ``` --- -### fn **`list_push`**(_list_ **`list`**, _any_ **`value`**) → _null_ +### fn **`push`**(_list_ **`list`**, ___undefined___ **`value`**) → _null_ Add (push) an item to the end of the `list`. @@ -445,7 +294,7 @@ a_list == ['a', 'b', 'c', {'some_key': 'some_value'}] ``` --- -### fn **`list_random`**(_list_ **`list`**) → _any_ +### fn **`random`**(_list_ **`list`**) → ___undefined___ Returns a random item from the `list`. @@ -454,7 +303,7 @@ Returns a random item from the `list`. ``` --- -### fn **`list_reverse`**(_list_ **`list`**) → _list_ +### fn **`reverse`**(_list_ **`list`**) → _list_ Returns a new `list` with values of the original `list` reversed. @@ -463,7 +312,7 @@ Returns a new `list` with values of the original `list` reversed. ``` --- -### fn **`list_shuffle`**(_list_ **`list`**) → _list_ +### fn **`shuffle`**(_list_ **`list`**) → _list_ Returns a new `list` with shuffled items. @@ -472,141 +321,79 @@ Returns a new `list` with shuffled items. ``` --- -## NumberExtension -### fn **`number_abs`**(_number_ **`n`**) → _number_ - -Returns the absolute value of number `n`. - ---- -### fn **`number_atan`**(_number_ **`n`**) → _number_ - -Returns the arc tangent of number `n` specified in radians. - ---- -### fn **`number_ceil`**(_number_ **`n`**) → _number_ +## Stdlib\TypeExtensions\NullTypeExtension +### fn **`execute`**() -Returns number `n` rounded up. + array Dict array containing Primi +function/method object that represent type/class methods. --- -### fn **`number_cos`**(_number_ **`n`**) → _number_ +## Stdlib\TypeExtensions\NumberTypeExtension +### fn **`execute`**() -Returns the cosine of number `n` specified in radians. + array Dict array containing Primi +function/method object that represent type/class methods. --- -### fn **`number_divisible_by`**(_number_ **`a`**, _number_ **`b`**) → _bool_ +### fn **`is_divisible_by`**(_number_ **`a`**, _number_ **`b`**) → _bool_ Return `true` if first argument is divisible by the second argument. --- -### fn **`number_floor`**(_number_ **`n`**) → _number_ - -Returns number `n` rounded down. - ---- -### fn **`number_mod`**(_number_ **`a`**, _number_ **`b`**) → _number_ - -Returns the remainder (modulo) of the division of the arguments. - ---- -### fn **`number_pow`**(_number_ **`n`**, *[_number_ **`power`**]*) → _number_ - -Returns number `n` squared to the power of `power`. - ---- -### fn **`number_round`**(_number_ **`n`**, *[_number_ **`precision`**]*) → _number_ - -Returns number `n` rounded to specified `precision`. If the -precision is not specified, a default `precision` of zero is used. - ---- -### fn **`number_sin`**(_number_ **`n`**) → _number_ +## Stdlib\TypeExtensions\ObjectTypeExtension +### fn **`execute`**() -Returns the sine of number `n` specified in radians. + array Dict array containing Primi +function/method object that represent type/class methods. --- -### fn **`number_sqrt`**(_number_ **`n`**) → _number_ +## Stdlib\TypeExtensions\RegexTypeExtension +### fn **`execute`**() -Returns the square root of a number `n`. + array Dict array containing Primi +function/method object that represent type/class methods. --- -### fn **`number_tan`**(_number_ **`n`**) → _number_ +### fn **`find`**(_regex_ **`regex`**, _string_ **`haystack`**) → _string|bool_ -Returns the tangent of number `n` specified in radians. - ---- -## RegexExtension -### fn **`regex_match`**(_regex_ **`regex`**, _string_ **`haystack`**) → _any_ - -Regular expression match. Returns the first matching string. Otherwise -returns `false`. +Regular expression find. Returns the first occurence of matching string. +Otherwise returns `false`. ```js -rx"[xyz]+".match("abbcxxyzzdeef") == "xxyzz" +rx"[xyz]+".find("abbcxxyzzdeef") == "xxyzz" ``` --- -## StandardExtension -### fn **`assert`**(_bool_ **`assumption`**, *[_string_ **`description`**]*) → _bool_ - -This function returns `true` if a `bool` value passed into it is `true` -and throws error if it's `false`. Optional `string` description can be -provided, which will be visible in the eventual error message. - ---- -### fn **`len`**(_any_ **`value`**) → _number_ +## Stdlib\TypeExtensions\StringTypeExtension +### fn **`contains`**(_string_ **`haystack`**, ___undefined___ **`needle`**) → _bool_ -Returns length of a value. - -```js -"hello, Česká Třebová".len() == 20 -len(123456) == 6 -[1, 2, 3].len() == 3 -len({'a': 1, 'b': 'c'}) == 2 -``` - ---- -### fn **`range`**(_number_ **`start`**, *[_number_ **`end`**]*, *[_number_ **`step`**]*) → _list_ - -Return a list containing numbers from `start` to `end` _(including)_. -If the `end` is not specified, numbers from `0` to the value of the -first argument `start` is returned. Optional third argument `step` can -be specified for steps other than `1`. +Returns `true` if the `string` contains `needle`. Returns `false` +otherwise. ```js -range(0) == [0] -range(1) == [0, 1] -range(5) == [0, 1, 2, 3, 4, 5] -range(2, 7) == [2, 3, 4, 5, 6, 7] -range(2, -7) == [2, 1, 0, -1, -2, -3, -4, -5, -6, -7] -range(2, -7, 3) == [2, -1, -4, -7] -range(5, 10, 3) == [5, 8] // The last number that could be obtained by incrementing 3 is 8. +"this is a sentence".contains("sen") == true +"this is a sentence".contains("yay") == false ``` --- -### fn **`type`**(_any_ **`value`**) → _string_ +### fn **`ends_with`**(_string_ **`haystack`**, _string_ **`needle`**) → _bool_ -Return type of value as string. +Returns `true` if the string ends with specified string suffix. +Returns `false` otherwise. ```js -type(true) == 'bool' -type("hello") == 'string' -type(type) == 'function' +"this is a sentence".ends_with("tence") == true +"this is a sentence".ends_with("e") == true +"this is a sentence".ends_with("x") == false ``` --- -## StringExtension -### fn **`string_contains`**(_string_ **`haystack`**, _any_ **`needle`**) → _bool_ - -Returns `true` if the `string` contains `needle`. Returns `false` -otherwise. +### fn **`execute`**() -```js -"this is a sentence".contains("sen") == true -"this is a sentence".contains("yay") == false -``` +_Missing description._ --- -### fn **`string_find_first`**(_string_ **`haystack`**, _any_ **`needle`**) → _any_ +### fn **`find_first`**(_string_ **`haystack`**, ___undefined___ **`needle`**) → ___undefined___ Returns the position _(index)_ of **first** occurrence of `needle` in the `string`. If the `needle` was not found, `null` is returned. @@ -618,7 +405,7 @@ the `string`. If the `needle` was not found, `null` is returned. ``` --- -### fn **`string_find_last`**(_string_ **`haystack`**, _any_ **`needle`**) → _any_ +### fn **`find_last`**(_string_ **`haystack`**, ___undefined___ **`needle`**) → ___undefined___ Returns the position _(index)_ of **last** occurrence of `needle` in the `string`. If the `needle` was not found, `null` is returned. @@ -630,7 +417,7 @@ the `string`. If the `needle` was not found, `null` is returned. ``` --- -### fn **`string_format`**(_string_ **`str`**, *[_any_ **`items`**]*) → _string_ +### fn **`format`**(_string_ **`str`**, *[___undefined___ **`items`**]*) → _string_ Returns a new `string` with placeholders from the original `string` replaced by additional arguments. @@ -645,7 +432,7 @@ Placeholders can be either _(but these can't be combined)_: ``` --- -### fn **`string_join`**(_string_ **`string`**, _any_ **`iterable`**) → _string_ +### fn **`join`**(_string_ **`string`**, ___undefined___ **`iterable`**) → _string_ Join items from `iterable` with this `string` and return the result as a new string. @@ -657,7 +444,7 @@ a new string. ``` --- -### fn **`string_number_of`**(_string_ **`haystack`**, _any_ **`needle`**) → _number_ +### fn **`number_of`**(_string_ **`haystack`**, ___undefined___ **`needle`**) → _number_ Returns `number` of occurrences of `needle` in a string. @@ -667,22 +454,18 @@ Returns `number` of occurrences of `needle` in a string. ``` --- -### fn **`string_replace`**(_string_ **`string`**, _any_ **`search`**, *[_string_ **`replace`**]*) → _string_ +### fn **`replace`**(_string_ **`string`**, ___undefined___ **`search`**, _string_ **`replace`**) → _string_ Perform search and replace and return the results as new `string`. -Two separate modes of operation: -1. The needle `search` is a `string` and haystack `replace` is a string. -2. The needle `search` is a `dict` defining search-and-replace pairs -_(and `replace` argument is omitted)_. - ```js "abcdef".replace("c", "X") == "abXdef" -"abcdef".replace({"c": "X", "e": "Y"}) == "abXdYf" +"přítmí ve městě za dvě stě".replace("stě", "šci") == "přítmí ve měšci za dvě šci" +"přítmí ve městě za dvě stě".replace(rx"\wt\w", "lol") == "přlolí ve mělol za dvě lol" ``` --- -### fn **`string_reverse`**(_string_ **`string`**) → _string_ +### fn **`reverse`**(_string_ **`string`**) → _string_ Return reversed string. @@ -691,7 +474,7 @@ Return reversed string. ``` --- -### fn **`string_shuffle`**(_string_ **`str`**) → _string_ +### fn **`shuffle`**(_string_ **`str`**) → _string_ Returns a new `string` from shuffled characters of the original `string`. @@ -700,7 +483,7 @@ Returns a new `string` from shuffled characters of the original `string`. ``` --- -### fn **`string_split`**(_string_ **`string`**, *[_any_ **`delimiter`**]*) → _list_ +### fn **`split`**() → _list_ Split original `string` by some `delimiter` and return result the as a `list`. If the `delimiter` is not specified, the `string` is splat by @@ -712,3 +495,60 @@ whitespace characters. ``` --- +### fn **`starts_with`**(_string_ **`haystack`**, _string_ **`needle`**) → _bool_ + +Returns `true` if the string starts with specified string. +Returns `false` otherwise. + +```js +"this is a sentence".starts_with("this") == true +"this is a sentence".starts_with("t") == true +"this is a sentence".starts_with("x") == false +``` + +--- +### fn **`substring`**(_string_ **`string`**, _number_ **`offset`**, *[_number_ **`length`**]*) → _string_ + +Returns a substring taken from `string` starting at `offset` with length `length`. +Access outside of bounds will not result in errors. +Length can be omitted to reach up to the `string` end. +Negative offset can be used. + +```js +"this is a sentence".substring(5, 4) == "is a" +"this is a sentence".substring(5) == "is a sentence" +"this is a sentence".substring(10, 100) == "sentence" +"this is a sentence".substring(-8) == "sentence" +"this is a sentence".substring(20, 15) == "" +``` + +--- +### fn **`translate`**(_string_ **`string`**, _dict_ **`pairs`**) → _string_ + +Search and replace strings within a string and return the new resulting +string. The from-to pairs are to be provided as a `dict`. + +```js +"abcdef".replace({'c': 'X', 'e': 'Y'}) == "abXdYf" +"abcdef".replace({'b': 'X', 'ab': 'Y'}) == "Ycdef" +``` + +The longest keys will be tried first. Once a substring has been replaced, +its new value will not be searched again. This behavior is identical +to PHP function [`strtr()`](https://www.php.net/manual/en/function.strtr.php). + +--- +## Stdlib\TypeExtensions\TupleTypeExtension +### fn **`execute`**() + + array Dict array containing Primi +function/method object that represent type/class methods. + +--- +## Stdlib\TypeExtensions\TypeTypeExtension +### fn **`execute`**() + + array Dict array containing Primi +function/method object that represent type/class methods. + +--- diff --git a/src/Helpers/StringEscaping.php b/src/Helpers/StringEscaping.php index 27f7fb80..0fbbd33a 100644 --- a/src/Helpers/StringEscaping.php +++ b/src/Helpers/StringEscaping.php @@ -79,7 +79,7 @@ public static function unescapeString(string $str): string { */ public static function escapeString( string $str, - string $quoteChar = \null + ?string $quoteChar = \null ): string { foreach (self::ESCAPE_PAIRS as $out => $in) { diff --git a/src/Repl.php b/src/Repl.php index 679e1422..997cb1e4 100644 --- a/src/Repl.php +++ b/src/Repl.php @@ -63,7 +63,7 @@ class Repl { public function __construct( ?string $replName = null, - ReplIoDriverInterface $driver = null + ?ReplIoDriverInterface $driver = null ) { self::$historyFilePath = getenv("HOME") . '/' . self::HISTORY_FILE; diff --git a/src/Stdlib/Modules/std/math.primi.php b/src/Stdlib/Modules/std/math.primi.php index 05a5a5ee..2589a062 100644 --- a/src/Stdlib/Modules/std/math.primi.php +++ b/src/Stdlib/Modules/std/math.primi.php @@ -122,7 +122,7 @@ public static function atan(NumberValue $n): NumberValue { #[PrimiFunc] public static function round( NumberValue $n, - NumberValue $precision = \null + ?NumberValue $precision = \null ): NumberValue { return Interned::number((string) \round( (float) $n->value, diff --git a/src/Stdlib/TypeExtensions/BoolTypeExtension.php b/src/Stdlib/TypeExtensions/BoolTypeExtension.php index ca94b649..98317439 100644 --- a/src/Stdlib/TypeExtensions/BoolTypeExtension.php +++ b/src/Stdlib/TypeExtensions/BoolTypeExtension.php @@ -52,7 +52,7 @@ public static function not(BoolValue $value): BoolValue { * ```js * true.and(false) == false * true.and(true) == true - * bool_and(true, false) == false + * bool.and(true, false) == false * ``` */ #[PrimiFunc] @@ -69,10 +69,10 @@ public static function and(BoolValue $a, BoolValue $b): BoolValue { * false.or(true) == true * false.or(false) == false * - * bool_or(true, true) == true - * bool_or(true, false) == true - * bool_or(false, true) == true - * bool_or(false, false) == false + * bool.or(true, true) == true + * bool.or(true, false) == true + * bool.or(false, true) == true + * bool.or(false, false) == false * ``` */ #[PrimiFunc] @@ -89,10 +89,10 @@ public static function or(BoolValue $a, BoolValue $b): BoolValue { * false.xor(true) == true * false.xor(false) == false * - * bool_xor(true, true) == false - * bool_xor(true, false) == true - * bool_xor(false, true) == true - * bool_xor(false, false) == false + * bool.xor(true, true) == false + * bool.xor(true, false) == true + * bool.xor(false, true) == true + * bool.xor(false, false) == false * ``` */ #[PrimiFunc] diff --git a/src/Stdlib/TypeExtensions/ListTypeExtension.php b/src/Stdlib/TypeExtensions/ListTypeExtension.php index 83e5a671..32218aa8 100644 --- a/src/Stdlib/TypeExtensions/ListTypeExtension.php +++ b/src/Stdlib/TypeExtensions/ListTypeExtension.php @@ -206,7 +206,7 @@ public static function contains( public static function get( ListValue $list, NumberValue $index, - AbstractValue $default = \null + ?AbstractValue $default = \null ): AbstractValue { // If the index is not found, this will return null. diff --git a/src/Stdlib/TypeExtensions/StringTypeExtension.php b/src/Stdlib/TypeExtensions/StringTypeExtension.php index a2dffc8b..c0d5fe80 100644 --- a/src/Stdlib/TypeExtensions/StringTypeExtension.php +++ b/src/Stdlib/TypeExtensions/StringTypeExtension.php @@ -482,10 +482,11 @@ public static function join( /** * Returns `true` if the string starts with specified string. - * + * Returns `false` otherwise. + * * ```js - * "this is a sentence".starts_with("tence") == true - * "this is a sentence".starts_with("e") == true + * "this is a sentence".starts_with("this") == true + * "this is a sentence".starts_with("t") == true * "this is a sentence".starts_with("x") == false * ``` */ @@ -499,7 +500,8 @@ public static function starts_with( /** * Returns `true` if the string ends with specified string suffix. - * + * Returns `false` otherwise. + * * ```js * "this is a sentence".ends_with("tence") == true * "this is a sentence".ends_with("e") == true @@ -514,4 +516,35 @@ public static function ends_with( return Interned::bool(\str_ends_with($haystack->value, $needle->value)); } + /** + * Returns a substring taken from `string` starting at `offset` with length `length`. + * Access outside of bounds will be silently tolerated. + * Length can be omitted to reach up to the `string` end. + * Negative offset can be used. + * + * ```js + * "this is a sentence".substring(5, 4) == "is a" + * "this is a sentence".substring(5) == "is a sentence" + * "this is a sentence".substring(10, 100) == "sentence" + * "this is a sentence".substring(-8) == "sentence" + * "this is a sentence".substring(20, 15) == "" + * ``` + */ + #[PrimiFunc] + public static function substring( + StringValue $string, + NumberValue $offset, + ?NumberValue $length = \null, + ): StringValue { + $input = $string->value; + $start = $offset->value ?? 0; + $len = $length?->value ?? \mb_strlen($input); + + if ($start < 0) { + $start = \mb_strlen($input) + $start; + } + + return new StringValue(\mb_substr($input, (int)$start, (int)$len)); + } + } diff --git a/tools/docgen/docgen.php b/tools/docgen/docgen.php index 40976a30..d56ed177 100644 --- a/tools/docgen/docgen.php +++ b/tools/docgen/docgen.php @@ -64,7 +64,7 @@ function err($text): void { function get_relevant_methods(string $className): array { - $classRef = new \ReflectionClass("\Smuuf\Primi\Stdlib\\Extensions\\{$className}"); + $classRef = new \ReflectionClass("\Smuuf\Primi\\{$className}"); // We want methods that are both public AND static AND non-PHP-magic. return array_filter( @@ -146,7 +146,7 @@ function extract_params(\ReflectionMethod $methodRef): array { line(Colors::get("- File {cyan}$filepath{_}")); $filename = basename($filepath); - $className = substr($filename, 0, strrpos($filename, '.')); + $className = str_replace("/", "\\", substr($filepath, 6, strrpos($filepath, '.') - 6)); $methods = get_relevant_methods($className); $data[$className] = []; @@ -168,7 +168,16 @@ function extract_params(\ReflectionMethod $methodRef): array { $returnType = false; if ($returnTypeRef = $methodRef->getReturnType()) { try { - $returnType = ($returnTypeRef->getName())::TYPE; + $returnType = match (true) { + $returnTypeRef instanceof ReflectionUnionType => implode( + "|", + array_map( + fn(ReflectionNamedType $type) => $type->getName()::TYPE, + $returnTypeRef->getTypes(), + ), + ), + default => ($returnTypeRef->getName())::TYPE, + }; } catch (\Throwable $e) { warn("Class '$className, method '$methodName', referencing non-existent Primi type having class " . $returnTypeRef->getName()); }