mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: make compiler an ordinary vlib/compiler module
* Move compiler/ under vlib/compiler/ . * Add a minimal compiler/main.v driver program. * Cleanup compiler/main.v . * Make most compiler tests pass again. * Apply the fix by @joe-conigliaro , so that the rest of the compiler tests are fixed too. * Thanks to @avitkauskas, now the vlib/vcompiler/tests/str_gen_test.v test does not need to be special cased anymore. * Reapply @joe-conigliaro fix for vgen.
This commit is contained in:
committed by
Alexander Medvednikov
parent
59d4535f84
commit
53c64abdeb
21
vlib/compiler/tests/bench/val_vs_ptr.c
Normal file
21
vlib/compiler/tests/bench/val_vs_ptr.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int increment_val(int n) {
|
||||
return n + 2;
|
||||
}
|
||||
|
||||
// ~26% faster
|
||||
void increment_ptr(int* n) {
|
||||
*n += 2;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int n = 0;
|
||||
for (int i = 0; i < 1000000000; i++) {
|
||||
n = increment_val(n);
|
||||
//increment_ptr(&n);
|
||||
}
|
||||
printf("%d\n", n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
51
vlib/compiler/tests/defer_test.v
Normal file
51
vlib/compiler/tests/defer_test.v
Normal file
@@ -0,0 +1,51 @@
|
||||
fn foo() string {
|
||||
println('foo()')
|
||||
return 'foo'
|
||||
}
|
||||
|
||||
fn foo2() string {
|
||||
println('start')
|
||||
defer { println('defer') }
|
||||
defer { println('defer2') }
|
||||
println('end')
|
||||
return foo()
|
||||
}
|
||||
|
||||
fn test_defer() {
|
||||
assert foo2() == 'foo'
|
||||
}
|
||||
|
||||
fn set_num(i int, n mut Num) {
|
||||
defer { n.val+=1 }
|
||||
println("Hi")
|
||||
if i < 5 {
|
||||
return
|
||||
} else {
|
||||
n.val+=1
|
||||
}
|
||||
}
|
||||
|
||||
fn set_num_opt(n mut Num) ?int {
|
||||
defer { n.val = 1 }
|
||||
return 99
|
||||
}
|
||||
|
||||
struct Num {
|
||||
mut:
|
||||
val int
|
||||
}
|
||||
|
||||
fn test_defer_early_exit() {
|
||||
mut sum := Num{0}
|
||||
for i in 0..10 {
|
||||
set_num(i, mut sum)
|
||||
}
|
||||
println("sum: $sum.val")
|
||||
assert sum.val == 15
|
||||
}
|
||||
|
||||
fn test_defer_option() {
|
||||
mut ok := Num{0}
|
||||
set_num_opt(mut ok)
|
||||
assert ok.val == 1
|
||||
}
|
||||
24
vlib/compiler/tests/enum_test.v
Normal file
24
vlib/compiler/tests/enum_test.v
Normal file
@@ -0,0 +1,24 @@
|
||||
enum Color {
|
||||
red
|
||||
blue
|
||||
green
|
||||
}
|
||||
|
||||
fn test_enum() {
|
||||
assert Color.red == Color.red
|
||||
assert Color.blue == Color.blue
|
||||
assert Color.green == Color.green
|
||||
|
||||
assert Color.red == .red
|
||||
assert Color.blue == .blue
|
||||
assert Color.green == .green
|
||||
|
||||
assert Color.red != Color.blue
|
||||
assert Color.red != Color.green
|
||||
assert Color.blue != Color.green
|
||||
|
||||
mut color := Color.red
|
||||
assert color == Color.red
|
||||
color = .green
|
||||
assert color == Color.green
|
||||
}
|
||||
32
vlib/compiler/tests/fixed_array_test.v
Normal file
32
vlib/compiler/tests/fixed_array_test.v
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
fn test_fixed_array_can_be_assigned(){
|
||||
x := 2.32
|
||||
mut v := [8]f32
|
||||
v = [1.0, x, 3.0,4.0,5.0,6.0,7.0,8.0]!!
|
||||
assert v[1] == x
|
||||
}
|
||||
|
||||
fn test_fixed_array_can_be_used_in_declaration(){
|
||||
x := 2.32
|
||||
v := [1.0, x, 3.0,4.0,5.0,6.0,7.0,8.0]!!
|
||||
assert v[1] == x
|
||||
}
|
||||
|
||||
|
||||
struct Context {
|
||||
pub mut:
|
||||
vb [8]f32
|
||||
}
|
||||
fn test_fixed_array_can_be_assigned_to_a_struct_field(){
|
||||
mut ctx := Context{}
|
||||
x := 2.32
|
||||
ctx.vb = [1.1, x, 3.3, 4.4, 5.0, 6.0, 7.0, 8.9]!!
|
||||
assert ctx.vb[1] == x
|
||||
assert ctx.vb[7] == 8.9
|
||||
/*
|
||||
println( ctx.vb[0] )
|
||||
println( ctx.vb[1] )
|
||||
println( ctx.vb[2] )
|
||||
println( ctx.vb[3] )
|
||||
*/
|
||||
}
|
||||
19
vlib/compiler/tests/fn_multiple_returns_test.v
Normal file
19
vlib/compiler/tests/fn_multiple_returns_test.v
Normal file
@@ -0,0 +1,19 @@
|
||||
struct UserData {
|
||||
test string
|
||||
}
|
||||
|
||||
fn test_fn_multiple_returns() {
|
||||
name, age, groups, data := fn_mr_get_user()
|
||||
assert name == 'joe'
|
||||
assert age == 34
|
||||
assert groups[0] == 'admins'
|
||||
assert groups[1] == 'users'
|
||||
assert data.test == 'Test Data'
|
||||
println('name: $name | age: $age | groups: ' + groups.join(',') + ' | data: $data.test')
|
||||
}
|
||||
|
||||
fn fn_mr_get_user() (string, int, []string, UserData) {
|
||||
groups := ['admins', 'users']
|
||||
data := UserData{test: 'Test Data'}
|
||||
return 'joe',34,groups,data
|
||||
}
|
||||
121
vlib/compiler/tests/fn_test.v
Normal file
121
vlib/compiler/tests/fn_test.v
Normal file
@@ -0,0 +1,121 @@
|
||||
// 1 line comment
|
||||
|
||||
/* 1 line comment */
|
||||
|
||||
/*
|
||||
multi line comment (1)
|
||||
multi line comment (2)
|
||||
multi line comment (3)
|
||||
*/
|
||||
|
||||
/*
|
||||
multi line comment (1)
|
||||
/*
|
||||
nested comment
|
||||
*/
|
||||
/*nested comment*/
|
||||
/*nested comment
|
||||
*/
|
||||
/* nested comment */
|
||||
/* /* nested comment */ */
|
||||
multi line comment (2)
|
||||
*/
|
||||
|
||||
type myfn fn (int) string
|
||||
|
||||
type myfn2 fn (a int, b int) int
|
||||
|
||||
type myfn3 fn (int, int)
|
||||
|
||||
fn myfn4(string)
|
||||
|
||||
fn foobar()
|
||||
|
||||
fn slopediv(num u32, den u32) int
|
||||
|
||||
type f1 fn ()
|
||||
|
||||
type f2 fn (voidptr)
|
||||
|
||||
type f3 fn (voidptr, voidptr)
|
||||
|
||||
type f4 fn (voidptr) int
|
||||
|
||||
type f5 fn (int, int) int
|
||||
|
||||
type f6 fn (int, int)
|
||||
|
||||
fn C.atoi(byteptr) int
|
||||
|
||||
fn foo() {
|
||||
}
|
||||
|
||||
type actionf_v fn ()
|
||||
|
||||
type actionf_p1 fn (voidptr)
|
||||
|
||||
type actionf_p2 fn (voidptr, voidptr)
|
||||
|
||||
// TODO
|
||||
fn modify_array(a mut []int) {
|
||||
a[0] = 10
|
||||
for i in 0..a.len {
|
||||
a[i] = a[i] * 2
|
||||
}
|
||||
//a << 888
|
||||
}
|
||||
|
||||
fn test_mut_array() {
|
||||
mut nums := [1, 2, 3]
|
||||
modify_array(mut nums)
|
||||
//assert nums.len == 4
|
||||
// println(nums)
|
||||
assert nums[0] == 20
|
||||
assert nums[1] == 4
|
||||
assert nums[2] == 6
|
||||
//assert nums[3] == 888
|
||||
// workaround for // [91, 32, -33686272] windows bug
|
||||
println(nums.clone())
|
||||
}
|
||||
|
||||
fn mod_struct(user mut User) {
|
||||
user.age++
|
||||
}
|
||||
|
||||
struct User {
|
||||
mut:
|
||||
age int
|
||||
}
|
||||
|
||||
fn test_mut_struct() {
|
||||
mut user := User{18}
|
||||
mod_struct(mut user)
|
||||
assert user.age == 19
|
||||
}
|
||||
|
||||
fn mod_ptr(buf mut byteptr) {
|
||||
buf[0] = 77
|
||||
}
|
||||
|
||||
fn test_mut_ptr() {
|
||||
buf := malloc(10)
|
||||
mod_ptr(mut buf)
|
||||
assert buf[0] == 77
|
||||
}
|
||||
|
||||
fn high_fn(f fn(int) int) {
|
||||
|
||||
}
|
||||
|
||||
fn high_fn_array(f fn(a []int) []int) {
|
||||
|
||||
}
|
||||
|
||||
fn high_fn_multi_return(a int, b fn (c []int, d []string) ([]int, []string)) {
|
||||
|
||||
}
|
||||
|
||||
fn test_fns() {
|
||||
// no asserts for now, just test function declarations above
|
||||
}
|
||||
|
||||
15
vlib/compiler/tests/fn_variadic_test.v
Normal file
15
vlib/compiler/tests/fn_variadic_test.v
Normal file
@@ -0,0 +1,15 @@
|
||||
struct VaTestGroup {
|
||||
name string
|
||||
}
|
||||
|
||||
fn variadic_test_a(name string, groups ...VaTestGroup) {
|
||||
assert groups.len == 2
|
||||
assert groups[0].name == 'users'
|
||||
assert groups[1].name == 'admins'
|
||||
}
|
||||
|
||||
fn test_fn_variadic() {
|
||||
group1 := VaTestGroup{name: 'users'}
|
||||
group2 := VaTestGroup{name: 'admins'}
|
||||
variadic_test_a('joe', group1, group2)
|
||||
}
|
||||
32
vlib/compiler/tests/interface_test.v
Normal file
32
vlib/compiler/tests/interface_test.v
Normal file
@@ -0,0 +1,32 @@
|
||||
struct Dog {
|
||||
breed string
|
||||
}
|
||||
|
||||
fn (d Dog) speak() {
|
||||
println('dog.speak()')
|
||||
}
|
||||
|
||||
fn (d Dog) name() string {
|
||||
return 'old gray'
|
||||
}
|
||||
|
||||
interface Speaker {
|
||||
name() string
|
||||
speak()
|
||||
}
|
||||
|
||||
interface Speak2er {
|
||||
speak()
|
||||
name() string
|
||||
}
|
||||
|
||||
fn perform_speak(s Speaker) bool {
|
||||
s.speak()
|
||||
return true
|
||||
}
|
||||
|
||||
fn test_perform_speak() {
|
||||
d := Dog{}
|
||||
assert perform_speak(d)
|
||||
}
|
||||
|
||||
7
vlib/compiler/tests/local/local.v
Normal file
7
vlib/compiler/tests/local/local.v
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
module local
|
||||
|
||||
pub fn local_fn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
7
vlib/compiler/tests/local_test.v
Normal file
7
vlib/compiler/tests/local_test.v
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
import compiler.tests.local
|
||||
|
||||
fn test_local_module_is_callable() {
|
||||
assert local.local_fn()
|
||||
}
|
||||
|
||||
88
vlib/compiler/tests/match_test.v
Normal file
88
vlib/compiler/tests/match_test.v
Normal file
@@ -0,0 +1,88 @@
|
||||
enum Color{
|
||||
red, green, blue
|
||||
}
|
||||
|
||||
fn test_match_integers() {
|
||||
// a := 3
|
||||
// mut b := 0
|
||||
// match a {
|
||||
// 2 => println('two')
|
||||
// 3 => println('three')
|
||||
// b = 3
|
||||
// 4 => println('four')
|
||||
// else => println('???')
|
||||
// }
|
||||
// assert b == 3
|
||||
|
||||
assert match 2 {
|
||||
1 => {2}
|
||||
2 => {3}
|
||||
else => {5}
|
||||
} == 3
|
||||
|
||||
assert match 0 {
|
||||
1 => {2}
|
||||
2 => {3}
|
||||
else => 5
|
||||
} == 5
|
||||
|
||||
assert match 1 {
|
||||
else => {5}
|
||||
} == 5
|
||||
|
||||
mut a := 0
|
||||
match 2 {
|
||||
0 => {a = 1}
|
||||
1 => {a = 2}
|
||||
else => {
|
||||
a = 3
|
||||
println('a is $a')
|
||||
}
|
||||
}
|
||||
assert a == 3
|
||||
|
||||
a = 0
|
||||
match 1 {
|
||||
0 => {a = 1}
|
||||
1 => {
|
||||
a = 2
|
||||
a = a + 2
|
||||
a = a + 2
|
||||
}
|
||||
}
|
||||
assert a == 6
|
||||
|
||||
a = 0
|
||||
match 1 {
|
||||
else => {
|
||||
a = -2
|
||||
}
|
||||
}
|
||||
assert a == -2
|
||||
}
|
||||
|
||||
fn test_match_enums(){
|
||||
mut b := Color.red
|
||||
match b{
|
||||
.red => {
|
||||
b = .green
|
||||
}
|
||||
.green => {b = .blue}
|
||||
else => {
|
||||
println('b is ${b.str()}')
|
||||
b = .red
|
||||
}
|
||||
}
|
||||
assert b == .green
|
||||
|
||||
match b{
|
||||
.red => {
|
||||
b = .green
|
||||
}
|
||||
else => {
|
||||
println('b is ${b.str()}')
|
||||
b = .blue
|
||||
}
|
||||
}
|
||||
assert b == .blue
|
||||
}
|
||||
18
vlib/compiler/tests/module_test.v
Normal file
18
vlib/compiler/tests/module_test.v
Normal file
@@ -0,0 +1,18 @@
|
||||
import os
|
||||
import time as t
|
||||
import crypto.sha256 as s2
|
||||
|
||||
import (
|
||||
math
|
||||
log as l
|
||||
crypto.sha512 as s5
|
||||
)
|
||||
|
||||
fn test_import() {
|
||||
assert os.SUCCESS == os.SUCCESS &&
|
||||
t.month_days[0] == t.month_days[0] &&
|
||||
s2.Size == s2.Size &&
|
||||
math.pi == math.pi &&
|
||||
l.INFO == l.INFO &&
|
||||
s5.Size == s5.Size
|
||||
}
|
||||
49
vlib/compiler/tests/msvc_test.v
Normal file
49
vlib/compiler/tests/msvc_test.v
Normal file
@@ -0,0 +1,49 @@
|
||||
fn test_flag_parsing() {
|
||||
mut rest := '-lGlfw -f gl2,-ltest_nice_meme,-l cc,-Ldl test.o a.o ' //, whatever.o'
|
||||
result := ['-l', 'Glfw',
|
||||
'-f', 'gl2',
|
||||
'-l', 'test_nice_meme',
|
||||
'-l', 'cc',
|
||||
'-L', 'dl',
|
||||
'', 'test.o',
|
||||
'', 'a.o']
|
||||
|
||||
mut flags := []string
|
||||
for {
|
||||
mut base := rest
|
||||
|
||||
fl := if rest.starts_with('-') {
|
||||
base = rest.right(2).trim_space()
|
||||
rest.left(2)
|
||||
} else {
|
||||
''
|
||||
}
|
||||
|
||||
// Which ever one of these is lowest we use
|
||||
// TODO: we really shouldnt support all of these cmon
|
||||
mut lowest := base.index('-')
|
||||
for x in [base.index(' '), base.index(',')] {
|
||||
if (x < lowest && x != -1) || lowest == -1 {
|
||||
lowest = x
|
||||
}
|
||||
}
|
||||
arg := if lowest != -1 {
|
||||
rest = base.right(lowest).trim_space().trim(',')
|
||||
base.left(lowest).trim_space().trim(',')
|
||||
} else {
|
||||
rest = ''
|
||||
base.trim_space()
|
||||
}
|
||||
|
||||
flags << fl
|
||||
flags << arg
|
||||
|
||||
if rest.len == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for i, f in flags {
|
||||
assert f == result[i]
|
||||
}
|
||||
}
|
||||
52
vlib/compiler/tests/mut_test.v
Normal file
52
vlib/compiler/tests/mut_test.v
Normal file
@@ -0,0 +1,52 @@
|
||||
struct A {
|
||||
pub mut:
|
||||
v []int
|
||||
}
|
||||
|
||||
struct B {
|
||||
pub mut:
|
||||
a []A
|
||||
}
|
||||
|
||||
fn foo(b int, a mut []int) {
|
||||
a[0] = 7
|
||||
//a << 4
|
||||
}
|
||||
|
||||
fn test_mut() {
|
||||
mut numbers := [1,2,3]
|
||||
foo(7, mut numbers)
|
||||
assert numbers.len == 3
|
||||
// TODO bring back once << works with mutable args
|
||||
//assert numbers.len == 4
|
||||
//assert numbers[0] == 7
|
||||
//assert numbers[3] == 4
|
||||
println(numbers)
|
||||
n := 1
|
||||
mut b := &n
|
||||
*b = 10
|
||||
//mut b := mut a
|
||||
//b = 10
|
||||
}
|
||||
|
||||
fn test_mut_2() {
|
||||
zero := 0
|
||||
|
||||
mut b := B{}
|
||||
b.a << A{}
|
||||
|
||||
b.a[0].v = [9, 8, 7]
|
||||
|
||||
b.a[0].v << 6
|
||||
b.a[zero].v << 5
|
||||
|
||||
b.a[0].v[zero] = 3
|
||||
b.a[0].v[b.a[zero].v[zero]] += 1b.a[0].v[b.a[0].v[zero]] += 1
|
||||
|
||||
assert b.a[0].v.len == 5
|
||||
assert b.a[0].v[0] == 3
|
||||
assert b.a[0].v[1] == 8
|
||||
assert b.a[0].v[2] == 7
|
||||
assert b.a[0].v[3] == 8
|
||||
assert b.a[0].v[4] == 5
|
||||
}
|
||||
48
vlib/compiler/tests/option_test.v
Normal file
48
vlib/compiler/tests/option_test.v
Normal file
@@ -0,0 +1,48 @@
|
||||
fn opt_err() ?string {return error('hi')}
|
||||
|
||||
fn test_err(){
|
||||
v := opt_err() or {
|
||||
assert err == 'hi'
|
||||
return
|
||||
}
|
||||
assert false
|
||||
println(v) // suppress not used error
|
||||
}
|
||||
|
||||
fn err_call(ok bool) ?int {
|
||||
if !ok {
|
||||
return error('Not ok!')
|
||||
}
|
||||
return 42
|
||||
}
|
||||
|
||||
fn ret_none() ?int {
|
||||
//return error('wtf') //none
|
||||
return none
|
||||
}
|
||||
|
||||
fn test_option_for_base_type_without_variable() {
|
||||
val := err_call(true) or {
|
||||
panic(err)
|
||||
}
|
||||
assert val == 42
|
||||
println('hm')
|
||||
val2 := ret_none() or {
|
||||
println('yep')
|
||||
return
|
||||
}
|
||||
println('$val2 should have been `none`')
|
||||
assert false
|
||||
// This is invalid:
|
||||
// x := 5 or {
|
||||
// return
|
||||
// }
|
||||
}
|
||||
|
||||
fn test_if_opt() {
|
||||
if val := err_call(false) {
|
||||
assert val == 42
|
||||
}
|
||||
assert 1 == 1
|
||||
println('nice')
|
||||
}
|
||||
2
vlib/compiler/tests/repl/.gitattributes
vendored
Normal file
2
vlib/compiler/tests/repl/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
*.repl text=auto eol=lf
|
||||
3
vlib/compiler/tests/repl/.gitignore
vendored
Normal file
3
vlib/compiler/tests/repl/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
run
|
||||
*.repl.result.txt
|
||||
*.repl.expected.txt
|
||||
25
vlib/compiler/tests/repl/README.md
Normal file
25
vlib/compiler/tests/repl/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# V REPL Tests Script
|
||||
|
||||
### How to write a new test
|
||||
- Create a new file named `*.repl`
|
||||
- Write the input to be given to REPL
|
||||
- Add `===output===`
|
||||
- Write the output expected
|
||||
|
||||
### Notes
|
||||
Keep in mind, that the way V repl works for now, every non empty line
|
||||
would cause a new recompilation of the entire repl content that was
|
||||
collected so far.
|
||||
|
||||
*Longer REPL files would cause measurably*
|
||||
*longer recompilation/testing times.*
|
||||
|
||||
Also, longer repl files would be slower to debug when they fail,
|
||||
*It is better to have several smaller files vs one huge REPL file.*
|
||||
|
||||
### Example :
|
||||
```
|
||||
a := 1
|
||||
println(a)
|
||||
===output===
|
||||
1
|
||||
4
vlib/compiler/tests/repl/arr_decl.repl
Normal file
4
vlib/compiler/tests/repl/arr_decl.repl
Normal file
@@ -0,0 +1,4 @@
|
||||
arr := ['1', '2', '3', '4']
|
||||
println(arr)
|
||||
===output===
|
||||
["1", "2", "3", "4"]
|
||||
16
vlib/compiler/tests/repl/chained_fields.correct.repl
Normal file
16
vlib/compiler/tests/repl/chained_fields.correct.repl
Normal file
@@ -0,0 +1,16 @@
|
||||
struct A { mut: v int } struct B { a A } struct C { mut: b B } struct D { mut: c C } struct E { mut: v []int } struct F { e []E }
|
||||
|
||||
mut b := B{} b = B{A{2}}
|
||||
println('b is: ' + b.a.v.str())
|
||||
|
||||
mut c := C{} c.b = B{}
|
||||
|
||||
mut d := D{} d.c.b = B{}
|
||||
|
||||
f := F{[E{[10,20,30]},E{[100,200,300,400]}]}
|
||||
println('f.e[0].v.len: ${f.e[0].v.len}')
|
||||
println('f.e[1].v.len: ${f.e[1].v.len}')
|
||||
===output===
|
||||
b is: 2
|
||||
f.e[0].v.len: 3
|
||||
f.e[1].v.len: 4
|
||||
78
vlib/compiler/tests/repl/chained_fields.repl
Normal file
78
vlib/compiler/tests/repl/chained_fields.repl
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 1 */ struct A { mut: v int }
|
||||
/* 2 */ struct B { a A }
|
||||
/* 3 */ struct C { mut: b B }
|
||||
/* 4 */ struct D { mut: c C }
|
||||
|
||||
/* 5 */ struct E { mut: v []int }
|
||||
/* 6 */ struct F { e []E }
|
||||
|
||||
/* 7 */ mut s := 'hello world'
|
||||
/*( 8)*/ s.len = 0 // Error (field len immutable)
|
||||
|
||||
/* 8 */ mut b := B{}
|
||||
/*( 9)*/ b.a.v = 1 // Error (field a immutable)
|
||||
/*( 9)*/ b.a = A{} // Error (field a immutable)
|
||||
/* 9 */ b = B{A{2}} // Correct
|
||||
|
||||
/* 10 */ mut c := C{}
|
||||
/* 11 */ c.b = B{} // Correct
|
||||
/*(12)*/ c.b.a = A{} // Error (field a immutable)
|
||||
/*(12)*/ c.b.a.v = 1 // Error (field a immutable)
|
||||
|
||||
/* 12 */ c2 := C{}
|
||||
/*(13)*/ c2.b = B{} // Error (c2 immutable)
|
||||
/* 13 */ mut d := D{}
|
||||
/* 14 */ d.c.b = B{} // Correct
|
||||
|
||||
/* 15 */ mut f := F{}
|
||||
/*(16)*/ f.e << E{} // Error (field e immutable)
|
||||
/*(16)*/ f.e[0].v << 1 // Error (field e immutable)
|
||||
|
||||
/* 16 */ e := E{}
|
||||
/*(17)*/ e.v << 1 // Error (e immutable)
|
||||
|
||||
===output===
|
||||
.vrepl_temp.v:27:14: cannot modify immutable field `len` (type `string`)
|
||||
declare the field with `mut:`
|
||||
struct string {
|
||||
mut:
|
||||
len int
|
||||
}
|
||||
.vrepl_temp.v:30:14: cannot modify immutable field `a` (type `B`)
|
||||
declare the field with `mut:`
|
||||
struct B {
|
||||
mut:
|
||||
a A
|
||||
}
|
||||
.vrepl_temp.v:29:12: cannot modify immutable field `a` (type `B`)
|
||||
declare the field with `mut:`
|
||||
struct B {
|
||||
mut:
|
||||
a A
|
||||
}
|
||||
.vrepl_temp.v:41:14: cannot modify immutable field `a` (type `B`)
|
||||
declare the field with `mut:`
|
||||
struct B {
|
||||
mut:
|
||||
a A
|
||||
}
|
||||
.vrepl_temp.v:42:16: cannot modify immutable field `a` (type `B`)
|
||||
declare the field with `mut:`
|
||||
struct B {
|
||||
mut:
|
||||
a A
|
||||
}
|
||||
.vrepl_temp.v:44:15: `c2` is immutable
|
||||
.vrepl_temp.v:53:12: cannot modify immutable field `e` (type `F`)
|
||||
declare the field with `mut:`
|
||||
struct F {
|
||||
mut:
|
||||
e []E
|
||||
}
|
||||
.vrepl_temp.v:54:17: cannot modify immutable field `e` (type `F`)
|
||||
declare the field with `mut:`
|
||||
struct F {
|
||||
mut:
|
||||
e []E
|
||||
}
|
||||
.vrepl_temp.v:57:17: `e` is immutable (can't <<)
|
||||
18
vlib/compiler/tests/repl/conditional_blocks.repl
Normal file
18
vlib/compiler/tests/repl/conditional_blocks.repl
Normal file
@@ -0,0 +1,18 @@
|
||||
if true {
|
||||
println('foo')
|
||||
}
|
||||
for i := 0; i < 4; i++ {
|
||||
println(i)
|
||||
}
|
||||
if false {
|
||||
println('foo')
|
||||
} else {
|
||||
println('bar')
|
||||
}
|
||||
===output===
|
||||
foo
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
bar
|
||||
7
vlib/compiler/tests/repl/default_printing.repl
Normal file
7
vlib/compiler/tests/repl/default_printing.repl
Normal file
@@ -0,0 +1,7 @@
|
||||
num := 1
|
||||
string := 'Hello'
|
||||
num
|
||||
string
|
||||
===output===
|
||||
1
|
||||
Hello
|
||||
4
vlib/compiler/tests/repl/empty_struct.repl
Normal file
4
vlib/compiler/tests/repl/empty_struct.repl
Normal file
@@ -0,0 +1,4 @@
|
||||
struct Empty{} ee := Empty{}
|
||||
println('OK')
|
||||
===output===
|
||||
OK
|
||||
3
vlib/compiler/tests/repl/error.repl
Normal file
3
vlib/compiler/tests/repl/error.repl
Normal file
@@ -0,0 +1,3 @@
|
||||
println(a)
|
||||
===output===
|
||||
.vrepl.v:2:9: undefined: `a`
|
||||
5
vlib/compiler/tests/repl/error_nosave.repl
Normal file
5
vlib/compiler/tests/repl/error_nosave.repl
Normal file
@@ -0,0 +1,5 @@
|
||||
a
|
||||
33
|
||||
===output===
|
||||
.vrepl_temp.v:3:9: undefined: `a`
|
||||
33
|
||||
11
vlib/compiler/tests/repl/function.repl
Normal file
11
vlib/compiler/tests/repl/function.repl
Normal file
@@ -0,0 +1,11 @@
|
||||
fn test() {
|
||||
println('foo')
|
||||
}
|
||||
test()
|
||||
fn test2(a int) {
|
||||
println(a)
|
||||
}
|
||||
test2(42)
|
||||
===output===
|
||||
foo
|
||||
42
|
||||
30
vlib/compiler/tests/repl/immutable_len_fields.repl
Normal file
30
vlib/compiler/tests/repl/immutable_len_fields.repl
Normal file
@@ -0,0 +1,30 @@
|
||||
mut s := 'hello world'
|
||||
s.len = 0 // Error (field len immutable)
|
||||
|
||||
mut a := []string
|
||||
a.len = 0 // Error (field len immutable)
|
||||
|
||||
mut ints := []int
|
||||
ints.len = 0 // Error (field len immutable)
|
||||
|
||||
println('BYE')
|
||||
===output===
|
||||
.vrepl_temp.v:3:5: cannot modify immutable field `len` (type `string`)
|
||||
declare the field with `mut:`
|
||||
struct string {
|
||||
mut:
|
||||
len int
|
||||
}
|
||||
.vrepl_temp.v:4:5: cannot modify immutable field `len` (type `array`)
|
||||
declare the field with `mut:`
|
||||
struct array {
|
||||
mut:
|
||||
len int
|
||||
}
|
||||
.vrepl_temp.v:5:8: cannot modify immutable field `len` (type `array`)
|
||||
declare the field with `mut:`
|
||||
struct array {
|
||||
mut:
|
||||
len int
|
||||
}
|
||||
BYE
|
||||
5
vlib/compiler/tests/repl/interpolation.repl
Normal file
5
vlib/compiler/tests/repl/interpolation.repl
Normal file
@@ -0,0 +1,5 @@
|
||||
a := 'Hello'
|
||||
b := 'World'
|
||||
println('$a $b')
|
||||
===output===
|
||||
Hello World
|
||||
10
vlib/compiler/tests/repl/multiple_decl.repl
Normal file
10
vlib/compiler/tests/repl/multiple_decl.repl
Normal file
@@ -0,0 +1,10 @@
|
||||
name := 'Bob'
|
||||
age := 20
|
||||
large_number := i64(9999999999)
|
||||
println(name)
|
||||
println(age)
|
||||
println(large_number)
|
||||
===output===
|
||||
Bob
|
||||
20
|
||||
9999999999
|
||||
7
vlib/compiler/tests/repl/multiple_println.repl
Normal file
7
vlib/compiler/tests/repl/multiple_println.repl
Normal file
@@ -0,0 +1,7 @@
|
||||
println('Hello World')
|
||||
println('Foo Bar')
|
||||
println('dlroW olleH')
|
||||
===output===
|
||||
Hello World
|
||||
Foo Bar
|
||||
dlroW olleH
|
||||
9
vlib/compiler/tests/repl/naked_strings.repl
Normal file
9
vlib/compiler/tests/repl/naked_strings.repl
Normal file
@@ -0,0 +1,9 @@
|
||||
'abc'
|
||||
'abc'+'xyz'
|
||||
'{'
|
||||
'}'
|
||||
===output===
|
||||
abc
|
||||
abcxyz
|
||||
{
|
||||
}
|
||||
5
vlib/compiler/tests/repl/newlines.repl
Normal file
5
vlib/compiler/tests/repl/newlines.repl
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
|
||||
|
||||
===output===
|
||||
1
vlib/compiler/tests/repl/nothing.repl
Normal file
1
vlib/compiler/tests/repl/nothing.repl
Normal file
@@ -0,0 +1 @@
|
||||
===output===
|
||||
7
vlib/compiler/tests/repl/println.repl
Normal file
7
vlib/compiler/tests/repl/println.repl
Normal file
@@ -0,0 +1,7 @@
|
||||
println('Hello, world!')
|
||||
println('Привет, мир!')
|
||||
println('你好世界')
|
||||
===output===
|
||||
Hello, world!
|
||||
Привет, мир!
|
||||
你好世界
|
||||
40
vlib/compiler/tests/repl/repl_test.v
Normal file
40
vlib/compiler/tests/repl/repl_test.v
Normal file
@@ -0,0 +1,40 @@
|
||||
import os
|
||||
import compiler.tests.repl.runner
|
||||
import benchmark
|
||||
|
||||
fn test_the_v_compiler_can_be_invoked() {
|
||||
vexec := runner.full_path_to_v()
|
||||
println('vexecutable: $vexec')
|
||||
assert vexec != ''
|
||||
|
||||
vcmd := '$vexec --version'
|
||||
r := os.exec(vcmd) or { panic(err) }
|
||||
//println('"$vcmd" exit_code: $r.exit_code | output: $r.output')
|
||||
assert r.exit_code == 0
|
||||
|
||||
vcmd_error := '$vexec nonexisting.v'
|
||||
r_error := os.exec(vcmd_error) or { panic(err) }
|
||||
//println('"$vcmd_error" exit_code: $r_error.exit_code | output: $r_error.output')
|
||||
assert r_error.exit_code == 1
|
||||
assert r_error.output == '`nonexisting.v` does not exist'
|
||||
}
|
||||
|
||||
fn test_all_v_repl_files() {
|
||||
options := runner.new_options()
|
||||
mut bmark := benchmark.new_benchmark()
|
||||
for file in options.files {
|
||||
bmark.step()
|
||||
fres := runner.run_repl_file(options.wd, options.vexec, file) or {
|
||||
bmark.fail()
|
||||
eprintln( bmark.step_message(err) )
|
||||
assert false
|
||||
continue
|
||||
}
|
||||
bmark.ok()
|
||||
println( bmark.step_message(fres) )
|
||||
assert true
|
||||
}
|
||||
bmark.stop()
|
||||
println( bmark.total_message('total time spent running REPL files') )
|
||||
}
|
||||
|
||||
24
vlib/compiler/tests/repl/run.v
Normal file
24
vlib/compiler/tests/repl/run.v
Normal file
@@ -0,0 +1,24 @@
|
||||
module main
|
||||
|
||||
import vcompiler.tests.repl.runner
|
||||
import log
|
||||
import benchmark
|
||||
|
||||
fn main(){
|
||||
logger := &log.Log{log.DEBUG, 'terminal'}
|
||||
options := runner.new_options()
|
||||
|
||||
mut bmark := benchmark.new_benchmark()
|
||||
for file in options.files {
|
||||
bmark.step()
|
||||
fres := runner.run_repl_file(options.wd, options.vexec, file) or {
|
||||
bmark.fail()
|
||||
logger.error( bmark.step_message( err ) )
|
||||
continue
|
||||
}
|
||||
bmark.ok()
|
||||
logger.info( bmark.step_message( fres ) )
|
||||
}
|
||||
bmark.stop()
|
||||
logger.info( bmark.total_message('total time spent running REPL files') )
|
||||
}
|
||||
93
vlib/compiler/tests/repl/runner/runner.v
Normal file
93
vlib/compiler/tests/repl/runner/runner.v
Normal file
@@ -0,0 +1,93 @@
|
||||
module runner
|
||||
|
||||
import os
|
||||
|
||||
struct RunnerOptions {
|
||||
pub:
|
||||
wd string
|
||||
vexec string
|
||||
files []string
|
||||
}
|
||||
|
||||
pub fn full_path_to_v() string {
|
||||
vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
|
||||
vexec := os.dir(os.dir(os.dir(os.dir(os.dir( os.executable() ))))) + os.path_separator + vname
|
||||
/*
|
||||
args := os.args
|
||||
vreal := os.realpath('v')
|
||||
myself := os.realpath( os.executable() )
|
||||
wd := os.getwd() + os.path_separator
|
||||
println('args are: $args')
|
||||
println('vreal : $vreal')
|
||||
println('myself : $myself')
|
||||
println('wd : $wd')
|
||||
*/
|
||||
return vexec
|
||||
}
|
||||
|
||||
fn find_working_diff_command() ?string {
|
||||
for diffcmd in ['colordiff', 'diff', 'colordiff.exe', 'diff.exe'] {
|
||||
p := os.exec('$diffcmd --version') or { continue }
|
||||
if p.exit_code == 0 { return diffcmd }
|
||||
}
|
||||
return error('no working diff command found')
|
||||
}
|
||||
|
||||
fn diff_files( file_result, file_expected string ) string {
|
||||
diffcmd := find_working_diff_command() or { return err }
|
||||
diff := os.exec('$diffcmd --minimal --text --unified=2 $file_result $file_expected') or { return 'found diff command "$diffcmd" does not work' }
|
||||
return diff.output
|
||||
}
|
||||
|
||||
pub fn run_repl_file(wd string, vexec string, file string) ?string {
|
||||
fcontent := os.read_file(file) or { return error('Could not read file $file') }
|
||||
content := fcontent.replace('\r', '')
|
||||
input := content.all_before('===output===\n')
|
||||
output := content.all_after('===output===\n')
|
||||
|
||||
input_temporary_filename := 'input_temporary_filename.txt'
|
||||
os.write_file(input_temporary_filename, input)
|
||||
|
||||
r := os.exec('$vexec runrepl < $input_temporary_filename') or {
|
||||
os.rm(input_temporary_filename)
|
||||
return error('Could not execute "$vexec runrepl < $input_temporary_filename" ')
|
||||
}
|
||||
os.rm(input_temporary_filename)
|
||||
|
||||
result := r.output.replace('\r','').replace('>>> ', '').replace('>>>', '').replace('... ', '').all_after('Use Ctrl-C or `exit` to exit\n').replace(wd, '' )
|
||||
|
||||
if result != output {
|
||||
file_result := '${file}.result.txt'
|
||||
file_expected := '${file}.expected.txt'
|
||||
os.write_file( file_result, result )
|
||||
os.write_file( file_expected, output )
|
||||
diff := diff_files( file_result, file_expected )
|
||||
return error('Difference found in REPL file: $file
|
||||
====> Got :
|
||||
|$result|
|
||||
====> Expected :
|
||||
|$output|
|
||||
====> Diff :
|
||||
$diff
|
||||
')
|
||||
} else {
|
||||
return 'Repl file $file is OK'
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_options() RunnerOptions {
|
||||
wd := os.getwd() + os.path_separator
|
||||
vexec := full_path_to_v()
|
||||
mut files := []string
|
||||
if os.args.len > 1 {
|
||||
files = os.args.right(1)
|
||||
} else {
|
||||
files = os.walk_ext('.', '.repl')
|
||||
}
|
||||
return RunnerOptions {
|
||||
wd: wd
|
||||
vexec: vexec
|
||||
files: files
|
||||
}
|
||||
}
|
||||
|
||||
4
vlib/compiler/tests/repl/var_decl.repl
Normal file
4
vlib/compiler/tests/repl/var_decl.repl
Normal file
@@ -0,0 +1,4 @@
|
||||
a := 1
|
||||
println(a)
|
||||
===output===
|
||||
1
|
||||
23
vlib/compiler/tests/return_voidptr_test.v
Normal file
23
vlib/compiler/tests/return_voidptr_test.v
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
struct Zest { val int }
|
||||
|
||||
fn (t Zest) get_a_finger_to_the_moon() voidptr {
|
||||
return voidptr(0)
|
||||
}
|
||||
|
||||
fn get_the_dao_way() voidptr {
|
||||
return voidptr(0)
|
||||
}
|
||||
|
||||
fn test_returning_a_void_pointer_from_a_method() {
|
||||
t := &Zest{ val: 123 }
|
||||
z := voidptr(0)
|
||||
assert z == t.get_a_finger_to_the_moon()
|
||||
assert t.get_a_finger_to_the_moon() == 0
|
||||
}
|
||||
|
||||
fn test_returning_a_void_pointer_from_a_function() {
|
||||
z := voidptr(0)
|
||||
assert z == get_the_dao_way()
|
||||
assert get_the_dao_way() == 0
|
||||
}
|
||||
18
vlib/compiler/tests/str_gen_test.v
Normal file
18
vlib/compiler/tests/str_gen_test.v
Normal file
@@ -0,0 +1,18 @@
|
||||
struct Foo {
|
||||
number int
|
||||
str string
|
||||
f f64
|
||||
}
|
||||
|
||||
fn test_array_str() {
|
||||
f := Foo{34, 'hello', 1.2}
|
||||
println(f)
|
||||
//s := f.str()
|
||||
//println(s)
|
||||
n := [1, 2, 3]
|
||||
assert n.str() == '[1, 2, 3]'
|
||||
println(n) // make sure the array is printable
|
||||
n2 := [4,5,6]
|
||||
//assert n2.str() == '[4, 5, 6]'
|
||||
println(n2)
|
||||
}
|
||||
29
vlib/compiler/tests/string_interpolation_test.v
Normal file
29
vlib/compiler/tests/string_interpolation_test.v
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
fn test_excape_dollar_in_string() {
|
||||
i := 42
|
||||
|
||||
assert '($i)' == '(42)'
|
||||
assert '(\$i)'.contains('i') && !'(\$i)'.contains('42')
|
||||
assert !'(\\$i)'.contains('i') && '(\\$i)'.contains('42') && '(\\$i)'.contains('\\')
|
||||
assert '(\\\$i)'.contains('i') && !'(\\\$i)'.contains('42') && '(\\$i)'.contains('\\')
|
||||
assert !'(\\\\$i)'.contains('i') && '(\\\\$i)'.contains('42') && '(\\\\$i)'.contains('\\\\')
|
||||
|
||||
assert '(${i})' == '(42)'
|
||||
assert '(\${i})'.contains('i') && !'(\${i})'.contains('42')
|
||||
assert !'(\\${i})'.contains('i') && '(\\${i})'.contains('42') && '(\\${i})'.contains('\\')
|
||||
assert '(\\\${i})'.contains('i') && !'(\\\${i})'.contains('42') && '(\\${i})'.contains('\\')
|
||||
assert !'(\\\\${i})'.contains('i') && '(\\\\${i})'.contains('42') && '(\\\\${i})'.contains('\\\\')
|
||||
assert i==42
|
||||
}
|
||||
|
||||
fn test_implicit_str() {
|
||||
i := 42
|
||||
assert 'int $i' == 'int 42'
|
||||
assert '$i' == '42'
|
||||
|
||||
check := '$i' == '42'
|
||||
assert check
|
||||
|
||||
text := '$i' + '42'
|
||||
assert text == '4242'
|
||||
}
|
||||
120
vlib/compiler/tests/struct_test.v
Normal file
120
vlib/compiler/tests/struct_test.v
Normal file
@@ -0,0 +1,120 @@
|
||||
struct A{
|
||||
mut:
|
||||
val int
|
||||
nums []int
|
||||
}
|
||||
|
||||
struct B{
|
||||
mut:
|
||||
a A
|
||||
}
|
||||
|
||||
struct C {
|
||||
mut:
|
||||
b B
|
||||
nums []int
|
||||
aarr []A
|
||||
num int
|
||||
}
|
||||
|
||||
struct User {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
@type string
|
||||
}
|
||||
|
||||
//We need to make sure that this compiles with all the reserved names.
|
||||
struct ReservedKeywords {
|
||||
delete int
|
||||
exit int
|
||||
unix int
|
||||
error int
|
||||
malloc int
|
||||
calloc int
|
||||
free int
|
||||
panic int
|
||||
auto int
|
||||
char int
|
||||
do int
|
||||
double int
|
||||
extern int
|
||||
float int
|
||||
inline int
|
||||
long int
|
||||
register int
|
||||
restrict int
|
||||
short int
|
||||
signed int
|
||||
typedef int
|
||||
unsigned int
|
||||
void int
|
||||
volatile int
|
||||
while int
|
||||
}
|
||||
|
||||
fn test_struct_levels() {
|
||||
mut c := C{}
|
||||
assert c.nums.len == 0
|
||||
c.nums << 3
|
||||
assert c.nums.len == 1
|
||||
assert c.nums[0] == 3
|
||||
c.nums[0] = 4
|
||||
assert c.nums[0] == 4
|
||||
c.b.a.val = 34
|
||||
assert c.b.a.val == 34
|
||||
c.b.a.nums = [0].repeat(0)
|
||||
c.b.a.nums << 0
|
||||
c.b.a.nums << 2
|
||||
assert c.b.a.nums.len == 2
|
||||
assert c.b.a.nums[0] == 0
|
||||
assert c.b.a.nums[1] == 2
|
||||
c.b.a.nums [0] = 7
|
||||
assert c.b.a.nums[0] == 7
|
||||
c.aarr << A{val:8}
|
||||
assert c.aarr.len == 1
|
||||
assert c.aarr[0].val == 8
|
||||
c.num = 20
|
||||
assert c.num == 20
|
||||
c.aarr[0].val = 10
|
||||
assert c.aarr[0].val == 10
|
||||
}
|
||||
|
||||
fn test_struct_str() {
|
||||
u := User{'Bob', 30}
|
||||
println(u) // make sure the struct is printable
|
||||
// assert u.str() == '{name:"Bob", age:30}' // TODO
|
||||
}
|
||||
|
||||
fn test_at() {
|
||||
foo := Foo{ @type: 'test' }
|
||||
println(foo.@type)
|
||||
}
|
||||
|
||||
fn test_reserved_keywords() {
|
||||
//Make sure we can initialize them correctly using full syntax.
|
||||
rk_holder := ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}
|
||||
//Test a few as it'll take too long to test all. If it's initialized
|
||||
//correctly, other fields are also probably valid.
|
||||
assert rk_holder.unix == 5
|
||||
assert rk_holder.while == 3
|
||||
|
||||
rk_holder2 := ReservedKeywords{inline: 9, volatile: 11}
|
||||
//Make sure partial initialization works too.
|
||||
assert rk_holder2.inline == 9
|
||||
assert rk_holder2.volatile == 11
|
||||
assert rk_holder2.while == 0 //Zero value as not specified.
|
||||
}
|
||||
|
||||
struct User2 {
|
||||
mut:
|
||||
name string
|
||||
}
|
||||
|
||||
fn test_mutable_fields() {
|
||||
mut u := User2{}
|
||||
u.name = 'Peter'
|
||||
assert u.name == 'Peter'
|
||||
}
|
||||
Reference in New Issue
Block a user