Initial commit
parent
825419003a
commit
8dd6fb1766
|
@ -0,0 +1,2 @@
|
||||||
|
*.v linguist-language=Go
|
||||||
|
website/* linguist-vendored
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Alexander Medvednikov
|
||||||
|
|
||||||
|
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.
|
82
README.md
82
README.md
|
@ -1,3 +1,81 @@
|
||||||
# Official V repository
|
# The V Programming Language
|
||||||
|
|
||||||
V is going to be open-sourced in mid 2019.
|
V is going to be open-sourced in June 2019. Early access on April 15.
|
||||||
|
|
||||||
|
https://vlang.io
|
||||||
|
|
||||||
|
Documentation: https://vlang.io/docs
|
||||||
|
|
||||||
|
Twitter: https://twitter.com/vlang_io
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Fast compilation
|
||||||
|
V compiles 1.5 million lines of code per second per CPU core
|
||||||
|
```
|
||||||
|
cd doom3/
|
||||||
|
wc -l doom3.v # 458 713
|
||||||
|
time v doom3.v # 0.5s
|
||||||
|
```
|
||||||
|
[Compilation speed benchmark and comparison with other languages.](https://vlang.io/compilation_speed)
|
||||||
|
|
||||||
|
## Safety
|
||||||
|
- No global state
|
||||||
|
- No null
|
||||||
|
- No undefined values
|
||||||
|
- Option types
|
||||||
|
- Generics
|
||||||
|
- Immutability by default
|
||||||
|
- Partially pure functions
|
||||||
|
|
||||||
|
## C/C++ translation
|
||||||
|
V can translate your entire C/C++ project and offer you the safety, simplicity, and up to 200x compilation speed up.
|
||||||
|
```
|
||||||
|
std::vector<std::string> s;
|
||||||
|
s.push_back("V is ");
|
||||||
|
s.push_back("awesome");
|
||||||
|
std::cout << s.size();
|
||||||
|
```
|
||||||
|
```
|
||||||
|
s := []string
|
||||||
|
s << 'V is '
|
||||||
|
s << 'awesome'
|
||||||
|
println(s.len)
|
||||||
|
```
|
||||||
|
Read about translating Doom & Doom 3, LevelDB, SQLite (coming in March).
|
||||||
|
|
||||||
|
## 400 KB compiler with zero dependencies
|
||||||
|
The entire V language and its standard library is less than 400 KB. You can build V in 0.3 seconds.
|
||||||
|
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
- As fast as C
|
||||||
|
- Minimal amount of allocations
|
||||||
|
- Built-in serialization without reflection
|
||||||
|
|
||||||
|
## Hot code reloading
|
||||||
|
Get your changes instantly without recompiling!
|
||||||
|
|
||||||
|
Since you also don't have to waste time to get to the state you are working on after every compilation, this can save a lot of precious minutes of your development time.
|
||||||
|
|
||||||
|
[Demonstration of hot code reloading.](https://volt-app.com/img/lang.webm)
|
||||||
|
|
||||||
|
## Simple language for building maintainable programs
|
||||||
|
You can learn the entire language by going through the documentation in half an hour.
|
||||||
|
|
||||||
|
Despite being simple, it gives a lot of power to the developer. Anything you can do in other languages, you can do in V.
|
||||||
|
|
||||||
|
## REPL
|
||||||
|
```
|
||||||
|
v
|
||||||
|
>> data := http.get('https://vlang.io/utc_now')?
|
||||||
|
>> data
|
||||||
|
'1551205308'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Native cross platform UI library
|
||||||
|
Build native apps that look native. You no longer need to embed a browser to develop cross platform apps quickly.
|
||||||
|
|
||||||
|
## Run everywhere
|
||||||
|
V can compile to (human readable) C, so you get the great platform support and optimization of gcc and Clang.
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
module base64
|
||||||
|
|
||||||
|
const (
|
||||||
|
INDEX = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
62, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29,
|
||||||
|
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
||||||
|
47, 48, 49, 50, 51]
|
||||||
|
)
|
||||||
|
|
||||||
|
fn decode(data string) string {
|
||||||
|
p := data.str
|
||||||
|
len := data.len
|
||||||
|
mut pad := 0
|
||||||
|
if len > 0 && (len % 4 != 0 || p[len - 1] == `=`) {
|
||||||
|
pad = 1
|
||||||
|
}
|
||||||
|
L := ((len + 3) / 4 - pad) * 4
|
||||||
|
str_len := L / 4 * 3 + pad
|
||||||
|
mut str := malloc(str_len + 2)
|
||||||
|
mut j := 0
|
||||||
|
for i := 0; i < L; i += 4 {
|
||||||
|
n := (INDEX[p[i]] << 18) | (INDEX[p[i + 1]] << 12) |
|
||||||
|
(INDEX[p[i + 2]] << 6) | (INDEX[p[i + 3]])
|
||||||
|
str[j] = n >> 16
|
||||||
|
j++
|
||||||
|
str[j] = n >> 8 & 0xff
|
||||||
|
j++
|
||||||
|
str[j] = n & 0xff
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
if pad > 0 {
|
||||||
|
mut nn := (INDEX[p[L]] << 18) | (INDEX[p[L + 1]] << 12)
|
||||||
|
str[str_len - 1] = nn >> 16
|
||||||
|
if len > L + 2 && p[L + 2] != `=` {
|
||||||
|
nn = nn | (INDEX[p[L + 2]] << 6)
|
||||||
|
str[str_len] = nn >> 8 & 0xff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str[str_len + 1] = `\0`
|
||||||
|
return string(str)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import base64
|
||||||
|
|
||||||
|
fn test_decode() {
|
||||||
|
assert base64.decode('TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=')
|
||||||
|
== 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Please share your thoughts, suggestions, questions, etc here:
|
||||||
|
// https://github.com/vlang-io/V/issues/3
|
||||||
|
// I'm very interested in your feedback.
|
||||||
|
import http
|
||||||
|
import json
|
||||||
|
import runtime
|
||||||
|
|
||||||
|
struct Story {
|
||||||
|
title string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetches top HN stories in 8 coroutines
|
||||||
|
fn main() {
|
||||||
|
resp := http.get('https://hacker-news.firebaseio.com/v0/topstories.json')?
|
||||||
|
ids := json.decode([]int, resp.body)?
|
||||||
|
mut cursor := 0
|
||||||
|
for _ in 0..8 {
|
||||||
|
go fn() {
|
||||||
|
for {
|
||||||
|
lock { // Without this lock the program will not compile
|
||||||
|
if cursor >= ids.len {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
id := ids[cursor]
|
||||||
|
cursor++
|
||||||
|
}
|
||||||
|
url := 'https://hacker-news.firebaseio.com/v0/item/$id.json'
|
||||||
|
resp := http.get(url)?
|
||||||
|
story := json.decode(Story, resp.body)?
|
||||||
|
println(story.title)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
runtime.wait() // Waits for all coroutines to finish
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Please share your thoughts, suggestions, questions, etc here:
|
||||||
|
// https://github.com/vlang-io/V/issues/3
|
||||||
|
|
||||||
|
// I'm very interested in your feedback.
|
||||||
|
|
||||||
|
module main
|
||||||
|
|
||||||
|
struct User { /* ... */ }
|
||||||
|
struct Post { /* ... */ }
|
||||||
|
struct DB { /* ... */ }
|
||||||
|
|
||||||
|
struct Repo <T> {
|
||||||
|
db DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic code is notoriously verbose. To reduce clutter, V doesn't require you
|
||||||
|
// to add `<T>` every time, since it already knows that Repo is a generic type.
|
||||||
|
fn new_repo<T>(db DB) Repo {
|
||||||
|
return Repo<T>{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a generic function. V will generate it for every type it's used with.
|
||||||
|
fn (r Repo) find_by_id(id int) T? { // `?` means the function returns an optional
|
||||||
|
table_name := T.name // in this example getting the name of the type gives us the table name
|
||||||
|
return r.db.query_one<T>('select * from $table_name where id = ?', id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
db := new_db()
|
||||||
|
users_repo := new_repo<User>(db)
|
||||||
|
// I'm also considering passing the type as an argument
|
||||||
|
// users_repo := new_repo(User, db)
|
||||||
|
posts_repo := new_repo<Post>(db)
|
||||||
|
user := users_repo.find_by_id(1) or {
|
||||||
|
eprintln('User not found')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
post := posts_repo.find_by_id(1) or {
|
||||||
|
eprintln('Post not found')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Please share your thoughts, suggestions, questions, etc here:
|
||||||
|
// https://github.com/vlang-io/V/issues/3
|
||||||
|
|
||||||
|
// I'm very interested in your feedback.
|
||||||
|
|
||||||
|
module main
|
||||||
|
|
||||||
|
import ui // Native cross platform ui toolkit (uses Cocoa, win32, GTK+)
|
||||||
|
|
||||||
|
// There are no globals, so we have to use a context struct
|
||||||
|
struct Context {
|
||||||
|
input ui.TextBox // this uses native controls (NSTextView on macOS, edit HWND on Windows)
|
||||||
|
names []string // let's log the names to demonstrate how arrays work
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
wnd := ui.new_window(ui.WindowCfg{ // V has no default arguments and overloading.
|
||||||
|
width: 600 // All stdlib functions with many args use Cfg wrappers.
|
||||||
|
height: 300
|
||||||
|
title: 'hello world'
|
||||||
|
})
|
||||||
|
ctx := Context{
|
||||||
|
input: ui.new_textbox(wnd)
|
||||||
|
// we don't need to initialize the names array, it's done automatically
|
||||||
|
}
|
||||||
|
ctx.input.set_placeholder('Enter your name')
|
||||||
|
btn := ui.new_button(wnd, 'Click me', ctx.btn_click)
|
||||||
|
for {
|
||||||
|
ui.wait_events()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (ctx mut Context) btn_click() {
|
||||||
|
name := ctx.input.text()
|
||||||
|
ctx.input.hide()
|
||||||
|
println('current list of names: $ctx.names') // >> current list of names: [ "Bob", "Alex" ]
|
||||||
|
ui.alert('Hello, $name!')
|
||||||
|
if ctx.names.contains(name) {
|
||||||
|
ui.alert('I already greeted you ;)')
|
||||||
|
}
|
||||||
|
ctx.names << name
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Please share your thoughts, suggestions, questions, etc here:
|
||||||
|
// https://github.com/vlang-io/V/issues/3
|
||||||
|
|
||||||
|
// I'm very interested in your feedback.
|
||||||
|
|
||||||
|
module main
|
||||||
|
|
||||||
|
import json // V will automatically insert missing imports (like the goimports tool)
|
||||||
|
import http
|
||||||
|
|
||||||
|
// Right now V requires all consts to be uppercase.
|
||||||
|
// I'm still not certain about this.
|
||||||
|
const API_URL = 'https://vlang.io/users.json'
|
||||||
|
|
||||||
|
// V will generate json.encode and json.decode functions for this type since
|
||||||
|
// `json.decode([]User, ...)` is called later. This results in better
|
||||||
|
// performance, since reflection is not used.
|
||||||
|
struct User {
|
||||||
|
name string // V will automatically format and align your code.
|
||||||
|
age int // No need to use an additional tool.
|
||||||
|
is_registered bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// `http.get()` returns an optional string.
|
||||||
|
// V optionals combine the features of Rust's Option<T> and Result<T>.
|
||||||
|
// We must unwrap all optionals with `or`, otherwise V will complain.
|
||||||
|
s := http.get(API_URL) or {
|
||||||
|
// `err` is a reserved variable (not a global) that
|
||||||
|
// contains an error message if there is one
|
||||||
|
eprintln('Failed to fetch "users.json": $err')
|
||||||
|
// `or` blocks must end with `return`, `break`, or `continue`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Types can be passed as arguments
|
||||||
|
users := json.decode([]User, s) or {
|
||||||
|
eprintln('Failed to parse users.json')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Encoding JSON doesn't require a type, since V knows what type
|
||||||
|
// the variable `users` has
|
||||||
|
println(json.encode(users))
|
||||||
|
// Please note the difference between V and Go:
|
||||||
|
// when there's only one variable, it's a value, not an index.
|
||||||
|
for user in users {
|
||||||
|
println('$user.name: $user.age')
|
||||||
|
}
|
||||||
|
// `for` loop has an alternative form when an index is required:
|
||||||
|
for i, user in users {
|
||||||
|
println('$i) $user')
|
||||||
|
if !user.can_register() {
|
||||||
|
// V allows both ' and " to denote strings.
|
||||||
|
// However, for consistency V will replace " with '
|
||||||
|
// unless the string contains an apostrophe.
|
||||||
|
println("Can't register")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The method declaration is the same as in Go.
|
||||||
|
// There is one big difference. Here `u` can be either passed by value (User)
|
||||||
|
// or by reference (&User). The compiler will make the right decision
|
||||||
|
// depending on the size of the User struct. You no longer have to remember
|
||||||
|
// which one to use. It works here because `u` can't be modified (it's not
|
||||||
|
// marked as `mut`).
|
||||||
|
fn (u User) can_register() bool {
|
||||||
|
return u.age >= 16
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here `u` can be modified and it will always be a reference.
|
||||||
|
fn (u mut User) register() {
|
||||||
|
u.is_registered = true
|
||||||
|
}
|
Loading…
Reference in New Issue