diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f97e72530d..53fafe29b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,16 @@ name: CI -on: [push, pull_request] -jobs: +on: + push: + paths-ignore: + - "doc/**" + - "CHANGELOG.md" + pull_request: + paths-ignore: + - "doc/**" + - "CHANGELOG.md" + +jobs: code-formatting: runs-on: ubuntu-18.04 env: @@ -461,15 +470,6 @@ jobs: # - name: v2 self compilation # run: .\v.exe -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v - docs-line-len-check: - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Build - run: make - - name: Check docs line length - run: ./v run cmd/tools/check-md.v doc/docs.md CHANGELOG.md - compilable-v-c-and-v-win-c: runs-on: ubuntu-latest diff --git a/.github/workflows/docs_ci.yml b/.github/workflows/docs_ci.yml new file mode 100644 index 0000000000..98267dfa6d --- /dev/null +++ b/.github/workflows/docs_ci.yml @@ -0,0 +1,23 @@ +name: Docs CI + +on: + push: + paths: + - "cmd/tools/check-md.v" + - "doc/**" + - "CHANGELOG.md" + pull_request: + paths: + - "cmd/tools/check-md.v" + - "doc/**" + - "CHANGELOG.md" + +jobs: + docs-line-len-check: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Build V + run: make + - name: Check docs line length + run: ./v run cmd/tools/check-md.v doc/docs.md doc/upcoming.md CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index af68a6cf11..93f80dae38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ ## V 0.1.27 *5 May 2020* -- vfmt has been re-written from scratch using the new AST parser. It's much faster, cleaner, and can format +- vfmt has been re-written from scratch using the new AST parser. + It's much faster, cleaner, and can format files with compilation errors. - `strconv`, `sprintf`, and `printf` in native V, without any libc calls. - Interfaces are now a lot more stable and have all expected features. @@ -10,13 +11,13 @@ files with compilation errors. - New `[]int{cap:cap, len:len}` syntax for initializing array length and capacity. - New `is` keyword for checking the type of sum types and interfaces. - `as` can now be used to cast interfaces and sum types. -- Profiling with `-profile`. Prints a nice table with detailed information about every single function call: -number of calls, average time per call, total time per function. +- Profiling with `-profile`. Prints a nice table with details about every single function call: + number of calls, average time per call, total time per function - `import(xxx)` syntax has been removed in favor of `import xxx` for simplicity and greppability. - Lots of fixes and improvements in the type checker. - `time.StopWatch` - `dl` module for dynamic loading. -- Automatic `str()` method generation for every single type, including all arrays and fixed size arrays. +- Automatic `str()` method generation for every single type, including all arrays. - Short struct initialization syntax for imitating named function args: `foo(bar:0, baz:1)`. - New operator `!in`. - Performance improvements in critical parts of the builtin data structures (array, map). @@ -37,13 +38,15 @@ number of calls, average time per call, total time per function. ## V 0.1.25 *1 Apr 2020* -- The entire compiler has been re-written with an AST parser. The code is now a lot cleaner and more maintainable. ~15k lines of old compiler code were removed. +- The entire compiler has been re-written with an AST parser. + The code is now a lot cleaner and more maintainable. + ~15k lines of old compiler code were removed. ## V 0.1.24 *31 Dec 2019* -- A new parser/generator built on top of an AST that simplifies code greatly and allows to implement new - backends much faster. +- A new parser/generator built on top of an AST that simplifies code greatly + and allows to implement new backends much faster. - Sum types (`type Expr = IfExpr | MatchExpr | IntegerLiteral`). - B-tree map (sped up the V compiler by ~10%). - `v fmt -w`. @@ -54,7 +57,7 @@ number of calls, average time per call, total time per function. - os: `is_link()`, `is_dir()`, `exists()`. - Ranging through fixed size arrays. - Lots of fixes in ORM and vweb. -- The first tutorial: [building a simple web application with vweb](https://github.com/vlang/v/blob/master/tutorials/building-a-simple-web-blog-with-vweb.md). +- The first tutorial: [building a simple web application with vweb](https://github.com/vlang/v/blob/master/tutorials/building-a-simple-web-blog-with-vweb.md) - Match expressions now must be exhaustive. - freestanding: `malloc()`/`free()`. - `++` is now required instead of `+= 1` for consistency. @@ -76,13 +79,14 @@ number of calls, average time per call, total time per function. ## V 0.1.23 *30 Nov 2019* -- [Direct x64 machine code generation](https://github.com/vlang/v/issues/2849). Hello world being built in 3 milliseconds. -- Bare metal support via the `-freestanding` flag, allowing to build programs without linking to libc. +- [Direct x64 machine code generation](https://github.com/vlang/v/issues/2849). + Hello world being built in 3 milliseconds. +- Bare metal support via the `-freestanding` flag, to build programs without linking to libc. - Prebuilt V packages for Linux, macOS, and Windows. - `string.index()` now returns `?int` instead of `int/-1`. - Lots of fixes in Generics. - vweb framework for developing web applications is back. -- Vorum, the forum/blogging software written in V/vweb, can now be compiled and has been added to CI. +- Vorum, the forum/blogging software written in vweb, can now be compiled and has been added to CI. - REPL, `v up` have been split up into separate applications to keep the core V compiler small. - V now enforces short enum syntax (`.green` instead of `Color.green`) when it's enough. - V UI for macOS. @@ -90,7 +94,8 @@ number of calls, average time per call, total time per function. - `os.cp()` for copying files and directores. - Additional compile-time flags: `$if clang, msvc, mingw, x32, x64, big_endian, little_endian {`. - All C functions now have to be declared, all missing C functions have been defined. -- Global variables (only with the `--enable-globals` flag) for low level applications like kernels and drivers. +- Global variables (only with the `--enable-globals` flag) + for low level applications like kernels and drivers. - Nothing can be cast to bool (previously code like `if bool(1) {` worked). - `<<` and `>>` now work with all integer types. - V detects Cygwin and shows an error (V supports Windows natively). @@ -116,7 +121,7 @@ number of calls, average time per call, total time per function. - `malloc/free` on bare metal. - `utf8` helper functions (`to_lower()`, `to_upper()`, etc). - Optimization of `for c in str {`. -- `string/array.left/right/slice/substr` were removed (`[a..b]` slicing syntax should be used instead). +- `string/array.left/right/slice/substr` were removed (use `[a..b]` slicing syntax instead). @@ -128,8 +133,7 @@ number of calls, average time per call, total time per function. - Optimized `array.filter()` and `array.map()`. - `sqlite` module. - Cached modules for faster compilation. -- Dramatic compilation optimizations: [V now compiles itself in -0.10 - 0.30 seconds](https://github.com/vlang/v/wiki/The-V-language-now-compiles-itself-in-0.09-seconds). +- Dramatic compilation optimizations: [V now compiles itself in 0.10 - 0.30 seconds](https://github.com/vlang/v/wiki/The-V-language-now-compiles-itself-in-0.09-seconds) - V scripts (simpler and cross-platform alternative to Bash). - Infinite multi-dimensional arrays (`[][][]int`). - `unsafe`. @@ -296,7 +300,7 @@ this backend. ## V 0.1.15 *15 Jul 2019* - FreeBSD, OpenBSD, NetBSD, DragonFly support. -- Hot code reloading now works with graphical applications: [bounce.v](https://github.com/vlang/v/blob/master/examples/hot_code_reloading/bounce.v). +- Hot reloading now works with graphical applications: [bounce.v](examples/hot_reload/bounce.v) - VROOT was removed, the installation process is now much simpler. - `defer` statement. - map.v was re-written. It's now much faster. @@ -310,7 +314,7 @@ this backend. ## V 0.1.14 *12 Jul 2019* - `gg` module Windows support, V Tetris runs on Windows. -- `glad` and `cJSON` are now compiled only once, this makes compilation of programs using `gg` and `json` a bit faster. +- Compile `glad` and `cJSON` only once. Programs using `gg` or `json` compile a bit faster. - `v.c` has been cleaned up and minimized (~16k => ~10k lines of code). - `type` aliases can now have methods. - Const overflow check during compilation (`byte(1000)` will no longer compile). @@ -332,8 +336,10 @@ this backend. ## V 0.1.12 *4 Jul 2019* - V can finally compile itself on Windows (https://github.com/vlang/v#mingw-w64). -- `os` module now uses optionals in all functions that return `File`. Lots of bugs with optionals fixed. -- `println` was optimized. It no longer results in allocations. Now it also works correctly with all integer types. +- `os` module now uses optionals in all functions that return `File`. +- Lots of bugs with optionals were fixed. +- `println` was optimized. It no longer results in allocations. + Now it also works correctly with all integer types. - Lots of `vfmt` fixes, it will be enabled tomorrow. - New `strings` module. - Lots of other fixes and improvements, thanks to all the contributors. diff --git a/cmd/tools/check-md.v b/cmd/tools/check-md.v index bfa4429828..a8ba9888b3 100644 --- a/cmd/tools/check-md.v +++ b/cmd/tools/check-md.v @@ -8,23 +8,36 @@ const ( fn main() { files_paths := os.args[1..] + mut warnings := 0 mut errors := 0 for file_path in files_paths { real_path := os.real_path(file_path) lines := os.read_lines(real_path) or { + println('"$file_path" does not exist') + warnings++ continue } for i, line in lines { if line.len > too_long_line_length { - eprintln('$real_path:${i+1}:${line.len+1}: line too long') - errors++ + linetrace_msg := '$file_path:${i + 1}:${line.len + 1}: ' + if line.starts_with('|') { + println(linetrace_msg + 'long table (warn)') + warnings++ + } else if line.contains('https') { + println(linetrace_msg + 'long link (warn)') + warnings++ + } else { + eprintln(linetrace_msg + 'line too long') + errors++ + } } } } - // TODO: uncomment this AFTER doc/docs.md line lengths are fixed - /* + if warnings > 0 || errors > 0 { + println('\nWarnings | Errors') + println('$warnings\t | $errors') + } if errors > 0 { exit(1) } - */ } diff --git a/doc/docs.md b/doc/docs.md index 499d71be7d..82c2936112 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -255,7 +255,8 @@ println(age) ``` To change the value of the variable use `=`. In V, variables are -immutable by default. To be able to change the value of the variable, you have to declare it with `mut`. +immutable by default. +To be able to change the value of the variable, you have to declare it with `mut`. Try compiling the program above after removing `mut` from the first line. @@ -281,8 +282,10 @@ fn main() { ### Declaration errors -In development mode the compiler will warn you that you haven't used the variable (you'll get an "unused variable" warning). -In production mode (enabled by passing the `-prod` flag to v – `v -prod foo.v`) it will not compile at all (like in Go). +In development mode the compiler will warn you that you haven't used the variable +(you'll get an "unused variable" warning). +In production mode (enabled by passing the `-prod` flag to v – `v -prod foo.v`) +it will not compile at all (like in Go). ```v fn main() { @@ -294,7 +297,8 @@ fn main() { } ``` -Unlike most languages, variable shadowing is not allowed. Declaring a variable with a name that is already used in a parent scope will cause a compilation error. +Unlike most languages, variable shadowing is not allowed. Declaring a variable with a name +that is already used in a parent scope will cause a compilation error. ## Types @@ -393,8 +397,9 @@ println('Hello, $name!') // Hello, Bob! It also works with fields: `'age = $user.age'`. If you need more complex expressions, use `${}`: `'can register = ${user.age > 13}'`. -Format specifiers similar to those in C's `printf()` are also supported. `f`, `g`, `x`, etc. are optional -and specify the output format. The compiler takes care of the storage size, so there is no `hd` or `llu`. +Format specifiers similar to those in C's `printf()` are also supported. +`f`, `g`, `x`, etc. are optional and specify the output format. +The compiler takes care of the storage size, so there is no `hd` or `llu`. ```v x := 123.4567 @@ -503,8 +508,10 @@ The type of an array is determined by the first element: * `[1, 2, 3]` is an array of ints (`[]int`). * `['a', 'b']` is an array of strings (`[]string`). -If V is unable to infer the type of an array, the user can explicitly specify it for the first element: `[byte(16), 32, 64, 128]`. -V arrays are homogeneous (all elements must have the same type). This means that code like `[1, 'a']` will not compile. +If V is unable to infer the type of an array, +the user can explicitly specify it for the first element: `[byte(16), 32, 64, 128]`. +V arrays are homogeneous (all elements must have the same type). +This means that code like `[1, 'a']` will not compile. The `.len` field returns the length of the array. Note that it's a read-only field, and it can't be modified by the user. Exported fields are read-only by default in V. @@ -543,7 +550,8 @@ and the default element (`init`): arr := []int{ len: 5, init: -1 } // `[-1, -1, -1, -1, -1]` ``` -Setting the capacity improves performance of insertions, as it reduces the number of reallocations needed: +Setting the capacity improves performance of insertions, +as it reduces the number of reallocations needed: ```v mut numbers := []int{ cap: 1000 } @@ -731,7 +739,8 @@ if a < b { ``` `if` statements are pretty straightforward and similar to most other languages. -Unlike other C-like languages, there are no parentheses surrounding the condition, and the braces are always required. +Unlike other C-like languages, +there are no parentheses surrounding the condition and the braces are always required. `if` can be used as an expression: @@ -767,7 +776,8 @@ if x is Abc { If you have a struct field which should be checked, there is also a way to name a alias. ```v if x.bar is MyStruct as bar { - // x.bar cannot be cast automatically, you must explicitly state "as bar" to create a variable with the MyStruct type + // x.bar cannot be cast automatically + // you must explicitly state "as bar" to create a variable with the MyStruct type println(bar) } ``` @@ -797,7 +807,8 @@ if parser.token in [.plus, .minus, .div, .mult] { } ``` -V optimizes such expressions, so both `if` statements above produce the same machine code and no arrays are created. +V optimizes such expressions, +so both `if` statements above produce the same machine code and no arrays are created. ### For loop @@ -819,7 +830,8 @@ for i, name in names { The `for value in arr` form is used for going through elements of an array. If an index is required, an alternative form `for index, value in arr` can be used. -Note, that the value is read-only. If you need to modify the array while looping, you have to use indexing: +Note, that the value is read-only. +If you need to modify the array while looping, you have to use indexing: ```v mut numbers := [0, 1, 2] @@ -982,7 +994,8 @@ Note: `match` as an expression is not usable in `for` loop and `if` statements. ### Defer -A defer statement defers the execution of a block of statements until the surrounding function returns. +A defer statement defers the execution of a block of statements +until the surrounding function returns. ```v fn read_log() { @@ -1061,7 +1074,8 @@ struct Foo { } ``` -All struct fields are zeroed by default during the creation of the struct. Array and map fields are allocated. +All struct fields are zeroed by default during the creation of the struct. +Array and map fields are allocated. It's also possible to define custom default values. @@ -1158,7 +1172,8 @@ fn main() { } ``` -This means that defining public readonly fields is very easy in V, no need in getters/setters or properties. +This means that defining public readonly fields is very easy in V, +no need in getters/setters or properties. ### Methods @@ -1190,11 +1205,11 @@ but a short, preferably one letter long, name. ### Pure functions by default -V functions are pure by default, meaning that their return values are a function of their arguments only, -and their evaluation has no side effects (besides I/O). +V functions are pure by default, meaning that their return values are a function of their +arguments only, and their evaluation has no side effects (besides I/O). -This is achieved by a lack of global variables and all function arguments being immutable by default, -even when [references](#references) are passed. +This is achieved by a lack of global variables and all function arguments being +immutable by default, even when [references](#references) are passed. V is not a purely functional language however. @@ -1243,7 +1258,8 @@ It is preferable to return values instead of modifying arguments. Modifying arguments should only be done in performance-critical parts of your application to reduce allocations and copying. -For this reason V doesn't allow the modification of arguments with primitive types such as integers. Only more complex types such as arrays and maps may be modified. +For this reason V doesn't allow the modification of arguments with primitive types (e.g. integers). +Only more complex types such as arrays and maps may be modified. Use `user.register()` or `user = register(user)` instead of `register(mut user)`. @@ -1542,7 +1558,8 @@ match color { ``` -Enum match must be exhaustive or have an `else` branch. This ensures that if a new enum field is added, it's handled everywhere in the code. +Enum match must be exhaustive or have an `else` branch. +This ensures that if a new enum field is added, it's handled everywhere in the code. ### Sum types @@ -1673,7 +1690,8 @@ V combines `Option` and `Result` into one type, so you don't need to decide whic The amount of work required to "upgrade" a function to an optional function is minimal; you have to add a `?` to the return type and return an error when something goes wrong. -If you don't need to return an error message, you can simply `return none` (this is a more efficient equivalent of `return error("")`). +If you don't need to return an error message, you can simply `return none` +(this is a more efficient equivalent of `return error("")`). This is the primary mechanism for error handling in V. They are still values, like in Go, but the advantage is that errors can't be unhandled, and handling them is a lot less verbose. @@ -1728,16 +1746,18 @@ user := repo.find_user_by_id(7) or { } ``` -Here, you can either call `panic()` or `exit()`, which will stop the execution of the entire program, -or use a control flow statement (`return`, `break`, `continue`, etc) to break from the current block. +Here, you can either call `panic()` or `exit()`, which will stop the execution of the +entire program, or use a control flow statement (`return`, `break`, `continue`, etc) +to break from the current block. Note that `break` and `continue` can only be used inside a `for` loop. -V does not have a way to forcibly "unwrap" an optional (as other languages do, for instance Rust's `unwrap()` -or Swift's `!`). To do this, use `or { panic(err) }` instead. +V does not have a way to forcibly "unwrap" an optional (as other languages do, +for instance Rust's `unwrap()` or Swift's `!`). To do this, use `or { panic(err) }` instead. --- -The third method is to provide a default value at the end of the `or` block. In case of an error, -that value would be assigned instead, so it must have the same type as the content of the `Option` being handled. +The third method is to provide a default value at the end of the `or` block. +In case of an error, that value would be assigned instead, +so it must have the same type as the content of the `Option` being handled. ```v fn do_something(s string) ?string { @@ -1911,8 +1931,9 @@ y := <-ch2 ? #### Channel Select -The `select` command allows monitoring several channels at the same time without noticeable CPU load. It consists -of a list of possible transfers and associated branches of statements - similar to the [match](#match) command: +The `select` command allows monitoring several channels at the same time +without noticeable CPU load. It consists of a list of possible transfers and associated branches +of statements - similar to the [match](#match) command: ```v select { a := <-ch { @@ -1934,7 +1955,8 @@ The timeout branch is optional. If it is absent `select` waits for an unlimited It is also possible to proceed immediately if no channel is ready in the moment `select` is called by adding an `else { ... }` branch. `else` and `> timeout` are mutually exclusive. -The `select` command can be used as an *expression* of type `bool` that becomes `false` if all channels are closed: +The `select` command can be used as an *expression* of type `bool` +that becomes `false` if all channels are closed: ```v if select { ch <- a { @@ -1956,14 +1978,15 @@ res2 := ch2.try_pop(mut b) // try to perform `b = <-ch2 l := ch.len // number of elements in queue c := ch.cap // maximum queue length ``` -The `try_push/pop()` methods will return immediately with one of the results `.success`, `.not_ready` -or `.closed` - dependent on whether the object has been transferred or the reason why not. Usage -of these methods and properties in production is not recommended - algorithms based on them are often subject -to race conditions. Use `select` instead. +The `try_push/pop()` methods will return immediately with one of the results +`.success`, `.not_ready` or `.closed` - dependent on whether the object has been transferred or +the reason why not. +Usage of these methods and properties in production is not recommended - +algorithms based on them are often subject to race conditions. Use `select` instead. -Data can be exchanged between a coroutine -and the calling thread via a shared variable. This variable should be created as reference and passed to -the coroutine as `mut`. The underlying `struct` should also contain a `mutex` to lock concurrent access: +Data can be exchanged between a coroutine and the calling thread via a shared variable. +This variable should be created as reference and passed to the coroutine as `mut`. +The underlying `struct` should also contain a `mutex` to lock concurrent access: ```v import sync @@ -2035,10 +2058,12 @@ println(foos[1].x) Because of the ubiquitous nature of JSON, support for it is built directly into V. -The `json.decode` function takes two arguments: the first argument of the `json.decode` function is the type into which the JSON value should be decoded and the second is a string containing the JSON data. +The `json.decode` function takes two arguments: +the first is the type into which the JSON value should be decoded and +the second is a string containing the JSON data. -V generates code for JSON encoding and decoding. No runtime reflection is used. This results in much better -performance. +V generates code for JSON encoding and decoding. +No runtime reflection is used. This results in much better performance. ## Testing @@ -2153,7 +2178,8 @@ fn test() []int { (This is still in an alpha state) -V has a built-in ORM (object-relational mapping) which supports SQLite, and will soon support MySQL, Postgres, MS SQL, and Oracle. +V has a built-in ORM (object-relational mapping) which supports SQLite, +and will soon support MySQL, Postgres, MS SQL, and Oracle. V's ORM provides a number of benefits: @@ -2161,7 +2187,8 @@ V's ORM provides a number of benefits: - Queries are constructed using V's syntax. (There's no need to learn another syntax.) - Safety. (All queries are automatically sanitised to prevent SQL injection.) - Compile time checks. (This prevents typos which can only be caught during runtime.) -- Readability and simplicity. (You don't need to manually parse the results of a query and then manually construct objects from the parsed results.) +- Readability and simplicity. (You don't need to manually parse the results of a query and + then manually construct objects from the parsed results.) ```v struct Customer { // struct name has to be the same as the table name (for now) @@ -2199,7 +2226,8 @@ For more examples, see replaced with the name of the current V function - `@MOD` => replaced with the name of the current V module @@ -2641,9 +2687,9 @@ fn main() { } ``` -Operator overloading goes against V's philosophy of simplicity and predictability. But since -scientific and graphical applications are among V's domains, operator overloading is an important feature to have -in order to improve readability: +Operator overloading goes against V's philosophy of simplicity and predictability. +But since scientific and graphical applications are among V's domains, +operator overloading is an important feature to have in order to improve readability: `a.add(b).add(c.mul(d))` is a lot less readable than `a + b + c * d`. @@ -2705,11 +2751,13 @@ An online C/C++ to V translator is coming soon. When should you translate C code and when should you simply call C code from V? -If you have well-written, well-tested C code, then of course you can always simply call this C code from V. +If you have well-written, well-tested C code, +then of course you can always simply call this C code from V. Translating it to V gives you several advantages: -- If you plan to develop that code base, you now have everything in one language, which is much safer and easier to develop in than C. +- If you plan to develop that code base, you now have everything in one language, + which is much safer and easier to develop in than C. - Cross-compilation becomes a lot easier. You don't have to worry about it at all. - No more build flags and include files either. @@ -2812,7 +2860,8 @@ On Unix-like platforms, the file can be run directly after making it executable V has several attributes that modify the behavior of functions and structs. -An attribute is specified inside `[]` right before a function/struct declaration and applies only to the following declaration. +An attribute is specified inside `[]` right before a function/struct declaration +and applies only to the following declaration. ```v // Calling this function will result in a deprecation warning