v2: compile vfmt again; consistent colored error messages

pull/4220/head
Delyan Angelov 2020-04-03 18:38:41 +03:00
parent 52f096f5d9
commit 31c4b1cda6
17 changed files with 266 additions and 308 deletions

View File

@ -6,9 +6,9 @@ module main
import (
os
os.cmdline
compiler
v.pref
v.fmt
v.util
v.parser
v.table
vhelp
@ -43,7 +43,7 @@ const (
fn main() {
toolexe := os.executable()
compiler.set_vroot_folder(os.dir(os.dir(os.dir(toolexe))))
util.set_vroot_folder(os.dir(os.dir(os.dir(toolexe))))
args := join_flags_and_argument()
foptions := FormatOptions{
is_2: '-2' in args
@ -81,17 +81,17 @@ fn main() {
for file in possible_files {
if foptions.is_2 {
if !file.ends_with('.v') && !file.ends_with('.vv') {
compiler.verror('v fmt -2 can only be used on .v or .vv files.\nOffending file: "$file" .')
verror('v fmt -2 can only be used on .v or .vv files.\nOffending file: "$file" .')
continue
}
} else {
if !file.ends_with('.v') {
compiler.verror('v fmt can only be used on .v files.\nOffending file: "$file" .')
verror('v fmt can only be used on .v files.\nOffending file: "$file" .')
continue
}
}
if !os.exists(file) {
compiler.verror('"$file" does not exist.')
verror('"$file" does not exist.')
continue
}
files << file
@ -151,89 +151,20 @@ fn main() {
}
fn (foptions &FormatOptions) format_file(file string) {
if foptions.is_2 {
if foptions.is_verbose {
eprintln('vfmt2 running fmt.fmt over file: $file')
}
table := table.new_table()
file_ast := parser.parse_file(file, table, .parse_comments, &pref.Preferences{})
formatted_content := fmt.fmt(file_ast, table)
file_name := os.file_name(file)
vfmt_output_path := os.join_path(os.temp_dir(), 'vfmt_' + file_name)
os.write_file(vfmt_output_path, formatted_content )
if foptions.is_verbose {
eprintln('vfmt2 fmt.fmt worked and ${formatted_content.len} bytes were written to ${vfmt_output_path} .')
}
eprintln('${FORMATTED_FILE_TOKEN}${vfmt_output_path}')
return
}
tmpfolder := os.temp_dir()
mut compiler_params := &pref.Preferences{}
target_os := file_to_target_os(file)
if target_os != '' {
//TODO Remove temporary variable once it compiles correctly in C
tmp := pref.os_from_string(target_os) or {
eprintln('unknown operating system $target_os')
return
}
compiler_params.os = tmp
}
mut cfile := file
mut mod_folder_parent := tmpfolder
is_test_file := file.ends_with('_test.v')
mod_name,is_module_file := file_to_mod_name_and_is_module_file(file)
use_tmp_main_program := is_module_file && !is_test_file
mod_folder := os.base_dir(file)
if use_tmp_main_program {
// TODO: remove the need for this
// This makes a small program that imports the module,
// so that the module files will get processed by the
// vfmt implementation.
mod_folder_parent = os.base_dir(mod_folder)
mut main_program_content := if mod_name == 'builtin' || mod_name == 'main' { 'fn main(){}\n' } else { 'import ${mod_name}\n' + 'fn main(){}\n' }
main_program_file := os.join_path(tmpfolder,'vfmt_tmp_${mod_name}_program.v')
if os.exists(main_program_file) {
os.rm(main_program_file)
}
os.write_file(main_program_file, main_program_content)
cfile = main_program_file
compiler_params.lookup_path = [mod_folder_parent, '@vlib', '@vmodule']
}
if !is_test_file && mod_name == 'main' {
// NB: here, file is guaranteed 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.path = cfile
compiler_params.mod = mod_name
compiler_params.is_test = is_test_file
compiler_params.is_script = file.ends_with('.v') || file.ends_with('.vsh')
prefs := pref.new_preferences()
if foptions.is_verbose {
eprintln('vfmt format_file: file: $file')
eprintln('vfmt format_file: cfile: $cfile')
eprintln('vfmt format_file: is_test_file: $is_test_file')
eprintln('vfmt format_file: is_module_file: $is_module_file')
eprintln('vfmt format_file: mod_name: $mod_name')
eprintln('vfmt format_file: mod_folder: $mod_folder')
eprintln('vfmt format_file: mod_folder_parent: $mod_folder_parent')
eprintln('vfmt format_file: use_tmp_main_program: $use_tmp_main_program')
eprintln('vfmt format_file: compiler_params: ')
print_compiler_options( compiler_params )
eprintln('-------------------------------------------')
eprintln('vfmt2 running fmt.fmt over file: $file')
}
compiler_params.fill_with_defaults()
table := table.new_table()
file_ast := parser.parse_file(file, table, .parse_comments, prefs)
formatted_content := fmt.fmt(file_ast, table)
file_name := os.file_name(file)
vfmt_output_path := os.join_path(os.temp_dir(), 'vfmt_' + file_name)
os.write_file(vfmt_output_path, formatted_content )
if foptions.is_verbose {
eprintln('vfmt format_file: compiler_params: AFTER fill_with_defaults() ')
print_compiler_options( compiler_params )
eprintln('vfmt2 fmt.fmt worked and ${formatted_content.len} bytes were written to ${vfmt_output_path} .')
}
formatted_file_path := foptions.compile_file(file, compiler_params)
if use_tmp_main_program {
if !foptions.is_debug {
os.rm(cfile)
}
}
eprintln('${FORMATTED_FILE_TOKEN}${formatted_file_path}')
eprintln('${FORMATTED_FILE_TOKEN}${vfmt_output_path}')
}
fn print_compiler_options( compiler_params &pref.Preferences ) {
@ -311,21 +242,6 @@ fn find_working_diff_command() ?string {
return error('no working diff command found')
}
fn (foptions &FormatOptions) compile_file(file string, compiler_params &pref.Preferences) string {
if foptions.is_verbose {
eprintln('> new_v_compiler_with_args file: $file')
eprintln('> new_v_compiler_with_args compiler_params:')
print_compiler_options( compiler_params )
}
mut v := compiler.new_v(compiler_params)
v.v_fmt_file = file
if foptions.is_all {
v.v_fmt_all = true
}
v.compile()
return v.v_fmt_file_result
}
pub fn (f FormatOptions) str() string {
return 'FormatOptions{ ' + ' is_2: $f.is_2' + ' is_l: $f.is_l' + ' is_w: $f.is_w' + ' is_diff: $f.is_diff' + ' is_verbose: $f.is_verbose' + ' is_all: $f.is_all' + ' is_worker: $f.is_worker' + ' is_debug: $f.is_debug' + ' }'
}
@ -435,3 +351,7 @@ fn join_flags_and_argument() []string {
fn non_empty(arg []string) []string {
return arg.filter(it != '')
}
fn verror(s string){
util.verror('vfmt error', s)
}

View File

@ -7,10 +7,6 @@ import (
v.pref
)
pub const (
v_modules_path = os.home_dir() + '.vmodules'
)
fn main() {
args := os.args
args_string := args[1..].join(' ')
@ -62,7 +58,8 @@ fn v_test_compiler(vargs string) {
if ret != 0 {
eprintln('failed to run v install')
}
if !os.exists(v_modules_path + '/nedpals/args') {
desired_path := os.join_path(pref.default_module_path, 'nedpals', 'args')
if !(os.exists( desired_path ) && os.is_dir( desired_path )) {
eprintln('v failed to install a test module')
}
vmark.stop()

View File

@ -11,10 +11,6 @@ import (
term
)
const (
v_modules_path = pref.default_module_path
)
fn todo() {
}
@ -157,7 +153,7 @@ fn (v mut V) cc() {
}
if v.pref.build_mode == .build_module {
// Create the modules & out directory if it's not there.
mut out_dir := if v.pref.path.starts_with('vlib') { '$v_modules_path${os.path_separator}cache${os.path_separator}$v.pref.path' } else { '$v_modules_path${os.path_separator}$v.pref.path' }
mut out_dir := if v.pref.path.starts_with('vlib') { '${pref.default_module_path}${os.path_separator}cache${os.path_separator}$v.pref.path' } else { '${pref.default_module_path}${os.path_separator}$v.pref.path' }
pdir := out_dir.all_before_last(os.path_separator)
if !os.is_dir(pdir) {
os.mkdir_all(pdir)
@ -226,7 +222,7 @@ fn (v mut V) cc() {
else if v.pref.is_cache {
/*
QTODO
builtin_o_path := os.join_path(v_modules_path, 'cache', 'vlib', 'builtin.o')
builtin_o_path := os.join_path(pref.default_module_path, 'cache', 'vlib', 'builtin.o')
a << builtin_o_path.replace('builtin.o', 'strconv.o') // TODO hack no idea why this is needed
if os.exists(builtin_o_path) {
libs = builtin_o_path
@ -243,7 +239,7 @@ fn (v mut V) cc() {
continue
}
imp_path := imp.replace('.', os.path_separator)
path := '$v_modules_path${os.path_separator}cache${os.path_separator}vlib${os.path_separator}${imp_path}.o'
path := '${pref.default_module_path}${os.path_separator}cache${os.path_separator}vlib${os.path_separator}${imp_path}.o'
// println('adding ${imp_path}.o')
if os.exists(path) {
libs += ' ' + path
@ -255,7 +251,7 @@ fn (v mut V) cc() {
os.cp('$vdir/thirdparty/ui/ui.o', path)or{
panic('error copying ui files')
}
os.cp('$vdir/thirdparty/ui/ui.vh', v_modules_path + '/vlib/ui.vh')or{
os.cp('$vdir/thirdparty/ui/ui.vh', pref.default_module_path + '/vlib/ui.vh')or{
panic('error copying ui files')
}
}
@ -484,13 +480,13 @@ fn (c mut V) cc_windows_cross() {
args += if c.pref.ccompiler == 'msvc' { cflags.c_options_before_target_msvc() } else { cflags.c_options_before_target() }
mut libs := ''
if false && c.pref.build_mode == .default_mode {
libs = '"$v_modules_path/vlib/builtin.o"'
libs = '"${pref.default_module_path}/vlib/builtin.o"'
if !os.exists(libs) {
println('`$libs` not found')
exit(1)
}
for imp in c.table.imports {
libs += ' "$v_modules_path/vlib/${imp}.o"'
libs += ' "${pref.default_module_path}/vlib/${imp}.o"'
}
}
args += ' $c.out_name_c '
@ -498,11 +494,11 @@ fn (c mut V) cc_windows_cross() {
args += if c.pref.ccompiler == 'msvc' { cflags.c_options_after_target_msvc() } else { cflags.c_options_after_target() }
/*
winroot := '$v_modules_path/winroot'
winroot := '${pref.default_module_path}/winroot'
if !os.is_dir(winroot) {
winroot_url := 'https://github.com/vlang/v/releases/download/v0.1.10/winroot.zip'
println('"$winroot" not found.')
println('Download it from $winroot_url and save it in $v_modules_path')
println('Download it from $winroot_url and save it in ${pref.default_module_path}')
println('Unzip it afterwards.\n')
println('winroot.zip contains all library and header files needed ' + 'to cross-compile for Windows.')
exit(1)
@ -522,7 +518,7 @@ fn (c mut V) cc_windows_cross() {
}
println(cmd)
//cmd := 'clang -o $obj_name -w $include -m32 -c -target x86_64-win32 $v_modules_path/$c.out_name_c'
//cmd := 'clang -o $obj_name -w $include -m32 -c -target x86_64-win32 ${pref.default_module_path}/$c.out_name_c'
if c.pref.verbosity.is_higher_or_equal(.level_one) {
println(cmd)
}

View File

@ -8,6 +8,7 @@ import (
os
v.builder
v.pref
v.util
strings
)
@ -216,13 +217,6 @@ fn (v mut V) set_module_lookup_paths() {
}
}
pub fn verror(s string) {
println('V error: $s')
os.flush()
exit(1)
}
pub fn (v &V) get_builtin_files() []string {
// Lookup for built-in folder in lookup path.
// Assumption: `builtin/` folder implies usable implementation of builtin
@ -405,4 +399,6 @@ pub fn (v &V) v_files_from_dir(dir string) []string {
return res
}
pub fn verror(s string) {
util.verror('compiler error', s)
}

View File

@ -7,6 +7,7 @@ import (
internal.flag
os.cmdline
v.pref
v.util
)
fn parse_arguments(args []string) (pref.Preferences, []string) {
@ -72,6 +73,14 @@ fn parse_arguments(args []string) (pref.Preferences, []string) {
fn parse_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
match flag {
'color' {
f.is_equivalent_to(['color','nocolor'])
util.emanager.set_support_color(true)
}
'nocolor' {
f.is_equivalent_to(['color','nocolor'])
util.emanager.set_support_color(false)
}
'path' {
// -path
path_str := f.string() or {

View File

@ -1,6 +1,7 @@
module compile
import os
import v.pref
#flag windows -l shell32
#flag windows -l dbghelp
@ -225,7 +226,7 @@ pub fn (v mut V) cc_msvc() {
}
else if v.pref.build_mode == .default_mode {
/*
b := os.real_path( '$v_modules_path/vlib/builtin.obj' )
b := os.real_path( '${pref.default_module_path}/vlib/builtin.obj' )
alibs << '"$b"'
if !os.exists(b) {
println('`builtin.obj` not found')
@ -235,7 +236,7 @@ pub fn (v mut V) cc_msvc() {
if imp == 'webview' {
continue
}
alibs << '"' + os.real_path( '$v_modules_path/vlib/${imp}.obj' ) + '"'
alibs << '"' + os.real_path( '${pref.default_module_path}/vlib/${imp}.obj' ) + '"'
}
*/
}

View File

@ -1,91 +0,0 @@
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module main
import (
os
v.pref
)
fn set_vroot_folder(vroot_path string) {
// Preparation for the compiler module:
// VEXE env variable is needed so that compiler.vexe_path()
// can return it later to whoever needs it:
vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
os.setenv('VEXE', os.real_path([vroot_path, vname].join(os.path_separator)), true)
}
fn launch_tool(is_verbose bool, tool_name string) {
vexe := pref.vexe_path()
vroot := os.dir(vexe)
set_vroot_folder(vroot)
tool_args := os.args[1..].join(' ')
tool_exe := path_of_executable(os.real_path('$vroot/cmd/tools/$tool_name'))
tool_source := os.real_path('$vroot/cmd/tools/${tool_name}.v')
tool_command := '"$tool_exe" $tool_args'
if is_verbose {
eprintln('launch_tool vexe : $vroot')
eprintln('launch_tool vroot : $vroot')
eprintln('launch_tool tool_args : $tool_args')
eprintln('launch_tool tool_command: $tool_command')
}
// TODO Caching should be done on the `vlib/v` level.
mut should_compile := false
if !os.exists(tool_exe) {
should_compile = true
} else {
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(vexe) {
// v was recompiled, maybe after v up ...
// rebuild the tool too just in case
should_compile = true
if tool_name == 'vself' || tool_name == 'vup' {
// The purpose of vself/up is to update and recompile v itself.
// After the first 'v self' execution, v will be modified, so
// then a second 'v self' will detect, that v is newer than the
// vself executable, and try to recompile vself/up again, which
// will slow down the next v recompilation needlessly.
should_compile = false
}
}
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(tool_source) {
// the user changed the source code of the tool, or git updated it:
should_compile = true
}
}
if is_verbose {
eprintln('launch_tool should_compile: $should_compile')
}
if should_compile {
mut compilation_command := '"$vexe" '
if tool_name == 'vfmt' {
// TODO Remove when it's no longer required by fmt
compilation_command += '-d vfmt '
}
compilation_command += '"$tool_source"'
if is_verbose {
eprintln('Compiling $tool_name with: "$compilation_command"')
}
tool_compilation := os.exec(compilation_command) or { panic(err) }
if tool_compilation.exit_code != 0 {
panic('V tool "$tool_source" could not be compiled\n' + tool_compilation.output)
}
}
if is_verbose {
eprintln('launch_tool running tool command: $tool_command ...')
}
exit(os.system(tool_command))
}
fn path_of_executable(path string) string {
$if windows {
return path + '.exe'
}
return path
}

View File

@ -30,7 +30,7 @@ fn main() {
if args.len == 0 || args[0] in ['-', 'repl'] {
// Running `./v` without args launches repl
println('For usage information, quit V REPL using `exit` and use `v help`')
launch_tool(false, 'vrepl')
util.launch_tool(false, 'vrepl')
return
}
if args.len > 0 && (args[0] in ['version', '-V', '-version', '--version'] || (args[0] == '-v' && args.len == 1) ) {
@ -53,7 +53,7 @@ fn main() {
// Note for future contributors: Please add new subcommands in the `match` block below.
if command in simple_cmd {
// External tools
launch_tool(prefs2.is_verbose, 'v' + command)
util.launch_tool(prefs2.is_verbose, 'v' + command)
return
}
match command {
@ -61,7 +61,7 @@ fn main() {
invoke_help_and_exit(args)
}
'create', 'init' {
launch_tool(prefs2.is_verbose, 'vcreate')
util.launch_tool(prefs2.is_verbose, 'vcreate')
return
}
'translate' {
@ -69,7 +69,7 @@ fn main() {
return
}
'search', 'install', 'update', 'remove' {
launch_tool(prefs2.is_verbose, 'vpm')
util.launch_tool(prefs2.is_verbose, 'vpm')
return
}
'get' {

View File

@ -6,6 +6,7 @@ import (
v.ast
v.table
v.pref
v.util
v.checker
v.parser
v.gen
@ -195,10 +196,6 @@ pub fn (b &Builder) v_files_from_dir(dir string) []string {
return res
}
fn verror(err string) {
panic('v error: $err')
}
pub fn (b &Builder) log(s string) {
if b.pref.verbosity.is_higher_or_equal(.level_two) {
println(s)
@ -233,3 +230,7 @@ pub fn (b &Builder) find_module_path(mod string) ?string {
}
return error('module "$mod" not found')
}
fn verror(s string) {
util.verror('builder error', s)
}

View File

@ -8,6 +8,7 @@ import (
v.table
v.token
v.pref
v.util
os
)
@ -922,15 +923,6 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
if !name.contains('.') && !(c.file.mod.name in ['builtin', 'main']) {
name = '${c.file.mod.name}.$ident.name'
}
// hack - const until consts are fixed properly
if ident.name == 'v_modules_path' {
ident.name = name
ident.kind = .constant
ident.info = ast.IdentVar{
typ: table.string_type
}
return table.string_type
}
// constant
if constant := c.table.find_const(name) {
ident.name = name
@ -1180,28 +1172,17 @@ pub fn (c mut Checker) error(s string, pos token.Position) {
if c.pref.verbosity.is_higher_or_equal(.level_one) {
print_backtrace()
}
mut path := c.file.path
// Get relative path
workdir := os.getwd() + os.path_separator
if path.starts_with(workdir) {
path = path.replace(workdir, '')
kind := if c.pref.verbosity.is_higher_or_equal(.level_one) {
'checker error #$c.nr_errors:'
} else {
'error:'
}
mut final_msg_line := '$path:$pos.line_nr: $s'
if c.pref.verbosity.is_higher_or_equal(.level_one) {
final_msg_line = '$path:$pos.line_nr: checker error #$c.nr_errors: $s'
}
c.errors << final_msg_line
ferror := util.formated_error(kind, s, c.file.path, pos)
c.errors << ferror
if !(pos.line_nr in c.error_lines) {
eprintln(final_msg_line)
eprintln(ferror)
}
c.error_lines << pos.line_nr
/*
if colored_output {
eprintln(term.bold(term.red(final_msg_line)))
}else{
eprintln(final_msg_line)
}
*/
if c.pref.verbosity.is_higher_or_equal(.level_one) {
println('\n\n')
}

View File

@ -2022,8 +2022,7 @@ fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
}
fn verror(s string) {
println('cgen error: $s')
exit(1)
util.verror('cgen error', s)
}
fn (g mut Gen) write_init_function() {

View File

@ -5,6 +5,7 @@ module x64
import (
v.ast
v.util
// term
)
@ -387,11 +388,10 @@ fn (g mut Gen) expr(node ast.Expr) {
ast.IfExpr {}
else {
// println(term.red('x64.expr(): bad node'))
}
}
}
}
}
fn verror(s string) {
println(s)
exit(1)
}
fn verror(s string) {
util.verror('x64 gen error', s)
}

View File

@ -9,6 +9,7 @@ import (
v.token
v.table
v.pref
v.util
term
os
// runtime
@ -16,10 +17,6 @@ import (
// time
)
const (
colored_output = term.can_show_color_on_stderr()
)
struct Parser {
scanner &scanner.Scanner
file_name string
@ -235,7 +232,7 @@ fn (p mut Parser) check(expected token.Kind) {
// p.next()
// }
if p.tok.kind != expected {
s := 'syntax error: unexpected `${p.tok.kind.str()}`, expecting `${expected.str()}`'
s := 'unexpected `${p.tok.kind.str()}`, expecting `${expected.str()}`'
p.error(s)
}
p.next()
@ -328,7 +325,7 @@ pub fn (p mut Parser) top_stmt() ast.Stmt {
}
else {
// #printf("");
p.error('parser: bad top level statement ' + p.tok.str())
p.error('bad top level statement ' + p.tok.str())
return ast.Stmt{}
}
}
@ -499,42 +496,19 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
pub fn (p &Parser) error(s string) {
print_backtrace()
mut path := p.file_name
// Get relative path
workdir := os.getwd() + os.path_separator
if path.starts_with(workdir) {
path = path.replace(workdir, '')
}
final_msg_line := '$path:$p.tok.line_nr: error: $s'
if colored_output {
eprintln(term.bold(term.red(final_msg_line)))
}
else {
eprintln(final_msg_line)
}
exit(1)
}
pub fn (p &Parser) error_at_line(s string, line_nr int) {
final_msg_line := '$p.file_name:$line_nr: error: $s'
if colored_output {
eprintln(term.bold(term.red(final_msg_line)))
}
else {
eprintln(final_msg_line)
mut kind := 'error:'
if p.pref.verbosity.is_higher_or_equal(.level_one) {
print_backtrace()
kind = 'parser error:'
}
ferror := util.formated_error(kind, s, p.file_name, p.tok.position())
eprintln(ferror)
exit(1)
}
pub fn (p &Parser) warn(s string) {
final_msg_line := '$p.file_name:$p.tok.line_nr: warning: $s'
if colored_output {
eprintln(term.bold(term.blue(final_msg_line)))
}
else {
eprintln(final_msg_line)
}
ferror := util.formated_error('warning:', s, p.file_name, p.tok.position())
eprintln(ferror)
}
pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident {
@ -839,7 +813,7 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
p.check(.rcbr)
}
else {
p.error('parser: expr(): bad token `$p.tok.str()`')
p.error('expr(): bad token `$p.tok.str()`')
}
}
// Infix
@ -2003,6 +1977,5 @@ fn (p &Parser) new_true_expr() ast.Expr {
}
fn verror(s string) {
println(s)
exit(1)
util.verror('parser error', s)
}

View File

@ -4,11 +4,22 @@
module pref
import os
import term
pub const (
default_module_path = os.home_dir() + '.vmodules'
default_module_path = mpath()
)
fn mpath() string {
return os.home_dir() + '.vmodules'
}
pub fn new_preferences() Preferences {
p := Preferences{}
p.fill_with_defaults()
return p
}
pub fn (p mut Preferences) fill_with_defaults() {
if p.vroot == '' {
// Location of all vlib files
@ -22,7 +33,7 @@ pub fn (p mut Preferences) fill_with_defaults() {
p.lookup_path[i] = path.replace('@vlib', vlib_path).replace('@vmodules', default_module_path)
}
rpath := os.real_path(p.path)
if p.out_name == ''{
if p.out_name == '' {
filename := os.file_name(rpath).trim_space()
mut base := filename.all_before_last('.')
if base == '' {
@ -60,6 +71,7 @@ pub fn (p mut Preferences) fill_with_defaults() {
}
}
}
p.enable_globals = true
}
fn default_c_compiler() string {

View File

@ -13,8 +13,6 @@ import (
const (
single_quote = `\'`
double_quote = `"`
error_context_before = 2 // how many lines of source context to print before the pointer line
error_context_after = 2 // ^^^ same, but after
is_fmt = os.getenv('VEXE').contains('vfmt')
num_sep = `_` // char used as number separator
)
@ -1027,9 +1025,7 @@ pub fn (s &Scanner) error(msg string) {
}
pub fn verror(s string) {
println('V error: $s')
os.flush()
exit(1)
util.verror('scanner error', s)
}
pub fn cescaped_path(s string) string {

View File

@ -0,0 +1,88 @@
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module util
import os
import term
import v.token
import v.util
// The filepath:line:col: format is the default C compiler error output format.
// It allows editors and IDE's like emacs to quickly find the errors in the
// output and jump to their source with a keyboard shortcut.
// NB: using only the filename may lead to inability of IDE/editors
// to find the source file, when the IDE has a different working folder than
// v itself.
const (
error_context_before = 2 // how many lines of source context to print before the pointer line
error_context_after = 2 // ^^^ same, but after
)
pub const (
emanager = new_error_manager()
)
//
pub struct EManager {
pub mut:
support_color bool // should the error and other messages
// have ANSI terminal escape color codes in them.
// By default, v tries to autodetect, if the terminal supports colors.
// Use -color and -nocolor options to override the detection decision.
}
pub fn (e &EManager) set_support_color(b bool) {
e.support_color = b
}
pub fn new_error_manager() &EManager {
return &EManager{ support_color: term.can_show_color_on_stderr() }
}
pub fn formated_error(kind string /*error or warn*/, emsg string, filepath string, pos token.Position) string {
mut path := filepath
verror_paths_override := os.getenv('VERROR_PATHS')
if verror_paths_override == 'absolute' {
path = os.real_path( path )
}else{
// Get relative path
workdir := os.getwd() + os.path_separator
if path.starts_with(workdir) {
path = path.replace(workdir, '')
}
}
column := 0
position := '${path}:${pos.line_nr+1}:$column:'
// QTODO: retrieve source lines around pos.line_nr and add them here
mut source_context := ''
//
final_position := if emanager.support_color {
term.bold(term.white(position))
} else {
position
}
mut final_kind := kind
if emanager.support_color {
final_kind = if kind.contains('error') {
term.bold(term.red(kind))
}else{
term.bold(term.bright_blue(kind))
}
}
final_msg := emsg
final_context := if source_context.len > 0 { '\n$source_context' } else { '' }
//
return '$final_position $final_kind $final_msg $final_context'.trim_space()
}
pub fn verror(kind string, s string) {
if emanager.support_color {
eprintln( term.bold(term.red(kind)) + ': $s' )
}else{
eprintln('${kind}: $s')
}
exit(1)
}

View File

@ -4,6 +4,7 @@
module util
import os
import v.pref
pub const (
v_version = '0.1.26'
@ -75,3 +76,82 @@ pub fn githash(should_get_from_filesystem bool) string {
C.snprintf(charptr(buf), 50, '%s', C.V_CURRENT_COMMIT_HASH)
return tos_clone(buf)
}
//
fn set_vroot_folder(vroot_path string) {
// Preparation for the compiler module:
// VEXE env variable is needed so that compiler.vexe_path()
// can return it later to whoever needs it:
vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
os.setenv('VEXE', os.real_path(os.join_path( vroot_path, vname)), true)
}
pub fn launch_tool(is_verbose bool, tool_name string) {
vexe := pref.vexe_path()
vroot := os.dir(vexe)
set_vroot_folder(vroot)
tool_args := os.args[1..].join(' ')
tool_exe := path_of_executable(os.real_path('$vroot/cmd/tools/$tool_name'))
tool_source := os.real_path('$vroot/cmd/tools/${tool_name}.v')
tool_command := '"$tool_exe" $tool_args'
if is_verbose {
eprintln('launch_tool vexe : $vroot')
eprintln('launch_tool vroot : $vroot')
eprintln('launch_tool tool_args : $tool_args')
eprintln('launch_tool tool_command: $tool_command')
}
// TODO Caching should be done on the `vlib/v` level.
mut should_compile := false
if !os.exists(tool_exe) {
should_compile = true
} else {
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(vexe) {
// v was recompiled, maybe after v up ...
// rebuild the tool too just in case
should_compile = true
if tool_name == 'vself' || tool_name == 'vup' {
// The purpose of vself/up is to update and recompile v itself.
// After the first 'v self' execution, v will be modified, so
// then a second 'v self' will detect, that v is newer than the
// vself executable, and try to recompile vself/up again, which
// will slow down the next v recompilation needlessly.
should_compile = false
}
}
if os.file_last_mod_unix(tool_exe) <= os.file_last_mod_unix(tool_source) {
// the user changed the source code of the tool, or git updated it:
should_compile = true
}
}
if is_verbose {
eprintln('launch_tool should_compile: $should_compile')
}
if should_compile {
mut compilation_command := '"$vexe" '
compilation_command += '"$tool_source"'
if is_verbose {
eprintln('Compiling $tool_name with: "$compilation_command"')
}
tool_compilation := os.exec(compilation_command) or { panic(err) }
if tool_compilation.exit_code != 0 {
panic('V tool "$tool_source" could not be compiled\n' + tool_compilation.output)
}
}
if is_verbose {
eprintln('launch_tool running tool command: $tool_command ...')
}
exit(os.system(tool_command))
}
pub fn path_of_executable(path string) string {
$if windows {
return path + '.exe'
}
return path
}