From 06f581e146fc8af9229ba407bc05adf43e916d9a Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 11 Jan 2020 00:33:35 +0200 Subject: [PATCH] vfmt: support for vid like projects having many module main .v files --- tools/vfmt.v | 62 +++++++++++++++++++++++++++++-- vlib/compiler/string_expression.v | 8 ++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/tools/vfmt.v b/tools/vfmt.v index 122374c861..66e0d6b4ef 100644 --- a/tools/vfmt.v +++ b/tools/vfmt.v @@ -160,6 +160,12 @@ fn (foptions &FormatOptions) format_file(file string) { cfile = main_program_file compiler_params << ['-user_mod_path', mod_folder_parent] } + if !is_test_file && mod_name == 'main' { + // NB: here, file is guaranted to be a main. We do not know however + // whether it is a standalone v program, or is it a part of a bigger + // project, like vorum or vid. + cfile = get_compile_name_of_potential_v_project(cfile) + } compiler_params << cfile if foptions.is_verbose { eprintln('vfmt format_file: file: $file') @@ -287,11 +293,9 @@ fn file_to_target_os(file string) string { fn file_to_mod_name_and_is_module_file(file string) (string,bool) { mut mod_name := 'main' mut is_module_file := false - raw_fcontent := os.read_file(file) or { + flines := read_source_lines(file) or { return mod_name,is_module_file } - fcontent := raw_fcontent.replace('\r\n', '\n') - flines := fcontent.split('\n') for fline in flines { line := fline.trim_space() if line.starts_with('module ') { @@ -304,3 +308,55 @@ fn file_to_mod_name_and_is_module_file(file string) (string,bool) { } return mod_name,is_module_file } + +fn read_source_lines(file string) ?[]string { + raw_fcontent := os.read_file(file) or { + return error('can not read $file') + } + fcontent := raw_fcontent.replace('\r\n', '\n') + return fcontent.split('\n') +} + +fn get_compile_name_of_potential_v_project(file string) string { + // This function get_compile_name_of_potential_v_project returns: + // a) the file's folder, if file is part of a v project + // b) the file itself, if the file is a standalone v program + pfolder := os.realpath(filepath.dir(file)) + // a .v project has many 'module main' files in one folder + // if there is only one .v file, then it must be a standalone + all_files_in_pfolder := os.ls(pfolder) or { + panic(err) + } + mut vfiles := []string + for f in all_files_in_pfolder { + vf := filepath.join(pfolder,f) + if f.starts_with('.') || !f.ends_with('.v') || os.is_dir(vf) { + continue + } + vfiles << vf + } + if vfiles.len == 1 { + return file + } + // ///////////////////////////////////////////////////////////// + // At this point, we know there are many .v files in the folder + // We will have to read them all, and if there are more than one + // containing `fn main` then the folder contains multiple standalone + // v programs. If only one contains `fn main` then the folder is + // a project folder, that should be compiled with `v pfolder`. + mut main_fns := 0 + for f in vfiles { + slines := read_source_lines(f) or { + panic(err) + } + for line in slines { + if line.contains('fn main()') { + main_fns++ + if main_fns > 1 { + return file + } + } + } + } + return pfolder +} diff --git a/vlib/compiler/string_expression.v b/vlib/compiler/string_expression.v index 7a0c6181ac..96cc9e4a46 100644 --- a/vlib/compiler/string_expression.v +++ b/vlib/compiler/string_expression.v @@ -37,6 +37,12 @@ fn (p mut Parser) string_expr() { p.gen('tos3("$f")') } p.next() + if p.scanner.is_fmt && p.tok == .not { + // handle '$age'! + // TODO remove this hack, do this automatically + p.fgen(' ') + p.check(.not) + } return } $if js { @@ -131,6 +137,7 @@ fn (p mut Parser) string_expr() { if complex_inter { p.fgen('}') } + // p.fgen('\'') // println("hello %d", num) optimization. if p.cgen.nogen { @@ -149,6 +156,7 @@ fn (p mut Parser) string_expr() { // won't be used again) // TODO remove this hack, do this automatically if p.tok == .not { + p.fgen(' ') p.check(.not) p.gen('_STR_TMP($format$args)') }