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

@ -34,4 +34,4 @@ pub fn (b &Builder) generic_struct_insts_to_concrete() {
typ.info = parent_info
}
}
}
}

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
@ -19,7 +18,7 @@ struct MsvcResult {
ucrt_include_path string
vs_include_path string
shared_include_path string
valid bool
valid bool
}
// shell32 for RegOpenKeyExW etc
@ -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

@ -48,7 +48,7 @@ const (
// for __offset_of
#ifndef __offsetof
#define __offsetof(s,memb) \\
((size_t)((char *)&((s *)0)->memb - (char *)0))
((size_t)((char *)&((s *)0)->memb - (char *)0))
#endif
#define OPTION_CAST(x) (x)
@ -337,7 +337,7 @@ void _vcleanup();
else if (_likely_(i)) _wymix128(_wyr3(p,i)^_wyp0,_wyp1, &seed, &see1);
else _wymix128(_wyp0,_wyp1, &seed, &see1);
}
else _wymix128(_wyr8(p)^_wyp0,_wyr8(p+i-8)^_wyp1, &seed, &see1);
else _wymix128(_wyr8(p)^_wyp0,_wyr8(p+i-8)^_wyp1, &seed, &see1);
#endif
_wymix128(len,_wyp0, &seed, &see1);
return seed^see1;

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

