ci: vet all files from the compiler (#5994)

pull/5996/head
Enzo 2020-07-27 12:15:29 +02:00 committed by GitHub
parent 1086150ab9
commit 2de1437a1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 650 additions and 643 deletions

View File

@ -45,12 +45,8 @@ jobs:
run: ./v build-tools
- name: v vet
run: |
./v vet vlib/v/scanner
./v vet vlib/v/parser
./v vet vlib/v/ast
./v vet vlib/v/gen/cgen.v
./v vet vlib/v/checker
./v vet vlib/sqlite
./v vet vlib/v
- name: v fmt
run: |
./v fmt -verify vlib/v/checker/checker.v

View File

@ -48,7 +48,7 @@ pub fn (mut b Builder) build_c(v_files []string, out_file string) {
pub fn (mut b Builder) compile_c() {
if os.user_os() != 'windows' && b.pref.ccompiler == 'msvc' {
verror('Cannot build with msvc on ${os.user_os()}')
verror('Cannot build with msvc on $os.user_os()')
}
// cgen.genln('// Generated by V')
// println('compile2()')
@ -57,7 +57,9 @@ pub fn (mut b Builder) compile_c() {
// println(files)
}
$if windows {
b.pref.ccompiler = b.find_win_cc() or { panic(no_compiler_error) }
b.pref.ccompiler = b.find_win_cc() or {
panic(no_compiler_error)
}
}
// v1 compiler files
// v.add_v_files_to_compile()

View File

@ -10,10 +10,13 @@ fn (v &Builder) get_os_cflags() []cflag.CFlag {
ctimedefines << v.pref.compile_defines
}
for flag in v.table.cflags {
if flag.os == '' || (flag.os == 'linux' && v.pref.os == .linux) || (flag.os == 'darwin' &&
v.pref.os == .mac) || (flag.os == 'freebsd' && v.pref.os == .freebsd) || (flag.os == 'windows' &&
v.pref.os == .windows) || (flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler !=
'msvc') || (flag.os == 'solaris' && v.pref.os == .solaris) {
if flag.os == '' ||
(flag.os == 'linux' && v.pref.os == .linux) ||
(flag.os == 'darwin' && v.pref.os == .mac) ||
(flag.os == 'freebsd' && v.pref.os == .freebsd) ||
(flag.os == 'windows' && v.pref.os == .windows) ||
(flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler != 'msvc') ||
(flag.os == 'solaris' && v.pref.os == .solaris) {
flags << flag
}
if flag.os in ctimedefines {

View File

@ -8,7 +8,6 @@ import v.cflag
#flag windows -l shell32
#flag windows -l dbghelp
#flag windows -l advapi32
struct MsvcResult {
full_cl_exe_path string
exe_path string
@ -51,7 +50,8 @@ fn find_windows_kit_internal(key RegKey, versions []string) ?string {
continue
}
//
else{}
else {
}
result2 := C.RegQueryValueEx(key, version.to_wide(), 0, 0, value, &alloc_length)
if result2 != 0 {
continue
@ -143,7 +143,7 @@ fn find_vs(vswhere_dir, host_arch string) ?VsInstallation {
res_output := res.output.trim_right('\r\n')
// println('res: "$res"')
version := os.read_file('$res_output\\VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt') or {
//println('Unable to find msvc version')
// println('Unable to find msvc version')
return error('Unable to find vs installation')
}
version2 := version // TODO remove. cgen option bug if expr
@ -214,13 +214,11 @@ pub fn (mut v Builder) cc_msvc() {
} else {
a << '/MDd'
}
if v.pref.is_debug {
// /Zi generates a .pdb
// /Fd sets the pdb file name (so its not just vc140 all the time)
a << ['/Zi', '/Fd"$out_name_pdb"']
}
if v.pref.is_shared {
if !v.pref.out_name.ends_with('.dll') {
v.pref.out_name += '.dll'
@ -261,7 +259,7 @@ pub fn (mut v Builder) cc_msvc() {
// Not all of these are needed (but the compiler should discard them if they are not used)
// these are the defaults used by msbuild and visual studio
mut real_libs := ['kernel32.lib', 'user32.lib', 'advapi32.lib']
//sflags := v.get_os_cflags().msvc_string_flags()
// sflags := v.get_os_cflags().msvc_string_flags()
sflags := msvc_string_flags(v.get_os_cflags())
real_libs << sflags.real_libs
inc_paths := sflags.inc_paths
@ -324,7 +322,6 @@ pub fn (mut v Builder) cc_msvc() {
fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags []cflag.CFlag) {
msvc := v.cached_msvc
if msvc.valid == false {
verror('Cannot find MSVC on this OS')
return
@ -368,7 +365,7 @@ mut:
other_flags []string
}
//pub fn (cflags []CFlag) msvc_string_flags() MsvcStringFlags {
// pub fn (cflags []CFlag) msvc_string_flags() MsvcStringFlags {
pub fn msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
mut real_libs := []string{}
mut inc_paths := []string{}

View File

@ -17,7 +17,6 @@ pub fn (mut b Builder) build_x64(v_files []string, out_file string) {
t1 := time.ticks()
parse_time := t1 - t0
b.timing_message('PARSE', parse_time)
b.checker.check_files(b.parsed_files)
t2 := time.ticks()
check_time := t2 - t1

View File

@ -18,7 +18,8 @@ fn test_all() {
// -prod so that warns are errors
total_errors += check_path(vexe, classic_dir, '-prod', '.out', classic_tests)
total_errors += check_path(vexe, global_dir, '--enable-globals', '.out', global_tests)
total_errors += check_path(vexe, classic_dir, '--enable-globals run', '.run.out', ['globals_error.vv'])
total_errors += check_path(vexe, classic_dir, '--enable-globals run', '.run.out',
['globals_error.vv'])
total_errors += check_path(vexe, run_dir, 'run', '.run.out', run_tests)
total_errors += check_path(vexe, parser_dir, '-prod', '.out', parser_tests)
assert total_errors == 0
@ -76,7 +77,7 @@ fn check_path(vexe, dir, voptions, result_extension string, tests []string) int
println('found:')
println(found)
println('============\n')
diff_content( expected, found )
diff_content(expected, found)
nb_fail++
} else {
println(term.green('OK'))
@ -95,9 +96,11 @@ fn clean_line_endings(s string) string {
return res
}
fn diff_content(s1 string, s2 string) {
diff_cmd := util.find_working_diff_command() or { return }
fn diff_content(s1, s2 string) {
diff_cmd := util.find_working_diff_command() or {
return
}
println('diff: ')
println( util.color_compare_strings(diff_cmd, s1, s2) )
println(util.color_compare_strings(diff_cmd, s1, s2))
println('============\n')
}

View File

@ -914,7 +914,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
}
ast.PrefixExpr {
f.write(node.op.str())
f.prefix_expr_cast_expr( node.right )
f.prefix_expr_cast_expr(node.right)
}
ast.RangeExpr {
f.expr(node.low)
@ -1274,12 +1274,8 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
else {}
}
match node.right as right {
ast.InfixExpr {
penalty--
}
ast.ParExpr {
penalty = 1
}
ast.InfixExpr { penalty-- }
ast.ParExpr { penalty = 1 }
else {}
}
f.penalties << penalty
@ -1311,8 +1307,8 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
}
pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
single_line := it.branches.len == 2 && it.has_else &&
it.branches[0].stmts.len == 1 && it.branches[1].stmts.len == 1 &&
single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == 1 &&
it.branches[1].stmts.len == 1 &&
(it.is_expr || f.is_assign)
f.single_line_if = single_line
for i, branch in it.branches {
@ -1321,11 +1317,9 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
if branch.cond is ast.InfixExpr {
infix := branch.cond as ast.InfixExpr
if infix.op == .key_is &&
(infix.left is ast.Ident || infix.left is ast.SelectorExpr) &&
infix.right is ast.Type {
//right_expr := infix.right as ast.Type
is_variable = if infix.left is ast.Ident { (infix.left as ast.Ident).kind ==
.variable } else { true }
(infix.left is ast.Ident || infix.left is ast.SelectorExpr) && infix.right is ast.Type {
// right_expr := infix.right as ast.Type
is_variable = if infix.left is ast.Ident { (infix.left as ast.Ident).kind == .variable } else { true }
}
}
if i == 0 {
@ -1661,15 +1655,12 @@ pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
}
mut penalty := if f.array_init_break[f.array_init_depth - 1] { 0 } else { 3 }
if penalty > 0 {
if i == 0 ||
it.exprs[i - 1] is ast.ArrayInit ||
it.exprs[i - 1] is ast.StructInit ||
if i == 0 || it.exprs[i - 1] is ast.ArrayInit || it.exprs[i - 1] is ast.StructInit ||
it.exprs[i - 1] is ast.MapInit || it.exprs[i - 1] is ast.CallExpr {
penalty--
}
if expr is ast.ArrayInit ||
expr is ast.StructInit || expr is ast.MapInit ||
expr is ast.CallExpr {
expr is ast.StructInit || expr is ast.MapInit || expr is ast.CallExpr {
penalty--
}
}
@ -1786,10 +1777,10 @@ pub fn (mut f Fmt) const_decl(it ast.ConstDecl) {
}
fn (mut f Fmt) is_external_name(name string) bool {
if name.len > 2 && name[0]==`C` && name[1]==`.` {
if name.len > 2 && name[0] == `C` && name[1] == `.` {
return true
}
if name.len > 3 && name[0]==`J` && name[1]==`S` && name[2] == `.` {
if name.len > 3 && name[0] == `J` && name[1] == `S` && name[2] == `.` {
return true
}
return false

View File

@ -11,6 +11,8 @@ fn vararg_test() {
variadic(1, 2, 3)
}
// TODO Remove `fn main` once vet supports scripts
fn main() {
vararg_test()
arr1 := ['Hello', 'JS', 'Backend']
@ -118,3 +120,4 @@ $f1
$f2
$f3
$f4')
}

View File

@ -6,6 +6,8 @@ enum Test {
baz
}
// TODO Remove `fn main` once vet supports scripts
fn main() {
mut a := hello.Ccc.a
a = .b
a = .c
@ -15,3 +17,4 @@ println(a)
mut b := Test.foo
b = .bar
println(b)
}

View File

@ -27,87 +27,73 @@ fn class(extends string, instanceof int) {
_ = delete
}
fn main() {
println('Hello from V.js!')
println(JS.Math.atan2(1, 0))
mut a := 1
a *= 2
a += 3
println(a) // TODO: Handle string interpolation
mut b := hl.Aaa{}
b.update('an update')
println(b)
mut c := Foo{ hl.Aaa{} }
mut c := Foo{hl.Aaa{}}
c.a.update('another update')
println(c)
_ = "done"
_ = 'done'
{
_ = "block"
_ = 'block'
}
_ = POSITION.go_back
_ = hl.Ccc.a
debugger := 'JS keywords'
// TODO: Implement interpolation
await := '$super: $debugger'
mut finally := 'implemented'
println('$await $finally')
dun := i_am_a_const * 20
dunn := hl.hello // External constant
_ = hl1.nested()
for i := 0; i < 10; i++ {}
for i, x in 'hello' {}
for x in 1..10 {}
arr := [1,2,3,4,5]
for i in arr {}
ma := {
'str': "done"
'ddo': "baba"
for i := 0; i < 10; i++ {
}
for i, x in 'hello' {
}
for x in 1 .. 10 {
}
arr := [1, 2, 3, 4, 5]
for i in arr {
}
ma := {
'str': 'done'
'ddo': 'baba'
}
// panic('foo')
for m, n in ma {
iss := m
}
go async(0, "hello")
go async(0, 'hello')
fn_in_var := fn (number int) {
println("number: $number")
println('number: $number')
}
hl.debugger()
anon_consumer(hl.excited(), fn (message string) {
println(message)
})
hl.raw_js_log()
}
fn anon_consumer (greeting string, anon fn(message string)) {
fn anon_consumer(greeting string, anon fn (message string)) {
anon(greeting)
}
fn async(num int, def string) {}
fn async(num int, def string) {
}
[inline]
[deprecated]
fn hello(game_on int, dummy ...string) (int, int) {
defer {
do := "not"
do := 'not'
}
for dd in dummy {
l := dd
@ -116,18 +102,20 @@ fn hello(game_on int, dummy ...string) (int, int) {
}
fn (it Companies) method() int {
ss := Companies {
ss := Companies{
google: 2
amazon: true
yahoo: "hello"
yahoo: 'hello'
}
a, b := hello(2, 'google', 'not google')
glue := if a > 2 { 'more_glue' } else if a > 5 {'more glueee'} else { 'less glue' }
if a != 2 {}
glue := if a > 2 {
'more_glue'
} else if a > 5 {
'more glueee'
} else {
'less glue'
}
if a != 2 {
}
return 0
}

View File

@ -51,6 +51,8 @@ fn show(game [][]bool) {
}
}
// TODO Remove `fn main` once vet supports scripts
fn main() {
mut game := [][]bool{ len: h, init: []bool{ len: w } }
game[11][15] = true
@ -62,3 +64,4 @@ game[12][21] = true
game[12][22] = true
JS.setInterval(fn () { show(game) game = step(game) }, 500)
}

View File

@ -20,17 +20,21 @@ struct Config {
bar string
}
fn use_config(c Config) {}
fn use_config(c Config) {
}
fn main() {
mut a := Int { value: 10 }
mut a := Int{
value: 10
}
a.add(5)
println(a) // 15
mut b := Int{}
b.add(10)
println(b.get()) // 10
use_config(Config{ 2, 'bar' })
use_config(foo: 2, bar: 'bar')
use_config(Config{2, 'bar'})
use_config({
foo: 2
bar: 'bar'
})
}

View File

@ -23,7 +23,7 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
mut enc := strings.new_builder(100)
sym := g.table.get_type_symbol(typ)
styp := g.typ(typ)
if is_js_prim(sym.name) || sym.kind == .enum_{
if is_js_prim(sym.name) || sym.kind == .enum_ {
return
}
if sym.kind == .array {
@ -38,7 +38,6 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
// cJSON_Parse(str) call is added by the compiler
// Code gen decoder
dec_fn_name := js_dec_name(sym.name)
// Make sure that this optional type actually exists
g.register_optional(typ)
dec_fn_dec := 'Option_$styp ${dec_fn_name}(cJSON* root)'
@ -49,15 +48,14 @@ $dec_fn_dec {
if (!root) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
// fprintf(stderr, "Error in decode() for $styp error_ptr=: %%s\\n", error_ptr);
// printf("\\nbad js=%%s\\n", js.str);
// fprintf(stderr, "Error in decode() for $styp error_ptr=: %%s\\n", error_ptr);
// printf("\\nbad js=%%s\\n", js.str);
Option err = v_error(tos2(error_ptr));
return *(Option_$styp *)&err;
}
}
')
g.json_forward_decls.writeln('$dec_fn_dec;')
// Code gen encoder
// encode_TYPE funcs receive an object to encode
enc_fn_name := js_enc_name(sym.name)
@ -107,11 +105,9 @@ $enc_fn_dec {
dec.writeln(' res . ${c_name(field.name)} = *($field_type*) $dec_name (js_get(root,"$name")).data;')
}
}
mut enc_name := js_enc_name(field_type)
if g.table.get_type_symbol(field.typ).kind == .enum_ {
enc.writeln('\tcJSON_AddItemToObject(o, "$name", json__encode_u64(val.${c_name(field.name)}));')
} else {
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.${c_name(field.name)}));')
}

View File

@ -40,12 +40,13 @@ fn (mut g Gen) generate_hotcode_reloader_code() {
mut load_code := []string{}
if g.pref.os != .windows {
for so_fn in g.hotcode_fn_names {
load_code << 'impl_live_${so_fn} = dlsym(live_lib, "impl_live_${so_fn}");'
load_code << 'impl_live_$so_fn = dlsym(live_lib, "impl_live_$so_fn");'
}
phd = posix_hotcode_definitions_1
} else {
for so_fn in g.hotcode_fn_names {
load_code << 'impl_live_${so_fn} = (void *)GetProcAddress(live_lib, "impl_live_${so_fn}"); '
load_code <<
'impl_live_$so_fn = (void *)GetProcAddress(live_lib, "impl_live_$so_fn"); '
}
phd = windows_hotcode_definitions_1
}
@ -76,10 +77,10 @@ fn (mut g Gen) generate_hotcode_reloading_main_caller() {
g.writeln('\t{')
g.writeln('\t\t// initialization of live function pointers')
for fname in g.hotcode_fn_names {
g.writeln('\t\timpl_live_${fname} = 0;')
g.writeln('\t\timpl_live_$fname = 0;')
}
vexe := util.cescaped_path( pref.vexe_path() )
file := util.cescaped_path( g.pref.path )
vexe := util.cescaped_path(pref.vexe_path())
file := util.cescaped_path(g.pref.path)
msvc := if g.pref.ccompiler == 'msvc' { '-cc msvc' } else { '' }
so_debug_flag := if g.pref.is_debug { '-cg' } else { '' }
vopts := '$msvc $so_debug_flag -sharedlive -shared'

View File

@ -4,6 +4,8 @@ import v.ast
import v.table
fn (mut p Parser) lock_expr() ast.LockExpr {
// TODO Handle aliasing sync
p.register_used_import('sync')
pos := p.tok.position()
is_rlock := p.tok.kind == .key_rlock
p.next()

View File

@ -30,15 +30,16 @@ fn (mut p Parser) register_used_import(alias string) {
}
fn (mut p Parser) check_unused_imports() {
if p.pref.is_repl {
if p.pref.is_repl || p.pref.is_fmt {
// The REPL should be much more liberal, and should not warn about
// unused imports, because they probably will be in the next few lines...
// vfmt doesn't care about unused imports either
return
}
for import_m in p.ast_imports {
alias := import_m.alias
mod := import_m.mod
if !p.is_used_import(alias) && !p.pref.is_fmt {
if !p.is_used_import(alias) {
mod_alias := if alias == mod { alias } else { '$alias ($mod)' }
p.warn_with_pos("module '$mod_alias' is imported but never used", import_m.pos)
}

View File

@ -15,8 +15,8 @@ import strings
pub type Type int
pub type TypeInfo = Alias | Array | ArrayFixed | Enum | FnType | Interface | Map | MultiReturn |
Struct | GenericStructInst | SumType
pub type TypeInfo = Alias | Array | ArrayFixed | Enum | FnType | GenericStructInst | Interface |
Map | MultiReturn | Struct | SumType
pub enum Language {
v
@ -46,10 +46,9 @@ pub enum TypeFlag {
}
/*
To save precious TypeFlag bits the 4 possible ShareTypes are coded in the two
To save precious TypeFlag bits the 4 possible ShareTypes are coded in the two
bits `shared` and `atomic_or_rw` (see sharetype_from_flags() below).
*/
pub enum ShareType {
mut_t
shared_t
@ -127,7 +126,6 @@ pub fn (t Type) to_ptr() Type {
if nr_muls == 255 {
panic('to_ptr: nr_muls is already at max of 255')
}
return int(t) & 0xff00ffff | ((nr_muls + 1) << 16)
}
@ -263,24 +261,12 @@ pub const (
pub const (
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
u16_type_idx,
u32_type_idx,
u64_type_idx,
any_int_type_idx
]
u16_type_idx, u32_type_idx, u64_type_idx, any_int_type_idx]
signed_integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx]
unsigned_integer_type_idxs = [byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx]
float_type_idxs = [f32_type_idx, f64_type_idx, any_flt_type_idx]
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx,
i64_type_idx, byte_type_idx,
u16_type_idx,
u32_type_idx,
u64_type_idx,
f32_type_idx,
f64_type_idx,
any_int_type_idx,
any_flt_type_idx
]
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
u16_type_idx, u32_type_idx, u64_type_idx, f32_type_idx, f64_type_idx, any_int_type_idx, any_flt_type_idx]
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
string_type_idxs = [string_type_idx, ustring_type_idx]
)
@ -314,13 +300,9 @@ pub const (
)
pub const (
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64',
'u16',
'u32',
'u64', 'any_int', 'f32', 'f64', 'any_float', 'string', 'ustring', 'char', 'byte',
'bool', 'none', 'array', 'array_fixed',
'map', 'any', 'struct',
'mapnode', 'size_t']
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16',
'u32', 'u64', 'any_int', 'f32', 'f64', 'any_float', 'string', 'ustring', 'char', 'byte', 'bool',
'none', 'array', 'array_fixed', 'map', 'any', 'struct', 'mapnode', 'size_t']
)
pub struct MultiReturn {

View File

@ -3,85 +3,66 @@ import table
fn test_idx() {
mut t := table.new_type(table.void_type_idx)
assert t.idx() == table.void_type_idx
t = table.new_type(table.i8_type_idx)
assert t.idx() == table.i8_type_idx
}
fn test_muls() {
mut t := table.new_type(table.void_type_idx)
idx := t.idx()
assert t.nr_muls() == 0
for i in 0..32 {
for i in 0 .. 32 {
t = t.set_nr_muls(i)
assert t.nr_muls() == i
}
t = t.set_nr_muls(0)
assert t.nr_muls() == 0
assert t.is_ptr() == false
t = t.to_ptr()
assert t.nr_muls() == 1
assert t.is_ptr() == true
t = t.to_ptr()
assert t.nr_muls() == 2
assert t.is_ptr() == true
t = t.deref()
assert t.nr_muls() == 1
assert t.is_ptr() == true
t = t.deref()
assert t.nr_muls() == 0
assert t.is_ptr() == false
assert t.idx() == idx
}
fn test_flags() {
mut t := table.new_type(table.void_type_idx)
idx := t.idx()
nr_muls := t.nr_muls()
t = t.set_flag(table.TypeFlag.optional)
assert t.has_flag(table.TypeFlag.optional) == true
assert t.has_flag(table.TypeFlag.variadic) == false
assert t.has_flag(table.TypeFlag.generic) == false
t = t.set_flag(table.TypeFlag.variadic)
assert t.has_flag(table.TypeFlag.optional) == true
assert t.has_flag(table.TypeFlag.variadic) == true
assert t.has_flag(table.TypeFlag.generic) == false
t = t.set_flag(table.TypeFlag.generic)
assert t.has_flag(table.TypeFlag.optional) == true
assert t.has_flag(table.TypeFlag.variadic) == true
assert t.has_flag(table.TypeFlag.generic) == true
assert t.idx() == idx
assert t.nr_muls() == nr_muls
t = t.clear_flag(table.TypeFlag.optional)
assert t.has_flag(table.TypeFlag.optional) == false
assert t.has_flag(table.TypeFlag.variadic) == true
assert t.has_flag(table.TypeFlag.generic) == true
t = t.clear_flag(table.TypeFlag.variadic)
assert t.has_flag(table.TypeFlag.optional) == false
assert t.has_flag(table.TypeFlag.variadic) == false
assert t.has_flag(table.TypeFlag.generic) == true
t = t.clear_flag(table.TypeFlag.generic)
assert t.has_flag(table.TypeFlag.optional) == false
assert t.has_flag(table.TypeFlag.variadic) == false
assert t.has_flag(table.TypeFlag.generic) == false
assert t.idx() == idx
assert t.nr_muls() == nr_muls
}
@ -91,12 +72,10 @@ fn test_derive() {
t = t.set_flag(table.TypeFlag.generic)
t = t.set_flag(table.TypeFlag.variadic)
t = t.set_nr_muls(10)
mut t2 := table.new_type(table.i16_type_idx)
t2 = t2.derive(t)
assert t2.has_flag(table.TypeFlag.optional) == false
assert t2.has_flag(table.TypeFlag.variadic) == true
assert t2.has_flag(table.TypeFlag.generic) == true
assert t2.nr_muls() == 10
}

View File

@ -19,7 +19,7 @@ fn test_parse_valid_cflags() {
make_flag('darwin', '-framework', 'Cocoa'),
make_flag('windows', '-l', 'gdi32'),
make_flag(no_os, '-l', 'mysqlclient'),
make_flag(no_os, no_name, '-test')
make_flag(no_os, no_name, '-test'),
]
parse_valid_flag(mut t, '-lmysqlclient')
parse_valid_flag(mut t, '-test')
@ -54,8 +54,7 @@ fn test_parse_invalid_cflags() {
}
fn parse_valid_flag(mut t table.Table, flag string) {
t.parse_cflag(flag, module_name, cdefines) or {
}
t.parse_cflag(flag, module_name, cdefines) or { }
}
fn assert_parse_invalid_flag(mut t table.Table, flag string) {

View File

@ -194,7 +194,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
return &t.types[idx]
}
// this should never happen
panic('get_type_symbol: invalid type (typ=$typ idx=${idx}). Compiler bug. This should never happen')
panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen')
}
// get_final_type_symbol follows aliases until it gets to a "real" Type
@ -210,7 +210,7 @@ pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol {
return &t.types[idx]
}
// this should never happen
panic('get_final_type_symbol: invalid type (typ=$typ idx=${idx}). Compiler bug. This should never happen')
panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen')
}
[inline]
@ -245,8 +245,7 @@ pub fn (mut t Table) register_builtin_type_symbol(typ TypeSymbol) int {
typ |
kind: existing_type.kind
}
}
else {
} else {
t.types[existing_idx] = typ
}
}
@ -296,7 +295,7 @@ pub fn (t &Table) known_type(name string) bool {
[inline]
pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
elem_type_sym := t.get_type_symbol(elem_type)
return 'array_${elem_type_sym.name}' + if elem_type.is_ptr() {
return 'array_$elem_type_sym.name' + if elem_type.is_ptr() {
'_ptr'.repeat(elem_type.nr_muls())
} else {
''
@ -310,7 +309,7 @@ pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
[inline]
pub fn (t &Table) array_fixed_name(elem_type Type, size, nr_dims int) string {
elem_type_sym := t.get_type_symbol(elem_type)
return 'array_fixed_${elem_type_sym.name}_${size}' + if elem_type.is_ptr() {
return 'array_fixed_${elem_type_sym.name}_$size' + if elem_type.is_ptr() {
'_ptr'
} else {
''
@ -326,7 +325,7 @@ pub fn (t &Table) map_name(key_type, value_type Type) string {
key_type_sym := t.get_type_symbol(key_type)
value_type_sym := t.get_type_symbol(value_type)
suffix := if value_type.is_ptr() { '_ptr' } else { '' }
return 'map_${key_type_sym.name}_${value_type_sym.name}' + suffix
return 'map_${key_type_sym.name}_$value_type_sym.name' + suffix
// return 'map_${value_type_sym.name}' + suffix
}
@ -489,7 +488,7 @@ pub fn (t &Table) mktyp(typ Type) Type {
// this is not optimal
pub fn (table &Table) qualify_module(mod, file_path string) string {
for m in table.imports {
//if m.contains('gen') { println('qm=$m') }
// if m.contains('gen') { println('qm=$m') }
if m.contains('.') && m.contains(mod) {
m_parts := m.split('.')
m_path := m_parts.join(os.path_separator)
@ -512,12 +511,11 @@ pub fn (mut table Table) register_fn_gen_type(fn_name string, typ Type) {
table.fn_gen_types[fn_name] = a
}
// TODO: there is a bug when casting sumtype the other way if its pointer
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
pub fn (table &Table) sumtype_has_variant(parent, variant Type) bool {
parent_sym := table.get_type_symbol(parent)
if parent_sym.kind ==.sum_type {
if parent_sym.kind == .sum_type {
parent_info := parent_sym.info as SumType
for v in parent_info.variants {
if v.idx() == variant.idx() {
@ -529,4 +527,5 @@ pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
}
}
return false
}

View File

@ -4,7 +4,7 @@ const (
my_random_letter_const = byte(65 + rand.u32n(25))
)
fn test_rand_is_initialized_before_main(){
fn test_rand_is_initialized_before_main() {
eprintln('random letter: $my_random_letter_const.str() | ASCII code: $my_random_letter_const')
assert my_random_letter_const.is_capital()
}

View File

@ -68,7 +68,6 @@ fn mut_arg<T>(mut x T) {
println(x.name) // = 'foo'
}
fn mut_arg2<T>(mut x T) T {
println(x.name) // = 'foo'
return x
@ -183,7 +182,6 @@ fn test_generic_fn_in_for_in_expression() {
}
}
*/
// test generic struct
struct DB {
driver string
@ -200,7 +198,7 @@ pub mut:
name string
}
struct Repo<T,U> {
struct Repo<T, U> {
db DB
pub mut:
model T
@ -211,30 +209,29 @@ pub mut:
// fn new_repo<T>(db DB) Repo<T,U> {
// return Repo<T,Permission>{db: db}
// }
fn test_generic_struct() {
mut a := Repo<User,Permission>{
model: User{name: 'joe'}
mut a := Repo<User, Permission>{
model: User{
name: 'joe'
}
}
// a.model.name = 'joe'
assert a.model.name == 'joe'
println('a.model.name: $a.model.name')
mut b := Repo<Group,Permission>{
permission: Permission{name: 'superuser'}
mut b := Repo<Group, Permission>{
permission: Permission{
name: 'superuser'
}
}
b.model.name = 'admins'
assert b.model.name == 'admins'
assert b.permission.name == 'superuser'
println('b.model.name: $b.model.name')
println('b.permission.name: $b.permission.name')
assert typeof(a.model) == 'User'
assert typeof(b.model) == 'Group'
println('typeof(a.model): ' + typeof(a.model))
println('typeof(b.model): ' + typeof(b.model))
// mut x := new_repo<User>(DB{})
// x.model.name = 'joe2'
// println(x.model.name)

View File

@ -217,5 +217,5 @@ fn test_optimized_in_expression_with_string() {
fn test_in_array_init() {
assert 1 !in []int{}
assert [1] in [[1]]
assert [1] in [[1], [2]]
}

View File

@ -6,7 +6,9 @@ fn test_all() {
mut total_errors := 0
vexe := os.getenv('VEXE')
vroot := os.dir(vexe)
diff_cmd := util.find_working_diff_command() or { '' }
diff_cmd := util.find_working_diff_command() or {
''
}
dir := 'vlib/v/tests/inout'
files := os.ls(dir) or {
panic(err)
@ -70,8 +72,8 @@ fn test_all() {
expected = expected.trim_right('\r\n').replace('\r\n', '\n')
if expected.contains('================ V panic ================') {
// panic include backtraces and absolute file paths, so can't do char by char comparison
n_found := normalize_panic_message( found, vroot )
n_expected := normalize_panic_message( expected, vroot )
n_found := normalize_panic_message(found, vroot)
n_expected := normalize_panic_message(expected, vroot)
if found.contains('================ V panic ================') {
if n_found.contains(n_expected) {
println(term.green('OK (panic)'))
@ -87,12 +89,12 @@ fn test_all() {
}
if expected != found {
println(term.red('FAIL'))
println(term.header('expected:','-'))
println(term.header('expected:', '-'))
println(expected)
println(term.header('found:','-'))
println(term.header('found:', '-'))
println(found)
if diff_cmd != '' {
println(term.header('difference:','-'))
println(term.header('difference:', '-'))
println(util.color_compare_strings(diff_cmd, expected, found))
} else {
println(term.h_divider('-'))
@ -105,7 +107,7 @@ fn test_all() {
assert total_errors == 0
}
fn normalize_panic_message(message string, vroot string) string {
fn normalize_panic_message(message, vroot string) string {
mut msg := message.all_before('=========================================')
msg = msg.replace(vroot + os.path_separator, '')
msg = msg.trim_space()

View File

@ -1,5 +1,3 @@
import os
fn main() {
println('hello world')
}

View File

@ -1,5 +1,3 @@
import os
fn main() {
areas := ['game', 'web', 'tools', 'science', 'systems', 'embedded']
for i :=0; i < areas.len; i++{

View File

@ -1,4 +1,3 @@
fn main() {
test := 'hello'
hello := 'world'

27
vlib/v/tests/live_test.v 100755 → 100644
View File

@ -27,7 +27,6 @@ not very flaky way.
TODO: Cleanup this when/if v has better process control/communication primitives.
*/
const (
vexe = os.getenv('VEXE')
tmp_file = os.join_path(os.temp_dir(), 'generated_live_program.tmp.v')
@ -98,12 +97,12 @@ fn main() {
"
)
fn atomic_write_source( source string ){
fn atomic_write_source(source string) {
// NB: here wrtiting is done in 2 steps, since os.write_file can take some time,
// during which the file will be modified, but it will still be not completely written.
// The os.mv after that, guarantees that the reloader will see a complete valid V program.
os.write_file(tmp_file, source)
os.mv(tmp_file, source_file )
os.mv(tmp_file, source_file)
}
//
@ -114,13 +113,15 @@ fn testsuite_begin() {
eprintln('You can still do it by setting FORCE_LIVE_TEST=1 .')
exit(0)
}
for f in [ tmp_file, source_file, output_file, res_original_file, res_changed_file, res_another_file, res_stop_file] {
for f in [tmp_file, source_file, output_file, res_original_file, res_changed_file, res_another_file,
res_stop_file,
] {
os.rm(f)
}
atomic_write_source( live_program_source )
atomic_write_source(live_program_source)
}
[if debuglivetest]
[debuglivetest]
fn vprintln(s string) {
eprintln(s)
}
@ -132,36 +133,36 @@ fn testsuite_end() {
output_lines := os.read_lines(output_file) or {
panic('could not read $output_file, error: $err')
}
mut histogram := map[string]int
mut histogram := map[string]int{}
for line in output_lines {
histogram[line] = histogram[line] + 1
}
for k, v in histogram {
eprintln('> found ${v:5d} times: ${k}')
eprintln('> found ${v:5d} times: $k')
}
vprintln('---------------------------------------------------------------------------')
assert histogram['START'] > 0
assert histogram['ORIGINAL'] > 0
assert histogram['CHANGED'] + histogram['ANOTHER'] > 0
//assert histogram['END'] > 0
// assert histogram['END'] > 0
}
fn change_source(new string) {
time.sleep_ms(100)
vprintln('> change ORIGINAL to: $new')
atomic_write_source( live_program_source.replace('ORIGINAL', new) )
atomic_write_source(live_program_source.replace('ORIGINAL', new))
wait_for_file(new)
}
fn wait_for_file(new string){
fn wait_for_file(new string) {
time.sleep_ms(100)
expected_file := os.join_path(os.temp_dir(), new + '.txt')
eprintln('waiting for $expected_file ...')
for i:=0 ; i <= 400 ; i++ {
for i := 0; i <= 400; i++ {
if i % 25 == 0 {
vprintln(' checking ${i:-10d} for $expected_file ...')
}
if os.exists( expected_file ) {
if os.exists(expected_file) {
assert true
vprintln('> done.')
time.sleep_ms(100)

View File

@ -12,13 +12,19 @@ fn test_match_integers() {
mut a := 3
mut b := 0
match a {
2 { println('two') }
2 {
println('two')
}
3 {
println('three')
b = 3
}
4 { println('four') }
else { println('???') }
4 {
println('four')
}
else {
println('???')
}
}
assert b == 3
assert match 2 {
@ -36,8 +42,12 @@ fn test_match_integers() {
} == 5
a = 0
match 2 {
0 { a = 1 }
1 { a = 2 }
0 {
a = 1
}
1 {
a = 2
}
else {
a = 3
println('a is $a')
@ -46,7 +56,9 @@ fn test_match_integers() {
assert a == 3
a = 0
match 1 {
0 { a = 1 }
0 {
a = 1
}
1 {
a = 2
a = a + 2
@ -83,18 +95,24 @@ fn test_match_range() {
fn test_match_enums() {
mut b := Color.red
match b {
.red { b = .green }
.green { b = .blue }
.red {
b = .green
}
.green {
b = .blue
}
else {
println('b is ${b.str()}')
println('b is $b.str()')
b = .red
}
}
assert b == .green
match b {
.red { b = .green }
.red {
b = .green
}
else {
println('b is ${b.str()}')
println('b is $b.str()')
b = .blue
}
}
@ -106,23 +124,22 @@ type Sum = A1 | B1
struct A1 {
pos int
}
struct B1 {
val string
}
fn f(s Sum) string {
match s {
A1 {
return typeof(s)
}
B1 {
return ''
}
A1 { return typeof(s) }
B1 { return '' }
}
return ''
}
fn test_sum_type_name() {
a := A1{pos: 22}
a := A1{
pos: 22
}
assert f(a) == 'A1'
}

View File

@ -2,7 +2,6 @@ module amodule
// This tests whether _test.v files can be *internal* to a
// module, and thus have access to its guts.
// NB: the function test_private_isub() is defined both here
// and inside internal_module_test.v . That is done on purpose,
// with the goal of ensuring that _test.v files are compiled
@ -10,7 +9,6 @@ module amodule
//
// _test.v files should *only* import all the other normal .v
// files from the same folder, NOT other _test.v files from it.
fn test_private_isub(){
assert private_isub(7,5) == 2
fn test_private_isub() {
assert private_isub(7, 5) == 2
}

View File

@ -2,15 +2,14 @@ module amodule
// this tests whether _test.v files can be *internal*
// to a module, and thus have access to its guts.
fn test_iadd(){
fn test_iadd() {
assert iadd(10, 20) == 30
}
fn test_imul(){
assert imul(5,8) == 40
fn test_imul() {
assert imul(5, 8) == 40
}
fn test_private_isub(){
assert private_isub(10,6) == 4
fn test_private_isub() {
assert private_isub(10, 6) == 4
}

View File

@ -1,15 +1,14 @@
module amodule
pub fn iadd(x int, y int) int {
pub fn iadd(x, y int) int {
return x + y
}
pub fn imul(x int, y int) int {
pub fn imul(x, y int) int {
return x * y
}
///////////////////////////////////////
fn private_isub(x int, y int) int {
// /////////////////////////////////////
fn private_isub(x, y int) int {
return x - y
}

View File

@ -8,7 +8,10 @@ fn new_st() MyStruct {
fn get_st() MyStruct {
r := new_st()
return {r|s:'6'}
return {
r |
s: '6'
}
}
fn main() {

View File

@ -2,7 +2,7 @@ module main
import mod1
fn main(){
res := mod1.vadd(1,2)
println( res )
fn main() {
res := mod1.vadd(1, 2)
println(res)
}

View File

@ -1,6 +1,6 @@
import mod1.submodule as m
fn test_mod1_can_still_be_found_through_parent_project_vmod(){
fn test_mod1_can_still_be_found_through_parent_project_vmod() {
assert 1051 == m.f()
}

View File

@ -1,11 +1,10 @@
import mod1
import mod1.submodule
fn test_mod1(){
fn test_mod1() {
assert 1 == mod1.f()
}
fn test_mod1_submodule_can_find_and_use_all_its_sibling_submodules(){
fn test_mod1_submodule_can_find_and_use_all_its_sibling_submodules() {
assert 1051 == submodule.f()
}

View File

@ -1,9 +1,8 @@
fn iadd(x int, y int) int {
fn iadd(x, y int) int {
return x + y
}
fn main(){
fn main() {
println('Hello world')
println('iadd: ' + iadd(1,2).str())
println('iadd: ' + iadd(1, 2).str())
}

View File

@ -1,6 +1,7 @@
module main
fn test_iadd_3_4(){
a := iadd(3,4)
fn test_iadd_3_4() {
a := iadd(3, 4)
assert a == 7
assert iadd(10,20) == 30
assert iadd(10, 20) == 30
}

View File

@ -1,9 +1,11 @@
module main
fn test_iadd_3_4(){
a := iadd(3,4)
fn test_iadd_3_4() {
a := iadd(3, 4)
assert a == 7
}
fn test_iadd_5_6(){
a := iadd(5,6)
fn test_iadd_5_6() {
a := iadd(5, 6)
assert a == 11
}

View File

@ -34,47 +34,41 @@ pub fn full_path_to_v(dirs_in int) string {
return vexec
}
fn diff_files( file_result, file_expected string ) string {
diffcmd := util.find_working_diff_command() or { return err }
fn diff_files(file_result, file_expected string) string {
diffcmd := util.find_working_diff_command() or {
return err
}
return util.color_compare_files(diffcmd, file_result, file_expected)
}
pub fn run_repl_file(wd string, vexec string, file string) ?string {
pub fn run_repl_file(wd, vexec, file string) ?string {
vexec_folder := os.dir(vexec) + os.path_separator
fcontent := os.read_file(file) or { return error('Could not read file ${file}') }
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').trim_right('\n\r')
fname := os.file_name( file )
input_temporary_filename := os.real_path(os.join_path( wd, 'input_temporary_filename.txt'))
fname := os.file_name(file)
input_temporary_filename := os.real_path(os.join_path(wd, 'input_temporary_filename.txt'))
os.write_file(input_temporary_filename, input)
os.write_file( os.real_path(os.join_path( wd, 'original.txt' ) ), fcontent )
os.write_file(os.real_path(os.join_path(wd, 'original.txt')), fcontent)
rcmd := '"$vexec" repl -replfolder "$wd" -replprefix "${fname}." < $input_temporary_filename'
r := os.exec(rcmd) or {
os.rm(input_temporary_filename)
return error('Could not execute: $rcmd')
}
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 + os.path_separator, '' )
.replace(vexec_folder, '')
.replace('\\', '/')
.trim_right('\n\r')
result := r.output.replace('\r', '').replace('>>> ', '').replace('>>>', '').replace('... ',
'').all_after('Use Ctrl-C or `exit` to exit\n').replace(wd + os.path_separator, '').replace(vexec_folder,
'').replace('\\', '/').trim_right('\n\r')
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}
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 :
@ -83,31 +77,29 @@ pub fn run_repl_file(wd string, vexec string, file string) ?string {
$diff
')
} else {
return 'Repl file ${file} is OK'
return 'Repl file $file is OK'
}
}
pub fn run_prod_file(wd string, vexec string, file string) ?string {
pub fn run_prod_file(wd, vexec, file string) ?string {
file_expected := '${file}.expected.txt'
f_expected_content := os.read_file(file_expected) or { return error('Could not read file ${file}') }
f_expected_content := os.read_file(file_expected) or {
return error('Could not read file $file')
}
expected_content := f_expected_content.replace('\r', '')
cmd := '"$vexec" -prod run "${file}"'
cmd := '"$vexec" -prod run "$file"'
r := os.exec(cmd) or {
return error('Could not execute: $cmd')
}
if r.exit_code != 0 {
return error('$cmd return exit code: $r.exit_code')
}
result := r.output.replace('\r','')
result := r.output.replace('\r', '')
if result != expected_content {
file_result := '${file}.result.txt'
os.write_file( file_result, result )
diff := diff_files( file_result, file_expected )
return error('Difference found in test: ${file}
os.write_file(file_result, result)
diff := diff_files(file_result, file_expected)
return error('Difference found in test: $file
====> Got :
|$result|
====> Expected :
@ -116,7 +108,7 @@ pub fn run_prod_file(wd string, vexec string, file string) ?string {
$diff
')
} else {
return 'Prod file ${file} is OK'
return 'Prod file $file is OK'
}
}
@ -127,11 +119,11 @@ pub fn new_options() RunnerOptions {
if os.args.len > 1 {
files = os.args[1..]
} else {
os.chdir( os.dir(vexec) )
os.chdir(os.dir(vexec))
wd = os.getwd()
files = os.walk_ext('.', '.repl')
}
return RunnerOptions {
return RunnerOptions{
wd: wd
vexec: vexec
files: files
@ -147,7 +139,7 @@ pub fn new_prod_options() RunnerOptions {
} else {
files = os.walk_ext(wd, '.prod.v')
}
return RunnerOptions {
return RunnerOptions{
wd: wd
vexec: vexec
files: files

View File

@ -1,5 +1,6 @@
struct Zest { val int }
struct Zest {
val int
}
fn (t Zest) get_a_finger_to_the_moon() voidptr {
return voidptr(0)
@ -10,7 +11,9 @@ fn get_the_dao_way() voidptr {
}
fn test_returning_a_void_pointer_from_a_method() {
t := &Zest{ val: 123 }
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

View File

@ -2,7 +2,7 @@ module main
struct Anything {
mut:
name string = ""
name string = ''
keepo int = 0
}
@ -12,80 +12,102 @@ fn (a Anything) str() string {
fn test_array_of_ptrs_to_structs_can_be_printed() {
mut testing := []&Anything{}
testing << &Anything{name: "Hehe"}
testing << &Anything{name: "other"}
testing << &Anything{name: "test"}
testing << &Anything{
name: 'Hehe'
}
testing << &Anything{
name: 'other'
}
testing << &Anything{
name: 'test'
}
for test in testing {
println(test)
assert true
}
println('testing: $testing')
println( testing )
println(testing)
assert true
}
// At the same time, this should also work:
// (note the str method defined on (a &T), instead on (a T))
struct PstrAnything {
mut:
name string = ""
name string = ''
keepo int = 0
}
fn (a &PstrAnything) str() string {
return a.name
}
fn test_array_of_ptrs_to_structs_can_be_printed_when_structs_have_str_with_ptr() {
mut testing := []&PstrAnything{}
testing << &PstrAnything{name: "abc"}
testing << &PstrAnything{name: "def"}
testing << &PstrAnything{name: "ghi"}
testing << &PstrAnything{
name: 'abc'
}
testing << &PstrAnything{
name: 'def'
}
testing << &PstrAnything{
name: 'ghi'
}
for test in testing {
println(test)
assert true
}
println('testing: $testing')
println( testing )
println(testing)
assert true
}
//
fn test_stack_array_of_structs_can_be_printed_when_structs_have_ordinary_str() {
mut t := [3]Anything
t[0] = Anything{name: "012"}
t[1] = Anything{name: "345"}
t[2] = Anything{name: "678"}
t[0] = Anything{
name: '012'
}
t[1] = Anything{
name: '345'
}
t[2] = Anything{
name: '678'
}
for test in t {
println(test)
assert true
}
println('t: $t')
println( t )
println( 't[0] := ${t[0]}')
println(t)
println('t[0] := ${t[0]}')
assert true
}
fn test_stack_array_of_structs_can_be_printed_when_structs_have_str_with_ptr() {
// this generates a C error
mut pt := [3]PstrAnything
pt[0] = PstrAnything{name: "P012"}
pt[1] = PstrAnything{name: "P345"}
pt[2] = PstrAnything{name: "P678"}
pt[0] = PstrAnything{
name: 'P012'
}
pt[1] = PstrAnything{
name: 'P345'
}
pt[2] = PstrAnything{
name: 'P678'
}
for test in pt {
println(test)
assert true
}
println('pt: $pt')
println( pt )
print( 'pt[0] := ')
print( pt[0] )
println(pt)
print('pt[0] := ')
print(pt[0])
println('')
assert true
$if debug_buggy_println ? {
//TODO: fix string interpolation for structs with `fn (t &T) str() string` too:
println( 'pt[0] := ${pt[0]}')
// TODO: fix string interpolation for structs with `fn (t &T) str() string` too:
println('pt[0] := ${pt[0]}')
}
}

View File

@ -1,11 +1,21 @@
fn test_ptr_assign() {
v := [int(5), 6, 77, 1]
mut p := &v[0]
unsafe { (*p)++ }
unsafe { p++ } // p now points to v[1]
unsafe { (*p) += 2 }
unsafe { p += 2 } // p now points to v[3]
unsafe { *p = 31 }
unsafe {
(*p)++
}
unsafe {
p++
} // p now points to v[1]
unsafe {
(*p) += 2
}
unsafe {
p += 2
} // p now points to v[3]
unsafe {
*p = 31
}
assert v[0] == 6
assert v[1] == 8
assert v[2] == 77
@ -14,18 +24,28 @@ fn test_ptr_assign() {
fn test_ptr_infix() {
v := 4
mut q := unsafe{ &v - 1 }
q = unsafe {q + 3}
mut q := unsafe {
&v - 1
}
q = unsafe {
q + 3
}
_ := q
_ := v
}
struct S1 {}
struct S1 {
}
[unsafe_fn]
fn (s S1) f(){}
fn (s S1) f() {
}
fn test_funcs() {
s := S1{}
unsafe { s.f() }
unsafe {
s.f()
}
}

View File

@ -168,11 +168,7 @@ fn get_array_content(tokens []Token, st_idx int) ?([]string, int) {
if tokens[idx + 1].typ !in [.comma, .rabr] {
return error('vmod: invalid separator "${tokens[idx+1].val}"')
}
idx += if tokens[idx + 1].typ == .comma {
2
} else {
1
}
idx += if tokens[idx + 1].typ == .comma { 2 } else { 1 }
}
.rabr {
idx++

View File

@ -19,14 +19,11 @@ import os
// => ModFileAndFolder{'vlib/v.mod', 'vlib'}
// ModFileCacher.get('vlib/v/test/project_with_c_code/mod1')
// => ModFileAndFolder{'vlib/v/test/project_with_c_code/mod1/v.mod', 'vlib/v/test/project_with_c_code/mod1'}
pub struct ModFileAndFolder {
pub:
// vmod_file contains the full path of the found 'v.mod' file, or ''
// if no 'v.mod' file was found in file_path_dir, or in its parent folders.
vmod_file string
// vmod_folder contains the file_path_dir, if there is no 'v.mod' file in
// *any* of the parent folders, otherwise it is the first parent folder,
// where a v.mod file was found.
@ -49,35 +46,34 @@ pub fn (mcache &ModFileCacher) dump() {
$if debug {
eprintln('ModFileCacher DUMP:')
eprintln(' ModFileCacher.cache:')
for k,v in mcache.cache {
for k, v in mcache.cache {
eprintln(' K: ${k:-32s} | V: "${v.vmod_file:32s}" | "${v.vmod_folder:32s}" ')
}
eprintln(' ModFileCacher.folder_files:')
for k,v in mcache.folder_files {
eprintln(' K: ${k:-32s} | V: ${v.str()}')
for k, v in mcache.folder_files {
eprintln(' K: ${k:-32s} | V: $v.str()')
}
}
}
pub fn (mut mcache ModFileCacher) get_by_file(vfile string) ModFileAndFolder {
return mcache.get_by_folder( os.dir( vfile ) )
return mcache.get_by_folder(os.dir(vfile))
}
pub fn (mut mcache ModFileCacher) get_by_folder(vfolder string) ModFileAndFolder {
mfolder := os.real_path( vfolder )
mfolder := os.real_path(vfolder)
if mfolder in mcache.cache {
return mcache.cache[ mfolder ]
return mcache.cache[mfolder]
}
traversed_folders, res := mcache.traverse( mfolder )
traversed_folders, res := mcache.traverse(mfolder)
for tfolder in traversed_folders {
mcache.add( tfolder, res )
mcache.add(tfolder, res)
}
return res
}
fn (mut cacher ModFileCacher) add(path string, result ModFileAndFolder) {
cacher.cache[ path ] = result
cacher.cache[path] = result
}
fn (mut mcache ModFileCacher) traverse(mfolder string) ([]string, ModFileAndFolder) {
@ -92,47 +88,59 @@ fn (mut mcache ModFileCacher) traverse(mfolder string) ([]string, ModFileAndFold
break
}
if cfolder in mcache.cache {
res := mcache.cache[ cfolder ]
res := mcache.cache[cfolder]
if res.vmod_file.len == 0 {
mcache.mark_folders_as_vmod_free( folders_so_far )
}else{
mcache.mark_folders_with_vmod( folders_so_far, res )
mcache.mark_folders_as_vmod_free(folders_so_far)
} else {
mcache.mark_folders_with_vmod(folders_so_far, res)
}
return []string{}, res
}
files := mcache.get_files( cfolder )
files := mcache.get_files(cfolder)
if 'v.mod' in files {
// TODO: actually read the v.mod file and parse its contents to see
// if its source folder is different
res := ModFileAndFolder{ vmod_file: os.join_path( cfolder, 'v.mod'), vmod_folder: cfolder }
res := ModFileAndFolder{
vmod_file: os.join_path(cfolder, 'v.mod')
vmod_folder: cfolder
}
return folders_so_far, res
}
if mcache.check_for_stop( cfolder, files ) {
if mcache.check_for_stop(cfolder, files) {
break
}
cfolder = os.base_dir( cfolder )
cfolder = os.base_dir(cfolder)
folders_so_far << cfolder
levels++
}
mcache.mark_folders_as_vmod_free( folders_so_far )
return [mfolder], ModFileAndFolder{ vmod_file: '', vmod_folder: mfolder }
}
fn (mut mcache ModFileCacher) mark_folders_with_vmod( folders_so_far []string, vmod ModFileAndFolder ) {
for f in folders_so_far {
mcache.add( f, vmod )
mcache.mark_folders_as_vmod_free(folders_so_far)
return [mfolder], ModFileAndFolder{
vmod_file: ''
vmod_folder: mfolder
}
}
fn (mut mcache ModFileCacher) mark_folders_as_vmod_free( folders_so_far []string ) {
fn (mut mcache ModFileCacher) mark_folders_with_vmod(folders_so_far []string, vmod ModFileAndFolder) {
for f in folders_so_far {
mcache.add(f, vmod)
}
}
fn (mut mcache ModFileCacher) mark_folders_as_vmod_free(folders_so_far []string) {
// No need to check these folders anymore,
// because their parents do not contain v.mod files
for f in folders_so_far {
mcache.add( f, ModFileAndFolder{ vmod_file: '', vmod_folder: f } )
mcache.add(f, ModFileAndFolder{
vmod_file: ''
vmod_folder: f
})
}
}
const ( mod_file_stop_paths = ['.git', '.hg', '.svn', '.v.mod.stop' ] )
const (
mod_file_stop_paths = ['.git', '.hg', '.svn', '.v.mod.stop']
)
fn (mcache &ModFileCacher) check_for_stop(cfolder string, files []string) bool {
for i in mod_file_stop_paths {
if i in files {
@ -144,20 +152,23 @@ fn (mcache &ModFileCacher) check_for_stop(cfolder string, files []string) bool {
fn (mut mcache ModFileCacher) get_files(cfolder string) []string {
if cfolder in mcache.folder_files {
return mcache.folder_files[ cfolder ]
return mcache.folder_files[cfolder]
}
mut files := []string{}
if os.exists( cfolder ) && os.is_dir(cfolder) {
if os.exists(cfolder) && os.is_dir(cfolder) {
if listing := os.ls(cfolder) {
files = listing
}
}
mcache.folder_files[ cfolder ] = files
mcache.folder_files[cfolder] = files
return files
}
// used during lookup for v.mod to support @VROOT
const ( private_file_cacher = new_mod_file_cacher() )
const (
private_file_cacher = new_mod_file_cacher()
)
pub fn get_cache() &ModFileCacher {
return private_file_cacher
}