mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin: add more documentation (#13160)
This commit is contained in:
parent
4660220f4c
commit
9329b6c8c8
@ -1,10 +1,12 @@
|
||||
## Description:
|
||||
|
||||
`builtin` is a module that is implicitly imported by every V program.
|
||||
|
||||
It implements the builtin V types `array`, `string`, `map`.
|
||||
|
||||
It also implements builtin functions like `println`, `eprintln`, `malloc`,
|
||||
`panic`, `print_backtrace`.
|
||||
|
||||
The autogenerated documentation for builtin functions is lacking,
|
||||
so for these functions, please refer to the
|
||||
The autogenerated documentation for `builtin` functions is lacking, so for these
|
||||
functions, please refer to the
|
||||
[official V documentation](https://github.com/vlang/v/blob/master/doc/docs.md).
|
||||
|
@ -5,7 +5,7 @@ module builtin
|
||||
|
||||
import strings
|
||||
|
||||
// `array` is a struct, used for denoting all array types in V.
|
||||
// array is a struct, used for denoting all array types in V.
|
||||
// `.data` is a void pointer to the backing heap memory block,
|
||||
// which avoids using generics and thus without generating extra
|
||||
// code for every type.
|
||||
@ -112,7 +112,9 @@ fn new_array_from_c_array_no_alloc(len int, cap int, elm_size int, c_array voidp
|
||||
return arr
|
||||
}
|
||||
|
||||
// Private function. Doubles array capacity if needed.
|
||||
// Private function. Increases the `cap` of an array to the
|
||||
// required value by copying the data to a new memory location
|
||||
// (creating a clone) unless `a.cap` is already large enough.
|
||||
fn (mut a array) ensure_cap(required int) {
|
||||
if required <= a.cap {
|
||||
return
|
||||
@ -139,15 +141,17 @@ fn (mut a array) ensure_cap(required int) {
|
||||
|
||||
// repeat returns a new array with the given array elements repeated given times.
|
||||
// `cgen` will replace this with an apropriate call to `repeat_to_depth()`
|
||||
|
||||
//
|
||||
// This is a dummy placeholder that will be overridden by `cgen` with an appropriate
|
||||
// call to `repeat_to_depth()`. However the `checker` needs it here.
|
||||
pub fn (a array) repeat(count int) array {
|
||||
return unsafe { a.repeat_to_depth(count, 0) }
|
||||
}
|
||||
|
||||
// version of `repeat()` that handles multi dimensional arrays
|
||||
// `unsafe` to call directly because `depth` is not checked
|
||||
// repeat_to_depth is an unsafe version of `repeat()` that handles
|
||||
// multi-dimensional arrays.
|
||||
//
|
||||
// It is `unsafe` to call directly because `depth` is not checked
|
||||
[unsafe]
|
||||
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||
if count < 0 {
|
||||
@ -176,16 +180,24 @@ pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||
return arr
|
||||
}
|
||||
|
||||
// sort_with_compare sorts array in-place using given `compare` function as comparator.
|
||||
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
|
||||
$if freestanding {
|
||||
panic('sort does not work with -freestanding')
|
||||
} $else {
|
||||
unsafe { vqsort(a.data, usize(a.len), usize(a.element_size), callback) }
|
||||
}
|
||||
}
|
||||
|
||||
// insert inserts a value in the array at index `i`
|
||||
// insert inserts a value in the array at index `i` and increases
|
||||
// the index of subsequent elements by 1.
|
||||
//
|
||||
// This function is type-aware and can insert items of the same
|
||||
// or lower dimensionality as the original array. That is, if
|
||||
// the original array is `[]int`, then the insert `val` may be
|
||||
// `int` or `[]int`. If the original array is `[][]int`, then `val`
|
||||
// may be `[]int` or `[][]int`. Consider the examples.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// mut a := [1, 2, 4]
|
||||
// a.insert(2, 3) // a now is [1, 2, 3, 4]
|
||||
// mut b := [3, 4]
|
||||
// b.insert(0, [1, 2]) // b now is [1, 2, 3, 4]
|
||||
// mut c := [[3, 4]]
|
||||
// c.insert(0, [1, 2]) // c now is [[1, 2], [3, 4]]
|
||||
// ```
|
||||
pub fn (mut a array) insert(i int, val voidptr) {
|
||||
$if !no_bounds_checking ? {
|
||||
if i < 0 || i > a.len {
|
||||
@ -200,7 +212,9 @@ pub fn (mut a array) insert(i int, val voidptr) {
|
||||
a.len++
|
||||
}
|
||||
|
||||
// insert_many inserts many values into the array from index `i`.
|
||||
// insert_many inserts many values into the array beginning at `i`.
|
||||
// NOTE: `array.insert()` already handles inserting multiple values
|
||||
// use that unless you know you need to use this.
|
||||
[unsafe]
|
||||
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||
$if !no_bounds_checking ? {
|
||||
@ -218,23 +232,58 @@ pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||
a.len += size
|
||||
}
|
||||
|
||||
// prepend prepends one value to the array.
|
||||
// prepend prepends one or more elements to an array.
|
||||
// Just like `.insert`, `.prepend` can take a single element
|
||||
// or an array of elements of the same type as the original list.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// mut a := []int{}
|
||||
// a.prepend(1) // a == [1]
|
||||
// mut b := [3, 4]
|
||||
// b.prepend([1, 2]) // b == [1, 2, 3, 4]
|
||||
//
|
||||
pub fn (mut a array) prepend(val voidptr) {
|
||||
a.insert(0, val)
|
||||
}
|
||||
|
||||
// prepend_many prepends another array to this array.
|
||||
// NOTE: `.prepend` is probably all you need.
|
||||
// NOTE: This code is never called in all of vlib
|
||||
[unsafe]
|
||||
pub fn (mut a array) prepend_many(val voidptr, size int) {
|
||||
unsafe { a.insert_many(0, val, size) }
|
||||
}
|
||||
|
||||
// delete deletes array element at index `i`.
|
||||
// This is exactly the same as calling `.delete_many(i, 1)`.
|
||||
// NOTE: This function does NOT operate in-place. Internally, it
|
||||
// creates a copy of the array, skipping over the element at `i`,
|
||||
// and then points the original variable to the new memory location.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// mut a := ['0', '1', '2', '3', '4', '5']
|
||||
// a.delete(1) // a is now ['0', '2', '3', '4', '5']
|
||||
// ```
|
||||
pub fn (mut a array) delete(i int) {
|
||||
a.delete_many(i, 1)
|
||||
}
|
||||
|
||||
// delete_many deletes `size` elements beginning with index `i`
|
||||
// NOTE: This function does NOT operate in-place. Internally, it
|
||||
// creates a copy of the array, skipping over `size` elements
|
||||
// starting at `i`, and then points the original variable
|
||||
// to the new memory location.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
// b := a[..9] // creates a `slice` of `a`, not a clone
|
||||
// a.delete_many(4, 3) // replaces `a` with a modified clone
|
||||
// dump(a) // a: [1, 2, 3, 4, 8, 9] // `a` is now different
|
||||
// dump(b) // b: [1, 2, 3, 4, 5, 6, 7, 8, 9] // `b` is still the same
|
||||
// ```
|
||||
pub fn (mut a array) delete_many(i int, size int) {
|
||||
$if !no_bounds_checking ? {
|
||||
if i < 0 || i + size > a.len {
|
||||
@ -263,12 +312,15 @@ pub fn (mut a array) delete_many(i int, size int) {
|
||||
}
|
||||
|
||||
// clear clears the array without deallocating the allocated data.
|
||||
// It does it by setting the array length to `0`
|
||||
// Example: a.clear() // `a.len` is now 0
|
||||
pub fn (mut a array) clear() {
|
||||
a.len = 0
|
||||
}
|
||||
|
||||
// trim trims the array length to "index" without modifying the allocated data. If "index" is greater
|
||||
// than len nothing will be changed.
|
||||
// trim trims the array length to `index` without modifying the allocated data.
|
||||
// If `index` is greater than `len` nothing will be changed.
|
||||
// Example: a.trim(3) // `a.len` is now <= 3
|
||||
pub fn (mut a array) trim(index int) {
|
||||
if index < a.len {
|
||||
a.len = index
|
||||
@ -305,7 +357,10 @@ fn (a array) get_with_check(i int) voidptr {
|
||||
}
|
||||
}
|
||||
|
||||
// first returns the first element of the array.
|
||||
// first returns the first element of the `array`.
|
||||
// If the `array` is empty, this will panic.
|
||||
// However, `a[0]` returns an error object
|
||||
// so it can be handled with an `or` block.
|
||||
pub fn (a array) first() voidptr {
|
||||
$if !no_bounds_checking ? {
|
||||
if a.len == 0 {
|
||||
@ -315,7 +370,8 @@ pub fn (a array) first() voidptr {
|
||||
return a.data
|
||||
}
|
||||
|
||||
// last returns the last element of the array.
|
||||
// last returns the last element of the `array`.
|
||||
// If the `array` is empty, this will panic.
|
||||
pub fn (a array) last() voidptr {
|
||||
$if !no_bounds_checking ? {
|
||||
if a.len == 0 {
|
||||
@ -328,6 +384,20 @@ pub fn (a array) last() voidptr {
|
||||
}
|
||||
|
||||
// pop returns the last element of the array, and removes it.
|
||||
// If the `array` is empty, this will panic.
|
||||
// NOTE: this function reduces the length of the given array,
|
||||
// but arrays sliced from this one will not change. They still
|
||||
// retain their "view" of the underlying memory.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
// b := a[..9] // creates a "view" into the same memory
|
||||
// c := a.pop() // c == 9
|
||||
// a[1] = 5
|
||||
// dump(a) // a: [1, 5, 3, 4, 5, 6, 7, 8]
|
||||
// dump(b) // b: [1, 5, 3, 4, 5, 6, 7, 8, 9]
|
||||
// ```
|
||||
pub fn (mut a array) pop() voidptr {
|
||||
// in a sense, this is the opposite of `a << x`
|
||||
$if !no_bounds_checking ? {
|
||||
@ -344,6 +414,8 @@ pub fn (mut a array) pop() voidptr {
|
||||
}
|
||||
|
||||
// delete_last efficiently deletes the last element of the array.
|
||||
// It does it simply by reducing the length of the array by 1.
|
||||
// If the array is empty, this will panic.
|
||||
pub fn (mut a array) delete_last() {
|
||||
// copy pasting code for performance
|
||||
$if !no_bounds_checking ? {
|
||||
@ -358,6 +430,11 @@ pub fn (mut a array) delete_last() {
|
||||
// but starting from the `start` element and ending with the element before
|
||||
// the `end` element of the original array with the length and capacity
|
||||
// set to the number of the elements in the slice.
|
||||
// It will remain tied to the same memory location until the length increases
|
||||
// (copy on grow) or `.clone()` is called on it.
|
||||
// If `start` and `end` are invalid this function will panic.
|
||||
// Alternative: Slices can also be made with [start..end] notation
|
||||
// Alternative: `.slice_ni()` will always return an array.
|
||||
fn (a array) slice(start int, _end int) array {
|
||||
mut end := _end
|
||||
$if !no_bounds_checking ? {
|
||||
@ -441,7 +518,7 @@ fn (a array) slice2(start int, _end int, end_max bool) array {
|
||||
return a.slice(start, end)
|
||||
}
|
||||
|
||||
// `clone_static_to_depth()` returns an independent copy of a given array.
|
||||
// clone_static_to_depth() returns an independent copy of a given array.
|
||||
// Unlike `clone_to_depth()` it has a value receiver and is used internally
|
||||
// for slice-clone expressions like `a[2..4].clone()` and in -autofree generated code.
|
||||
fn (a array) clone_static_to_depth(depth int) array {
|
||||
@ -562,7 +639,6 @@ pub fn (a array) reverse() array {
|
||||
return arr
|
||||
}
|
||||
|
||||
// pub fn (a []int) free() {
|
||||
// free frees all memory occupied by the array.
|
||||
[unsafe]
|
||||
pub fn (a &array) free() {
|
||||
@ -576,29 +652,105 @@ pub fn (a &array) free() {
|
||||
unsafe { free(mblock_ptr) }
|
||||
}
|
||||
|
||||
// filter creates a new array with all elements that pass the test implemented by the provided function
|
||||
// Some of the following functions have no implementation in V and exist here
|
||||
// to expose them to the array namespace. Their implementation is compiler
|
||||
// specific because of their use of `it` and `a < b` expressions.
|
||||
// Therefore, the implementation is left to the backend.
|
||||
|
||||
// filter creates a new array with all elements that pass the test.
|
||||
// Ignore the function signature. `filter` does not take an actual callback. Rather, it
|
||||
// takes an `it` expression.
|
||||
//
|
||||
// Example: array.filter(it % 2 == 1) // will yield a new array of only odd elements
|
||||
pub fn (a array) filter(predicate fn (voidptr) bool) array
|
||||
|
||||
// any tests whether at least one element in the array passes the test implemented by the
|
||||
// provided function. It returns true if, in the array, it finds an element for which the provided
|
||||
// function returns true; otherwise it returns false. It doesn't modify the array
|
||||
// any tests whether at least one element in the array passes the test.
|
||||
// Ignore the function signature. `any` does not take an actual callback. Rather, it
|
||||
// takes an `it` expression.
|
||||
// It returns `true` if it finds an element passing the test. Otherwise,
|
||||
// it returns `false`. It doesn't modify the array.
|
||||
//
|
||||
// Example: array.any(it % 2 == 1) // will return true if any element is odd
|
||||
pub fn (a array) any(predicate fn (voidptr) bool) bool
|
||||
|
||||
// all tests whether all elements in the array pass the test implemented by the provided function
|
||||
// all tests whether all elements in the array pass the test
|
||||
// Ignore the function signature. `all` does not take an actual callback. Rather, it
|
||||
// takes an `it` expression.
|
||||
// It returns `false` if any element fails the test. Otherwise,
|
||||
// it returns `true`. It doesn't modify the array.
|
||||
//
|
||||
// Example: array.all(it % 2 == 1) // will return true if every element is odd
|
||||
pub fn (a array) all(predicate fn (voidptr) bool) bool
|
||||
|
||||
// map creates a new array populated with the results of calling a provided function
|
||||
// on every element in the calling array
|
||||
pub fn (a array) map(callback fn (voidptr) voidptr) array
|
||||
|
||||
// sort sorts an array in place in ascending order.
|
||||
// sort sorts an array in place.
|
||||
// Ignore the function signature. Passing a callback to `.sort` is not supported
|
||||
// for now. Consider using the `.sort_with_compare` method if you need it.
|
||||
//
|
||||
// Instead, a very simple syntax is available to you for custom sorting and more.
|
||||
//
|
||||
// Certain array functions (`filter` `any` `all` and `sort`) support a simplified
|
||||
// domain-specific-language by the backend compiler to make these operations
|
||||
// more idiomatic to V. These functions are described here, but their implementation
|
||||
// is compiler specific.
|
||||
//
|
||||
// Each function takes a boolean test expression as its single argument.
|
||||
// These test expressions may use certain 'magic' variables depending on their context:
|
||||
// - `sort` may use `a` and `b` as pointers to two elements
|
||||
// giving you direct access to those objects
|
||||
// - `filter`, `any`, and `all` may use `it` as a pointer to a single element at a time.
|
||||
//
|
||||
// Example: array.sort() // will sort the array in ascending order
|
||||
// Example: array.sort(b < a) // will sort the array in decending order
|
||||
// Example: array.sort(b.name < a.name) // will sort descending by the .name field
|
||||
// Example: array.filter(it % 2 == 1) // will yield a new array of only odd elements
|
||||
// Example: array.any(it.name == 'Bob') // will yield `true` if any element has `.name == 'Bob'`
|
||||
pub fn (mut a array) sort(callback fn (voidptr, voidptr) int)
|
||||
|
||||
// contains determines whether an array includes a certain value among its entries
|
||||
pub fn (a array) contains(val voidptr) bool
|
||||
// sort_with_compare sorts array in-place using the results of the
|
||||
// given function to determine sort order.
|
||||
//
|
||||
// The function should return one of three values:
|
||||
// - `-1` when `a` should come before `b` ( `a < b` )
|
||||
// - `1` when `b` should come before `a` ( `b < a` )
|
||||
// - `0` when the order cannot be determined ( `a == b` )
|
||||
//
|
||||
// ### Example:
|
||||
// ```v
|
||||
// fn main() {
|
||||
// mut a := ['hi', '1', '5', '3']
|
||||
// a.sort_with_compare(fn (a &string, b &string) int {
|
||||
// if a < b {
|
||||
// return -1
|
||||
// }
|
||||
// if a > b {
|
||||
// return 1
|
||||
// }
|
||||
// return 0
|
||||
// })
|
||||
// assert a == ['1', '3', '5', 'hi']
|
||||
// }
|
||||
// ```
|
||||
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
|
||||
$if freestanding {
|
||||
panic('sort does not work with -freestanding')
|
||||
} $else {
|
||||
unsafe { vqsort(a.data, usize(a.len), usize(a.element_size), callback) }
|
||||
}
|
||||
}
|
||||
|
||||
// contains determines whether an array includes a certain value among its elements
|
||||
// It will return `true` if the array contains an element with this value.
|
||||
// It is similar to `.any` but does not take an `it` expression.
|
||||
//
|
||||
// Example: [1, 2, 3].contains(4) == false
|
||||
pub fn (a array) contains(value voidptr) bool
|
||||
|
||||
// index returns the first index at which a given element can be found in the array
|
||||
// or -1 if the value is not found.
|
||||
// or `-1` if the value is not found.
|
||||
pub fn (a array) index(value voidptr) int
|
||||
|
||||
[unsafe]
|
||||
@ -612,8 +764,11 @@ pub fn (mut a []string) free() {
|
||||
unsafe { (&array(&a)).free() }
|
||||
}
|
||||
|
||||
// str returns a string representation of the array of strings
|
||||
// => '["a", "b", "c"]'.
|
||||
// The following functions are type-specific functions that apply
|
||||
// to arrays of different types in different ways.
|
||||
|
||||
// str returns a string representation of an array of strings
|
||||
// Example: ['a', 'b', 'c'].str() // => "['a', 'b', 'c']".
|
||||
[manualfree]
|
||||
pub fn (a []string) str() string {
|
||||
mut sb_len := 4 // 2x" + 1x, + 1xspace
|
||||
@ -666,6 +821,7 @@ pub fn (b []byte) hex() string {
|
||||
// copy copies the `src` byte array elements to the `dst` byte array.
|
||||
// The number of the elements copied is the minimum of the length of both arrays.
|
||||
// Returns the number of elements copied.
|
||||
// NOTE: This is not an `array` method. It is a function that takes two arrays of bytes.
|
||||
// TODO: implement for all types
|
||||
pub fn copy(dst []byte, src []byte) int {
|
||||
min := if dst.len < src.len { dst.len } else { src.len }
|
||||
@ -677,6 +833,7 @@ pub fn copy(dst []byte, src []byte) int {
|
||||
|
||||
// reduce executes a given reducer function on each element of the array,
|
||||
// resulting in a single output value.
|
||||
// NOTE: It exists as a method on `[]int` types only
|
||||
pub fn (a []int) reduce(iter fn (int, int) int, accum_start int) int {
|
||||
mut accum_ := accum_start
|
||||
for i in a {
|
||||
@ -686,11 +843,16 @@ pub fn (a []int) reduce(iter fn (int, int) int, accum_start int) int {
|
||||
}
|
||||
|
||||
// grow_cap grows the array's capacity by `amount` elements.
|
||||
// Internally, it does this by copying the entire array to
|
||||
// a new memory location (creating a clone).
|
||||
pub fn (mut a array) grow_cap(amount int) {
|
||||
a.ensure_cap(a.cap + amount)
|
||||
}
|
||||
|
||||
// grow_len ensures that an array has a.len + amount of length
|
||||
// Internally, it does this by copying the entire array to
|
||||
// a new memory location (creating a clone) unless the array.cap
|
||||
// is already large enough.
|
||||
[unsafe]
|
||||
pub fn (mut a array) grow_len(amount int) {
|
||||
a.ensure_cap(a.len + amount)
|
||||
@ -708,7 +870,8 @@ pub fn (a array) pointers() []voidptr {
|
||||
return res
|
||||
}
|
||||
|
||||
// voidptr.vbytes() - makes a V []byte structure from a C style memory buffer. NB: the data is reused, NOT copied!
|
||||
// vbytes on`voidptr` makes a V []byte structure from a C style memory buffer.
|
||||
// NOTE: the data is reused, NOT copied!
|
||||
[unsafe]
|
||||
pub fn (data voidptr) vbytes(len int) []byte {
|
||||
res := array{
|
||||
@ -720,7 +883,8 @@ pub fn (data voidptr) vbytes(len int) []byte {
|
||||
return res
|
||||
}
|
||||
|
||||
// byteptr.vbytes() - makes a V []byte structure from a C style memory buffer. NB: the data is reused, NOT copied!
|
||||
// vbytes on `&byte` makes a V []byte structure from a C style memory buffer.
|
||||
// NOTE: the data is reused, NOT copied!
|
||||
[unsafe]
|
||||
pub fn (data &byte) vbytes(len int) []byte {
|
||||
return unsafe { voidptr(data).vbytes(len) }
|
||||
|
@ -843,6 +843,20 @@ fn test_sort() {
|
||||
assert users[2].name == 'Peter'
|
||||
}
|
||||
|
||||
fn test_sort_with_compare() {
|
||||
mut a := ['hi', '1', '5', '3']
|
||||
a.sort_with_compare(fn (a &string, b &string) int {
|
||||
if a < b {
|
||||
return -1
|
||||
}
|
||||
if a > b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
assert a == ['1', '3', '5', 'hi']
|
||||
}
|
||||
|
||||
fn test_rune_sort() {
|
||||
mut bs := [`f`, `e`, `d`, `b`, `c`, `a`]
|
||||
bs.sort()
|
||||
|
@ -539,7 +539,7 @@ pub fn (s string) u64() u64 {
|
||||
return strconv.common_parse_uint(s, 0, 64, false, false) or { 0 }
|
||||
}
|
||||
|
||||
// `parse_int` interprets a string s in the given base (0, 2 to 36) and
|
||||
// parse_int interprets a string s in the given base (0, 2 to 36) and
|
||||
// bit size (0 to 64) and returns the corresponding value i.
|
||||
//
|
||||
// If the base argument is 0, the true base is implied by the string's
|
||||
@ -560,7 +560,7 @@ pub fn (s string) parse_uint(_base int, _bit_size int) ?u64 {
|
||||
return strconv.parse_uint(s, _base, _bit_size)
|
||||
}
|
||||
|
||||
// `parse_uint` is like `parse_int` but for unsigned numbers
|
||||
// parse_uint is like `parse_int` but for unsigned numbers
|
||||
//
|
||||
// This method directly exposes the `parse_int` function from `strconv`
|
||||
// as a method on `string`. For more advanced features,
|
||||
|
@ -1,3 +1,6 @@
|
||||
## Description:
|
||||
|
||||
`strings` provides utilities for efficiently processing large strings.
|
||||
|
||||
If you got here looking for methods available on the `string` struct, those
|
||||
methods are found in the `builtin` module.
|
||||
|
Loading…
Reference in New Issue
Block a user