@ -2,132 +2,120 @@ import hello as hl
import hello.hello1 as hl1
const (
i_am_a_const = 21214
super = 'amazing keyword'
i_am_a_const = 21214
super = 'amazing keyword'
)
struct Foo {
mut:
a hl.Aaa
a hl.Aaa
}
struct Companies {
google int
amazon bool
yahoo string
amazon bool
yahoo string
}
enum POSITION {
go_back
dont_go_back
go_back
dont_go_back
}
fn class(extends string, instanceof int) {
delete := instanceof
_ = delete
delete := instanceof
_ = 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{} }
c.a.update('another update')
println(c)
_ = "done"
{
_ = "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"
}
// panic('foo')
for m, n in ma {
iss := m
}
go async(0, "hello")
fn_in_var := fn (number int) {
println("number: $number")
}
hl.debugger()
anon_consumer(hl.excited(), fn (message string) {
println(message)
})
hl.raw_js_log()
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{}}
c.a.update('another update')
println(c)
_ = 'done'
{
_ = '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'
}
// panic('foo')
for m, n in ma {
iss := m
}
go async(0, 'hello')
fn_in_var := fn (number int) {
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)) {
anon(greeting)
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"
}
for dd in dummy {
l := dd
}
return game_on + 2, 221
defer {
do := 'not'
}
for dd in dummy {
l := dd
}
return game_on + 2, 221
}
fn (it Companies) method() int {
ss := Companies {
google: 2
amazon: true
yahoo: "hello"
ss := Companies{
google: 2
amazon: true
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 {}
return 0
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 {
}
return 0
}

View File

@ -5,7 +5,7 @@ const (w = 30 h = 30)
fn get(game [][]bool, x int, y int) bool {
if y < 0 || x < 0 { return false }
if y >= h || x >= w { return false }
return game[y][x]
}
@ -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

@ -2,35 +2,39 @@ module main
struct Int {
mut:
value int
test map[string]int
hello []int
value int
test map[string]int
hello []int
}
fn (mut i Int) add(value int) {
i.value += value
i.value += value
}
fn (i Int) get() int {
return i.value
return i.value
}
struct Config {
foo int
bar string
foo int
bar string
}
fn use_config(c Config) {}
fn use_config(c Config) {
}
fn main() {
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')
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'
})
}

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,26 +38,24 @@ 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)'
dec.writeln('
//Option_$styp ${dec_fn_name}(cJSON* root, $styp* res) {
$dec_fn_dec {
$styp res;
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);
Option err = v_error(tos2(error_ptr));
return *(Option_$styp *)&err;
}
}
$styp res;
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);
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)}));')
}
@ -160,7 +156,7 @@ const cJSON *jsval = NULL;
cJSON_ArrayForEach(jsval, root)
{
$s
array_push(&res, &val);
array_push(&res, &val);
}
'
}
@ -171,7 +167,7 @@ fn (mut g Gen) encode_array(value_type table.Type) string {
return '
o = cJSON_CreateArray();
for (int i = 0; i < val.len; i++){
cJSON_AddItemToArray(o, $fn_name ( (($styp*)val.data)[i] ));
cJSON_AddItemToArray(o, $fn_name ( (($styp*)val.data)[i] ));
}
'
}

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
}
@ -54,14 +55,14 @@ fn (mut g Gen) generate_hotcode_reloader_code() {
}
const (
posix_hotcode_definitions_1 = '
posix_hotcode_definitions_1 = '
void v_bind_live_symbols(void* live_lib){
@LOAD_FNS@
@LOAD_FNS@
}
'
windows_hotcode_definitions_1 = '
void v_bind_live_symbols(void* live_lib){
@LOAD_FNS@
@LOAD_FNS@
}
'
)
@ -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)
}
@ -144,13 +142,13 @@ pub fn (t Type) deref() Type {
// set `flag` on `t` and return `t`
[inline]
pub fn (t Type) set_flag(flag TypeFlag) Type {
return int(t) | (1 << (int(flag) + 24))
return int(t) | (1 << (int(flag) + 24))
}
// clear `flag` on `t` and return `t`
[inline]
pub fn (t Type) clear_flag(flag TypeFlag) Type {
return int(t) & ~(1 << (int(flag) + 24))
return int(t) & ~(1 << (int(flag) + 24))
}
// clear all flags
@ -162,7 +160,7 @@ pub fn (t Type) clear_flags() Type {
// return true if `flag` is set on `t`
[inline]
pub fn (t Type) has_flag(flag TypeFlag) bool {
return int(t) & (1 << (int(flag) + 24)) > 0
return int(t) & (1 << (int(flag) + 24)) > 0
}
// copy flags & nr_muls from `t_from` to `t` and return `t`
@ -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 {
@ -548,10 +530,10 @@ pub fn (mut t Table) register_builtin_type_symbols() {
mod: 'builtin'
})
// t.register_type_symbol({
// kind: .any
// name: 'T'
// mod: 'builtin'
// is_public: true
// kind: .any
// name: 'T'
// mod: 'builtin'
// is_public: true
// })
t.register_type_symbol({
kind: .any_float
@ -681,15 +663,15 @@ pub mut:
pub struct Enum {
pub:
vals []string
is_flag bool
vals []string
is_flag bool
is_multi_allowed bool
}
pub struct Alias {
pub:
parent_type Type
language Language
language Language
}
// NB: FExpr here is a actually an ast.Expr .

View File

@ -1,102 +1,81 @@
import table
fn test_idx() {
mut t := table.new_type(table.void_type_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)
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()
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
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
}
fn test_derive() {
mut t := table.new_type(table.i8_type_idx)
t = t.set_flag(table.TypeFlag.generic)
t = t.set_flag(table.TypeFlag.variadic)
mut t := table.new_type(table.i8_type_idx)
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)
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
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

@ -112,12 +112,12 @@ pub fn (t &Table) known_fn(name string) bool {
}
pub fn (mut t Table) register_fn(new_fn Fn) {
// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
t.fns[new_fn.name] = new_fn
}
pub fn (mut t TypeSymbol) register_method(new_fn Fn) {
// println('reg me $new_fn.name nr_args=$new_fn.args.len')
// println('reg me $new_fn.name nr_args=$new_fn.args.len')
t.methods << new_fn
}
@ -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

@ -26,7 +26,7 @@ fn test_autolocked_array() {
rlock abc {
finished_threads = unsafe {
abc[0]
}
}
}
if finished_threads == 2 {
break

View File

@ -1,10 +1,10 @@
import rand
const (
my_random_letter_const = byte(65 + rand.u32n(25))
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

@ -1,20 +1,20 @@
struct Abc {
mut:
flags []Flag
flags []Flag
}
enum Flag {
flag_one
flag_two
flag_one
flag_two
}
fn test_enum_array_field() {
mut a := Abc{}
a.flags << .flag_one
assert true
a.flags << .flag_two
assert true
a.flags << .flag_one
println(a)
assert true
mut a := Abc{}
a.flags << .flag_one
assert true
a.flags << .flag_two
assert true
a.flags << .flag_one
println(a)
assert true
}

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
@ -99,99 +98,98 @@ fn test_return_array() {
/*
fn map_f<T,U>(l []T, f fn(T)U) []U {
mut r := []U{}
for e in l {
r << f(e)
}
return r
mut r := []U{}
for e in l {
r << f(e)
}
return r
}
fn foldl<T>(l []T, nil T, f fn(T,T)T) T {
mut r := nil
for e in l {
r = f(r, e)
}
return r
mut r := nil
for e in l {
r = f(r, e)
}
return r
}
fn square(x int) int {
return x*x
return x*x
}
fn mul_int(x int, y int) int {
return x*y
return x*y
}
fn assert_eq<T>(a, b T) {
r := a == b
println('$a == $b: ${r.str()}')
assert r
r := a == b
println('$a == $b: ${r.str()}')
assert r
}
fn print_nice<T>(x T, indent int) {
mut space := ''
for _ in 0..indent {
space = space + ' '
}
println('$space$x')
mut space := ''
for _ in 0..indent {
space = space + ' '
}
println('$space$x')
}
fn test_generic_fn() {
assert_eq(simple(0+1), 1)
assert_eq(simple('g') + 'h', 'gh')
assert_eq(sum([5.1,6.2,7.0]), 18.3)
assert_eq(plus(i64(4), i64(6)), i64(10))
a := [1,2,3,4]
b := map_f(a, square)
assert_eq(sum(b), 30) // 1+4+9+16 = 30
assert_eq(foldl(b, 1, mul_int), 576) // 1*4*9*16 = 576
print_nice('str', 8)
assert_eq(simple(0+1), 1)
assert_eq(simple('g') + 'h', 'gh')
assert_eq(sum([5.1,6.2,7.0]), 18.3)
assert_eq(plus(i64(4), i64(6)), i64(10))
a := [1,2,3,4]
b := map_f(a, square)
assert_eq(sum(b), 30) // 1+4+9+16 = 30
assert_eq(foldl(b, 1, mul_int), 576) // 1*4*9*16 = 576
print_nice('str', 8)
}
struct Point {
mut:
x f64
y f64
x f64
y f64
}
fn (mut p Point) translate<T>(x, y T) {
p.x += x
p.y += y
p.x += x
p.y += y
}
fn test_generic_method() {
mut p := Point{}
p.translate(2, 1.0)
assert p.x == 2.0 && p.y == 1.0
mut p := Point{}
p.translate(2, 1.0)
assert p.x == 2.0 && p.y == 1.0
}
fn get_values<T>(i T) []T {
return [i]
return [i]
}
fn test_generic_fn_in_for_in_expression() {
for value in get_values(1) {
assert value == 1
}
for value in get_values(1) {
assert value == 1
}
for i, val in get_values(0) {
assert i == val
}
for i, val in get_values(0) {
assert i == val
}
for value in get_values('a') {
assert value == 'a'
}
for value in get_values('a') {
assert value == 'a'
}
}
*/
// test generic struct
struct DB {
driver string
driver string
}
struct Group {
pub mut:
name string
name string
group_name string
}
@ -200,41 +198,40 @@ pub mut:
name string
}
struct Repo<T,U> {
db DB
struct Repo<T, U> {
db DB
pub mut:
model T
model T
permission U
}
// TODO: multiple type generic struct needs fixing in return for fn
// fn new_repo<T>(db DB) Repo<T,U> {
// return Repo<T,Permission>{db: db}
// 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'}
println('a.model.name: $a.model.name')
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,6 +1,5 @@
fn main() {
test := 'hello'
hello := 'world'
println('%.*s$hello$test')
println('%.*s$hello$test')
}

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

@ -5,29 +5,28 @@ import time
The goal of this test, is to simulate a developer, that has run a program, compiled with -live flag.
It does so by writing a new generated program containing a [live] fn pmessage() string {...} function,
then runs the generated program at the start *in the background*,
waits some time, so that the program could run a few iterations, then modifies its source
(simulates a developer that has saved a new version of the program source),
then runs the generated program at the start *in the background*,
waits some time, so that the program could run a few iterations, then modifies its source
(simulates a developer that has saved a new version of the program source),
then it waits some more, modifies it again and saves it once more.
On each modification, the running program, should detect that its source code has changed,
and recompile a shared library, which it then it should load, and thus modify its own
On each modification, the running program, should detect that its source code has changed,
and recompile a shared library, which it then it should load, and thus modify its own
behavior at runtime (the pmessage function).
If everything works fine, the output of the generated program would have changed at least 1-2 times,
which then is detected by the test program (the histogram checks).
Since this test program is sensitive to coordination (or lack of) of several processes,
it tries to sidestep the coordination issue by polling the file system for the existance
Since this test program is sensitive to coordination (or lack of) of several processes,
it tries to sidestep the coordination issue by polling the file system for the existance
of files, ORIGINAL.txt ... STOP.txt , which are appended to by the generated program.
NB: That approach of monitoring the state of the running generated program, is clearly not ideal,
but sidesteps the issue of coordinating processes through IPC or stdin/stdout in hopefully
NB: That approach of monitoring the state of the running generated program, is clearly not ideal,
but sidesteps the issue of coordinating processes through IPC or stdin/stdout in hopefully
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')
@ -48,14 +47,14 @@ import live
fn append_to_file(fname, s string) {
mut f := os.open_append(fname) or {
println('>>>> could not open file \$fname for appending, err: \$err ')
return
return
}
f.writeln('\$s')
//info := live.info()
//info := live.info()
//f.writeln('>>> reloads: \${info.reloads} | ok reloads: \${info.reloads_ok}')
f.flush()
f.close()
}
}
fn myprintln(s string) {
append_to_file('$output_file', s)
@ -76,12 +75,12 @@ const (
fn main() {
mut info := live.info()
info.recheck_period_ms = 5
info.recheck_period_ms = 5
myprintln('START')
myprintln('DATE: ' + time.now().str())
pmessage()
pmessage()
// NB: 1000 * 5 = maximum of ~5s runtime
// NB: 1000 * 5 = maximum of ~5s runtime
for i:=0; i<1000; i++ {
s := pmessage()
append_to_file(os.resource_abs_path(s + '.txt'), s)
@ -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

@ -2,6 +2,6 @@
module local
pub fn local_fn() bool {
return true
return true
}

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 ''
}
}
match s {
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

@ -1,16 +1,14 @@
module amodule
// This tests whether _test.v files can be *internal* to a
// 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
// and inside internal_module_test.v . That is done on purpose,
// with the goal of ensuring that _test.v files are compiled
// *independently* from each other.
//
// _test.v files should *only* import all the other normal .v
// _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

@ -1,16 +1,15 @@
module amodule
// this tests whether _test.v files can be *internal*
// 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 {
return x - y
// /////////////////////////////////////
fn private_isub(x, y int) int {
return x - y
}

View File

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

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,10 +1,10 @@
import mod1.submodule as m
fn test_mod1_can_still_be_found_through_parent_project_vmod(){
assert 1051 == m.f()
}
fn test_mod1_can_still_be_found_through_parent_project_vmod() {
assert 1051 == m.f()
}
/*
/*
NB: this main program is under bin/ , but it still
can find mod1, because the parent project has v.mod,
so v module lookup for this program will find mod1 through

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(){
assert 1051 == submodule.f()
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)
assert a == 7
assert iadd(10,20) == 30
fn test_iadd_3_4() {
a := iadd(3, 4)
assert a == 7
assert iadd(10, 20) == 30
}

View File

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

View File

@ -5,7 +5,7 @@ import v.util
pub struct RunnerOptions {
pub:
wd string
wd string
vexec string
files []string
}
@ -30,51 +30,45 @@ pub fn full_path_to_v(dirs_in int) string {
println('vreal : $vreal')
println('myself : $myself')
println('wd : $wd')
*/
*/
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_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}
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
====> 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,6 +1,7 @@
struct Zest {
val int
}
struct Zest { val int }
fn (t Zest) get_a_finger_to_the_moon() voidptr {
return voidptr(0)
}
@ -8,9 +9,11 @@ fn (t Zest) get_a_finger_to_the_moon() voidptr {
fn get_the_dao_way() voidptr {
return voidptr(0)
}
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

@ -32,7 +32,7 @@ fn test_shared_array() {
finished_threads = unsafe {
foo[2]
}
}
if finished_threads == 4 {
break
@ -43,11 +43,11 @@ fn test_shared_array() {
f0 := unsafe {
foo[0]
}
f1 := unsafe {
foo[1]
}
assert f0 == 100010
assert f1 == 350020
}

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,31 +1,51 @@
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 }
assert v[0] == 6
assert v[1] == 8
assert v[2] == 77
assert v[3] == 31
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
}
assert v[0] == 6
assert v[1] == 8
assert v[2] == 77
assert v[3] == 31
}
fn test_ptr_infix() {
v := 4
mut q := unsafe{ &v - 1 }
q = unsafe {q + 3}
_ := q
_ := v
v := 4
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() }
s := S1{}
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_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.
@ -36,7 +33,7 @@ pub:
[ref_only]
pub struct ModFileCacher {
mut:
cache map[string]ModFileAndFolder
cache map[string]ModFileAndFolder
// folder_files caches os.ls(key)
folder_files map[string][]string
}
@ -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
}