merge and simplify cmd/v and v.builder
parent
8da12eb8a7
commit
8d150d427a
100
cmd/v/flag.v
100
cmd/v/flag.v
|
@ -1,100 +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 (
|
|
||||||
internal.flag
|
|
||||||
os
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
list_of_flags_that_allow_duplicates = ['cc','d','define','cf','cflags']
|
|
||||||
//list_of_flags contains a list of flags where an argument is expected past it.
|
|
||||||
list_of_flags_with_param = [
|
|
||||||
'o', 'output', 'd', 'define', 'b', 'backend', 'cc', 'os', 'target-os', 'arch',
|
|
||||||
'csource', 'cf', 'cflags', 'path'
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
fn join_flags_and_argument() []string {
|
|
||||||
vosargs := os.getenv('VOSARGS')
|
|
||||||
if vosargs != '' {
|
|
||||||
return vosargs.split(' ')
|
|
||||||
}
|
|
||||||
// No VOSARGS? Look for VFLAGS and concat it with command-line options.
|
|
||||||
mut args := []string
|
|
||||||
vflags := os.getenv('VFLAGS')
|
|
||||||
if vflags != '' {
|
|
||||||
args << os.args[0]
|
|
||||||
args << vflags.split(' ')
|
|
||||||
if os.args.len > 1 {
|
|
||||||
args << os.args[1..]
|
|
||||||
}
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
// No VFLAGS too? Just return command-line args.
|
|
||||||
return os.args
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_flags(flag string, f mut flag.Instance, prefs mut flag.MainCmdPreferences) {
|
|
||||||
match flag {
|
|
||||||
'v' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
prefs.verbosity = .level_one
|
|
||||||
}
|
|
||||||
'vv' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
prefs.verbosity = .level_two
|
|
||||||
}
|
|
||||||
'vvv' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
prefs.verbosity = .level_three
|
|
||||||
}
|
|
||||||
'verbose' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
level := f.int() or {
|
|
||||||
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
match level {
|
|
||||||
0 {} //Zero verbosity is already default.
|
|
||||||
1 {
|
|
||||||
prefs.verbosity = .level_one
|
|
||||||
}
|
|
||||||
2 {
|
|
||||||
prefs.verbosity = .level_two
|
|
||||||
}
|
|
||||||
3 {
|
|
||||||
prefs.verbosity = .level_three
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'h', 'help' {
|
|
||||||
f.is_equivalent_to(['h', 'help'])
|
|
||||||
prefs.action = .help
|
|
||||||
}
|
|
||||||
'version' {
|
|
||||||
prefs.action = .version
|
|
||||||
}
|
|
||||||
'-version', '-help' {
|
|
||||||
println('V error: `-$flag` has been deprecated. Use `$flag` instead.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prefs.unknown_flag = '-$flag'
|
|
||||||
if !(flag in list_of_flags_with_param) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f.string() or {
|
|
||||||
println('V error: Error parsing flag. Expected value for `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +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 compile
|
|
||||||
|
|
||||||
import (
|
|
||||||
os
|
|
||||||
v.pref
|
|
||||||
)
|
|
||||||
|
|
||||||
fn check_for_common_mistake(args []string, p &pref.Preferences) {
|
|
||||||
// Note: This feature is still currently commonly used. Uncomment this when
|
|
||||||
// proper deprecation detection is ready.
|
|
||||||
if p.out_name.ends_with('.c') && p.backend == .c {
|
|
||||||
//println('HINT: `-o $p.out_name` implies `-csource keep` and does not results in an executable currently.')
|
|
||||||
//println(' To overwrite this, specify `-csource drop` explicitly.')
|
|
||||||
}
|
|
||||||
if p.out_name.ends_with('.js') && p.backend != .js {
|
|
||||||
println('HINT: `-o $p.out_name` implies `-backend js` currently.')
|
|
||||||
//println(' To overwrite this, specify the intended backend explicitly.')
|
|
||||||
}
|
|
||||||
if p.path == 'vlib/compiler' || p.path == 'v.v' {
|
|
||||||
println('HINT: The V compiler is now located in `cmd/v`.')
|
|
||||||
println(' `$p.path` is no longer the correct path to compile if you are intending to do so.')
|
|
||||||
}
|
|
||||||
if !p.path.ends_with('.v') && !os.is_dir(p.path) && os.is_dir(p.path + os.path_separator) {
|
|
||||||
println('HINT: `$p.path` is not a directory nor a file suffixed with `.v`.')
|
|
||||||
println(' Did you perhaps accidentally reference the compiled executable?')
|
|
||||||
println(' To make sure V detects the directory correctly, add the path separator to the end of the path like so:')
|
|
||||||
println(' `v $p.path$os.path_separator`')
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,404 +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 compile
|
|
||||||
|
|
||||||
import (
|
|
||||||
benchmark
|
|
||||||
os
|
|
||||||
v.builder
|
|
||||||
v.pref
|
|
||||||
v.util
|
|
||||||
strings
|
|
||||||
)
|
|
||||||
|
|
||||||
pub struct V {
|
|
||||||
pub mut:
|
|
||||||
mod_file_cacher &builder.ModFileCacher // used during lookup for v.mod to support @VROOT
|
|
||||||
out_name_c string // name of the temporary C file
|
|
||||||
files []string // all V files that need to be parsed and compiled
|
|
||||||
compiled_dir string // contains os.real_path() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
|
|
||||||
pref &pref.Preferences // all the preferences and settings extracted to a struct for reusability
|
|
||||||
vgen_buf strings.Builder // temporary buffer for generated V code (.str() etc)
|
|
||||||
file_parser_idx map[string]int // map absolute file path to v.parsers index
|
|
||||||
gen_parser_idx map[string]int
|
|
||||||
cached_mods []string
|
|
||||||
module_lookup_paths []string
|
|
||||||
|
|
||||||
v_fmt_all bool // << input set by cmd/tools/vfmt.v
|
|
||||||
v_fmt_file string // << file given by the user from cmd/tools/vfmt.v
|
|
||||||
v_fmt_file_result string // >> file with formatted output generated by vlib/compiler/vfmt.v
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_v(pref &pref.Preferences) &V {
|
|
||||||
rdir := os.real_path(pref.path)
|
|
||||||
|
|
||||||
mut out_name_c := get_vtmp_filename(pref.out_name, '.tmp.c')
|
|
||||||
if pref.is_so {
|
|
||||||
out_name_c = get_vtmp_filename(pref.out_name, '.tmp.so.c')
|
|
||||||
}
|
|
||||||
|
|
||||||
mut vgen_buf := strings.new_builder(1000)
|
|
||||||
vgen_buf.writeln('module vgen\nimport strings')
|
|
||||||
compiled_dir:=if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
|
|
||||||
|
|
||||||
return &V{
|
|
||||||
mod_file_cacher: builder.new_mod_file_cacher()
|
|
||||||
compiled_dir:compiled_dir// if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
|
|
||||||
out_name_c: out_name_c
|
|
||||||
pref: pref
|
|
||||||
vgen_buf: vgen_buf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// make v2 from v1
|
|
||||||
fn (v &V) new_v2() builder.Builder {
|
|
||||||
mut b := builder.new_builder(v.pref)
|
|
||||||
b = { b|
|
|
||||||
os: v.pref.os,
|
|
||||||
module_path: pref.default_module_path,
|
|
||||||
compiled_dir: v.compiled_dir,
|
|
||||||
module_search_paths: v.module_lookup_paths
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_vtmp_folder() string {
|
|
||||||
vtmp := os.join_path(os.temp_dir(), 'v')
|
|
||||||
if !os.is_dir(vtmp) {
|
|
||||||
os.mkdir(vtmp) or {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vtmp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_vtmp_filename(base_file_name string, postfix string) string {
|
|
||||||
vtmp := get_vtmp_folder()
|
|
||||||
return os.real_path(os.join_path(vtmp, os.file_name(os.real_path(base_file_name)) + postfix))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn (v mut V) compile_x64() {
|
|
||||||
$if !linux {
|
|
||||||
println('v -x64 can only generate Linux binaries for now')
|
|
||||||
println('You are not on a Linux system, so you will not ' + 'be able to run the resulting executable')
|
|
||||||
}
|
|
||||||
//v.files << v.v_files_from_dir(os.join_path(v.pref.vlib_path,'builtin','bare'))
|
|
||||||
v.files << v.pref.path
|
|
||||||
v.set_module_lookup_paths()
|
|
||||||
mut b := v.new_v2()
|
|
||||||
// move all this logic to v2
|
|
||||||
b.build_x64(v.files, v.pref.out_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn (v mut V) compile2() {
|
|
||||||
if os.user_os() != 'windows' && v.pref.ccompiler == 'msvc' {
|
|
||||||
verror('Cannot build with msvc on ${os.user_os()}')
|
|
||||||
}
|
|
||||||
//cgen.genln('// Generated by V')
|
|
||||||
//println('compile2()')
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
|
||||||
println('all .v files before:')
|
|
||||||
println(v.files)
|
|
||||||
}
|
|
||||||
// v1 compiler files
|
|
||||||
//v.add_v_files_to_compile()
|
|
||||||
//v.files << v.dir
|
|
||||||
// v2 compiler
|
|
||||||
v.files << v.get_builtin_files()
|
|
||||||
v.files << v.get_user_files()
|
|
||||||
v.set_module_lookup_paths()
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
|
||||||
println('all .v files:')
|
|
||||||
println(v.files)
|
|
||||||
}
|
|
||||||
mut b := v.new_v2()
|
|
||||||
b.build_c(v.files, v.out_name_c)// v.pref.out_name + '.c')
|
|
||||||
v.cc()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn compile(command string, args []string) {
|
|
||||||
// Construct the V object from command line arguments
|
|
||||||
parse_and_output_new_format(args)
|
|
||||||
prefs, remaining := parse_arguments(args)
|
|
||||||
check_for_common_mistake(args, prefs)
|
|
||||||
mut v := new_v(prefs)
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
println(args)
|
|
||||||
}
|
|
||||||
mut tmark := benchmark.new_benchmark()
|
|
||||||
if v.pref.backend == .x64 {
|
|
||||||
v.compile_x64()
|
|
||||||
}
|
|
||||||
else if v.pref.backend == .experimental {
|
|
||||||
v.compile2()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//v.compile()
|
|
||||||
v.compile2()
|
|
||||||
}
|
|
||||||
if v.pref.is_stats {
|
|
||||||
tmark.stop()
|
|
||||||
println('compilation took: ' + tmark.total_duration().str() + 'ms')
|
|
||||||
}
|
|
||||||
if v.pref.is_test || v.pref.is_run {
|
|
||||||
run_compiled_executable_and_exit(v, remaining)
|
|
||||||
}
|
|
||||||
//v.finalize_compilation()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_compiled_executable_and_exit(v &V, remaining_args []string) {
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
println('============ running $v.pref.out_name ============')
|
|
||||||
}
|
|
||||||
mut cmd := '"${v.pref.out_name}"'
|
|
||||||
for i in 1..remaining_args.len {
|
|
||||||
// Determine if there are spaces in the parameters
|
|
||||||
if remaining_args[i].index_byte(` `) > 0 {
|
|
||||||
cmd += ' "' + remaining_args[i] + '"'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cmd += ' ' + remaining_args[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
println('command to run executable: $cmd')
|
|
||||||
}
|
|
||||||
if v.pref.is_test {
|
|
||||||
ret := os.system(cmd)
|
|
||||||
if ret != 0 {
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.pref.is_run {
|
|
||||||
ret := os.system(cmd)
|
|
||||||
// TODO: make the runner wrapping as transparent as possible
|
|
||||||
// (i.e. use execve when implemented). For now though, the runner
|
|
||||||
// just returns the same exit code as the child process.
|
|
||||||
exit(ret)
|
|
||||||
}
|
|
||||||
exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'strings' => 'VROOT/vlib/strings'
|
|
||||||
// 'installed_mod' => '~/.vmodules/installed_mod'
|
|
||||||
// 'local_mod' => '/path/to/current/dir/local_mod'
|
|
||||||
fn (v mut V) set_module_lookup_paths() {
|
|
||||||
// Module search order:
|
|
||||||
// 0) V test files are very commonly located right inside the folder of the
|
|
||||||
// module, which they test. Adding the parent folder of the module folder
|
|
||||||
// with the _test.v files, *guarantees* that the tested module can be found
|
|
||||||
// without needing to set custom options/flags.
|
|
||||||
// 1) search in the *same* directory, as the compiled final v program source
|
|
||||||
// (i.e. the . in `v .` or file.v in `v file.v`)
|
|
||||||
// 2) search in the modules/ in the same directory.
|
|
||||||
// 3) search in the provided paths
|
|
||||||
// By default, these are what (3) contains:
|
|
||||||
// 3.1) search in vlib/
|
|
||||||
// 3.2) search in ~/.vmodules/ (i.e. modules installed with vpm)
|
|
||||||
v.module_lookup_paths = []
|
|
||||||
if v.pref.is_test {
|
|
||||||
v.module_lookup_paths << os.base_dir(v.compiled_dir) // pdir of _test.v
|
|
||||||
}
|
|
||||||
v.module_lookup_paths << v.compiled_dir
|
|
||||||
x := os.join_path(v.compiled_dir, 'modules')
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
println('x: "$x"')
|
|
||||||
}
|
|
||||||
v.module_lookup_paths << os.join_path(v.compiled_dir, 'modules')
|
|
||||||
v.module_lookup_paths << v.pref.lookup_path
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
v.log('v.module_lookup_paths') //: $v.module_lookup_paths')
|
|
||||||
println(v.module_lookup_paths)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (v &V) get_builtin_files() []string {
|
|
||||||
// Lookup for built-in folder in lookup path.
|
|
||||||
// Assumption: `builtin/` folder implies usable implementation of builtin
|
|
||||||
for location in v.pref.lookup_path {
|
|
||||||
if !os.exists(os.join_path(location, 'builtin')) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if v.pref.is_bare {
|
|
||||||
return v.v_files_from_dir(os.join_path(location, 'builtin', 'bare'))
|
|
||||||
}
|
|
||||||
$if js {
|
|
||||||
return v.v_files_from_dir(os.join_path(location, 'builtin', 'js'))
|
|
||||||
}
|
|
||||||
return v.v_files_from_dir(os.join_path(location, 'builtin'))
|
|
||||||
}
|
|
||||||
// Panic. We couldn't find the folder.
|
|
||||||
verror('`builtin/` not included on module lookup path.
|
|
||||||
Did you forget to add vlib to the path? (Use @vlib for default vlib)')
|
|
||||||
panic('Unreachable code reached.')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn (v &V) get_user_files() []string {
|
|
||||||
mut dir := v.pref.path
|
|
||||||
v.log('get_v_files($dir)')
|
|
||||||
// Need to store user files separately, because they have to be added after
|
|
||||||
// libs, but we dont know which libs need to be added yet
|
|
||||||
mut user_files := []string
|
|
||||||
|
|
||||||
// See cmd/tools/preludes/README.md for more info about what preludes are
|
|
||||||
vroot := os.dir(pref.vexe_path())
|
|
||||||
preludes_path := os.join_path(vroot, 'cmd', 'tools', 'preludes')
|
|
||||||
if v.pref.is_live {
|
|
||||||
user_files << os.join_path(preludes_path, 'live_main.v')
|
|
||||||
}
|
|
||||||
if v.pref.is_solive {
|
|
||||||
user_files << os.join_path(preludes_path, 'live_shared.v')
|
|
||||||
}
|
|
||||||
if v.pref.is_test {
|
|
||||||
user_files << os.join_path(preludes_path, 'tests_assertions.v')
|
|
||||||
}
|
|
||||||
if v.pref.is_test && v.pref.is_stats {
|
|
||||||
user_files << os.join_path(preludes_path, 'tests_with_stats.v')
|
|
||||||
}
|
|
||||||
|
|
||||||
is_test := dir.ends_with('_test.v')
|
|
||||||
mut is_internal_module_test := false
|
|
||||||
if is_test {
|
|
||||||
tcontent := os.read_file(dir)or{
|
|
||||||
panic('$dir does not exist')
|
|
||||||
}
|
|
||||||
slines := tcontent.trim_space().split_into_lines()
|
|
||||||
for sline in slines {
|
|
||||||
line := sline.trim_space()
|
|
||||||
if line.len > 2 {
|
|
||||||
if line[0] == `/` && line[1] == `/` {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if line.starts_with('module ') && !line.starts_with('module main') {
|
|
||||||
is_internal_module_test = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_internal_module_test {
|
|
||||||
// v volt/slack_test.v: compile all .v files to get the environment
|
|
||||||
single_test_v_file := os.real_path(dir)
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
v.log('> Compiling an internal module _test.v file $single_test_v_file .')
|
|
||||||
v.log('> That brings in all other ordinary .v files in the same module too .')
|
|
||||||
}
|
|
||||||
user_files << single_test_v_file
|
|
||||||
dir = os.base_dir(single_test_v_file)
|
|
||||||
}
|
|
||||||
is_real_file := os.exists(dir) && !os.is_dir(dir)
|
|
||||||
if is_real_file && ( dir.ends_with('.v') || dir.ends_with('.vsh') ) {
|
|
||||||
single_v_file := dir
|
|
||||||
// Just compile one file and get parent dir
|
|
||||||
user_files << single_v_file
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
v.log('> just compile one file: "${single_v_file}"')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
v.log('> add all .v files from directory "${dir}" ...')
|
|
||||||
}
|
|
||||||
// Add .v files from the directory being compiled
|
|
||||||
files := v.v_files_from_dir(dir)
|
|
||||||
for file in files {
|
|
||||||
user_files << file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if user_files.len == 0 {
|
|
||||||
println('No input .v files')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
v.log('user_files: $user_files')
|
|
||||||
}
|
|
||||||
return user_files
|
|
||||||
}
|
|
||||||
pub fn (v &V) log(s string) {
|
|
||||||
if !v.pref.verbosity.is_higher_or_equal(.level_two) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
println(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn (v &V) v_files_from_dir(dir string) []string {
|
|
||||||
mut res := []string
|
|
||||||
if !os.exists(dir) {
|
|
||||||
if dir == 'compiler' && os.is_dir('vlib') {
|
|
||||||
println('looks like you are trying to build V with an old command')
|
|
||||||
println('use `v -o v cmd/v` instead of `v -o v compiler`')
|
|
||||||
}
|
|
||||||
verror("$dir doesn't exist")
|
|
||||||
}
|
|
||||||
else if !os.is_dir(dir) {
|
|
||||||
verror("$dir isn't a directory!")
|
|
||||||
}
|
|
||||||
mut files := os.ls(dir)or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
|
||||||
println('v_files_from_dir ("$dir")')
|
|
||||||
}
|
|
||||||
files.sort()
|
|
||||||
for file in files {
|
|
||||||
if !file.ends_with('.v') && !file.ends_with('.vh') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_test.v') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (file.ends_with('_win.v') || file.ends_with('_windows.v')) && v.pref.os != .windows {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (file.ends_with('_lin.v') || file.ends_with('_linux.v')) && v.pref.os != .linux {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (file.ends_with('_mac.v') || file.ends_with('_darwin.v')) && v.pref.os != .mac {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_nix.v') && v.pref.os == .windows {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_android.v') && v.pref.os != .android {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_freebsd.v') && v.pref.os != .freebsd {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_solaris.v') && v.pref.os != .solaris {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_js.v') && v.pref.os != .js {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if file.ends_with('_c.v') && v.pref.os == .js {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if v.pref.compile_defines_all.len > 0 && file.contains('_d_') {
|
|
||||||
mut allowed := false
|
|
||||||
for cdefine in v.pref.compile_defines {
|
|
||||||
file_postfix := '_d_${cdefine}.v'
|
|
||||||
if file.ends_with(file_postfix) {
|
|
||||||
allowed = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !allowed {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res << os.join_path(dir, file)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verror(s string) {
|
|
||||||
util.verror('compiler error', s)
|
|
||||||
}
|
|
|
@ -1,75 +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 compile
|
|
||||||
|
|
||||||
// This file contains the options specific to the C backend of V.
|
|
||||||
// To add a flag to all backends at once, please add the flag to `parse_options()` in `compile_options.v`.
|
|
||||||
// To add a flag to both x64 and C, please add the flag to `parse_executable_options()` in `compile_x64_options.v`.
|
|
||||||
|
|
||||||
import (
|
|
||||||
internal.flag
|
|
||||||
v.pref
|
|
||||||
)
|
|
||||||
|
|
||||||
fn parse_c_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
|
||||||
match flag {
|
|
||||||
'cc', 'compiler' {
|
|
||||||
f.is_equivalent_to(['cc', 'compiler'])
|
|
||||||
//TODO Remove `tmp` variable when it doesn't error out in C.
|
|
||||||
tmp := f.string() or {
|
|
||||||
println('V error: Expected argument after `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
prefs.ccompiler = tmp
|
|
||||||
}
|
|
||||||
'cg', 'cdebug' {
|
|
||||||
f.is_equivalent_to(['cg', 'cdebug', 'g', 'debug'])
|
|
||||||
if f.bool() {
|
|
||||||
prefs.is_debug = true
|
|
||||||
prefs.is_vlines = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'live' {
|
|
||||||
prefs.is_live = f.bool()
|
|
||||||
}
|
|
||||||
'csource' {
|
|
||||||
operation := f.string() or {
|
|
||||||
println('V error: Expected argument after `-csource`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
match operation {
|
|
||||||
'keep' {
|
|
||||||
prefs.is_keep_c = true
|
|
||||||
}
|
|
||||||
'drop' {} //Default
|
|
||||||
else {
|
|
||||||
println('V error: Unknown argument for `-csource` (`$operation`).')
|
|
||||||
println('Allowed options: `keep`, `prettify` and `drop`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'sanitize' {
|
|
||||||
prefs.sanitize = f.bool()
|
|
||||||
}
|
|
||||||
'cf', 'cflags' {
|
|
||||||
cflag := f.string() or {
|
|
||||||
println('V error: Expected argument after `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
prefs.cflags += ' $cflag'
|
|
||||||
}
|
|
||||||
// TODO Deprecate these once v2 parser is live
|
|
||||||
'repl' {
|
|
||||||
prefs.is_repl = f.bool()
|
|
||||||
}
|
|
||||||
'solive' {
|
|
||||||
prefs.is_solive = f.bool()
|
|
||||||
prefs.is_so = prefs.is_solive
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parse_executable_options(flag, mut f, mut prefs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +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 compile
|
|
||||||
|
|
||||||
// This file contains the options specific to the JS backend of V.
|
|
||||||
|
|
||||||
import (
|
|
||||||
internal.flag
|
|
||||||
v.pref
|
|
||||||
)
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn parse_js_options(flag string, f flag.Instance, prefs pref.Preferences) {
|
|
||||||
// No notable flags for JS-only currently. Add them here when they are needed.
|
|
||||||
// For now, we just fail as this is meant to be a fallback.
|
|
||||||
println('V error: Unknown flag `-$flag` provided.')
|
|
||||||
println('Use `--` to terminate flag list if necessary.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
|
@ -1,235 +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 compile
|
|
||||||
|
|
||||||
import (
|
|
||||||
internal.flag
|
|
||||||
os.cmdline
|
|
||||||
v.pref
|
|
||||||
v.util
|
|
||||||
)
|
|
||||||
|
|
||||||
fn parse_arguments(args []string) (pref.Preferences, []string) {
|
|
||||||
mut p := pref.Preferences{
|
|
||||||
//TODO: Refactor away this preference.
|
|
||||||
// It's no longer controlled by a command-line flag.
|
|
||||||
enable_globals: true
|
|
||||||
}
|
|
||||||
mut backend := cmdline.options(args, '-b')
|
|
||||||
backend << cmdline.options(args, '-backend')
|
|
||||||
if backend.len > 1 {
|
|
||||||
println('V error: Only one backend may be enabled at once. (Multiple `-b`/`-backend` flags provided)')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if backend.len == 1 {
|
|
||||||
|
|
||||||
// TODO remove tmp var after cgen optional bug is fixed
|
|
||||||
x := pref.backend_from_string(backend[0]) or {
|
|
||||||
println('V error: Unknown backend ${backend[0]} provided.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
p.backend = x
|
|
||||||
} else {
|
|
||||||
p.backend = .c
|
|
||||||
}
|
|
||||||
remaining2 := flag.parse_pref(args, parse_options, p) or {
|
|
||||||
println('V error: Error while parsing flags.')
|
|
||||||
println(err)
|
|
||||||
println('Args:')
|
|
||||||
println(args)
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
mut remaining := remaining2 // TODO cgen bug
|
|
||||||
match remaining[0] {
|
|
||||||
'run' {
|
|
||||||
p.is_run = true
|
|
||||||
remaining = remaining[1..]
|
|
||||||
}
|
|
||||||
'build' {
|
|
||||||
remaining = remaining[1..]
|
|
||||||
if remaining.len > 0 && remaining[0] == 'module' {
|
|
||||||
remaining = remaining[1..]
|
|
||||||
//TODO Figure out module
|
|
||||||
println('V error: Module compilation is not ready yet.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
}
|
|
||||||
if remaining.len == 0 {
|
|
||||||
println('V error: Expected file/directory to compile.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if !p.is_run && remaining.len > 1 {
|
|
||||||
println('V error: Expected only one file/directory to compile.')
|
|
||||||
println('Did you perhaps put flags after the file/directory?')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
p.path = remaining[0]
|
|
||||||
p.fill_with_defaults()
|
|
||||||
return p, remaining
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
println('V error: Expected argument for `-path`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
prefs.lookup_path = path_str.split('|')
|
|
||||||
}
|
|
||||||
'o', 'output' {
|
|
||||||
f.is_equivalent_to(['o', 'output'])
|
|
||||||
//TODO Remove `tmp` variable when it doesn't error out in C.
|
|
||||||
tmp := f.string() or {
|
|
||||||
println('V error: Expected argument for `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
prefs.out_name = tmp
|
|
||||||
}
|
|
||||||
'd', 'define' {
|
|
||||||
define := f.string() or {
|
|
||||||
println('V error: Expected argument for `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
parse_define(mut prefs, define)
|
|
||||||
}
|
|
||||||
'g', 'debug' {
|
|
||||||
f.is_equivalent_to(['g', 'debug', 'cg', 'cdebug'])
|
|
||||||
if f.bool() {
|
|
||||||
prefs.is_debug = true
|
|
||||||
prefs.is_vlines = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'e', 'experiments' {
|
|
||||||
to_enable := f.string() or {
|
|
||||||
println('V error: Expected argument for `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
match to_enable {
|
|
||||||
'prealloc' {
|
|
||||||
prefs.prealloc = true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
println('V error: Unknown experiment `$to_enable`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'prod' {
|
|
||||||
prefs.is_prod = true
|
|
||||||
}
|
|
||||||
'v' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
prefs.verbosity = .level_one
|
|
||||||
}
|
|
||||||
'vv' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
prefs.verbosity = .level_two
|
|
||||||
}
|
|
||||||
'vvv' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
prefs.verbosity = .level_three
|
|
||||||
}
|
|
||||||
'verbose' {
|
|
||||||
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
|
||||||
level := f.int() or {
|
|
||||||
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
match level {
|
|
||||||
0 {} //Zero verbosity is already default.
|
|
||||||
1 {
|
|
||||||
prefs.verbosity = .level_one
|
|
||||||
}
|
|
||||||
2 {
|
|
||||||
prefs.verbosity = .level_two
|
|
||||||
}
|
|
||||||
3 {
|
|
||||||
prefs.verbosity = .level_three
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'full-rebuild' {
|
|
||||||
prefs.is_cache = !f.bool()
|
|
||||||
}
|
|
||||||
'stats' {
|
|
||||||
prefs.is_stats = f.bool()
|
|
||||||
}
|
|
||||||
'obf', 'obfuscate' {
|
|
||||||
f.is_equivalent_to(['-obf', '-obfuscate'])
|
|
||||||
prefs.obfuscate = f.bool()
|
|
||||||
}
|
|
||||||
'prof', 'profile' {
|
|
||||||
f.is_equivalent_to(['-prof', '-profile'])
|
|
||||||
prefs.is_prof = f.bool()
|
|
||||||
}
|
|
||||||
'translated' {
|
|
||||||
prefs.translated = f.bool()
|
|
||||||
}
|
|
||||||
'b', 'backend' {
|
|
||||||
// Just consume it. The option is handled outside of this function
|
|
||||||
f.string() or { return }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
match prefs.backend {
|
|
||||||
.c, .experimental {
|
|
||||||
parse_c_options(flag, mut f, mut prefs)
|
|
||||||
}
|
|
||||||
.x64 {
|
|
||||||
parse_x64_options(flag, mut f, mut prefs)
|
|
||||||
}
|
|
||||||
.js {
|
|
||||||
parse_js_options(flag, f, prefs)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO: Remove when compiler allows for it.
|
|
||||||
// This enum matching IS exhaustive.
|
|
||||||
panic('unexpected backend type: $prefs.backend')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn parse_define(prefs mut pref.Preferences, define string) {
|
|
||||||
define_parts := define.split('=')
|
|
||||||
if define_parts.len == 1 {
|
|
||||||
prefs.compile_defines << define
|
|
||||||
prefs.compile_defines_all << define
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if define_parts.len == 2 {
|
|
||||||
prefs.compile_defines_all << define_parts[0]
|
|
||||||
match define_parts[1] {
|
|
||||||
'0' {}
|
|
||||||
'1' {
|
|
||||||
prefs.compile_defines << define_parts[0]
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
println('V error: Unknown define argument value `${define_parts[1]}` for ${define_parts[0]}.' +
|
|
||||||
'Expected `0` or `1`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
println('V error: Unknown define argument: ${define}. Expected at most one `=`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
|
@ -1,83 +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 compile
|
|
||||||
|
|
||||||
// This file contains the options specific to the x64 backend of V and backends that generate executable files.
|
|
||||||
// To add a flag to all backends at once, please add the flag to `parse_options()` in `compile_options.v`.
|
|
||||||
// To add a flag to the C backend-only, please add the flag to `parse_c_options()` in `compile_c_options.v`.
|
|
||||||
|
|
||||||
import (
|
|
||||||
internal.flag
|
|
||||||
v.pref
|
|
||||||
)
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn parse_x64_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
|
||||||
// No notable flags for x64-only currently. Add them here when they are needed.
|
|
||||||
if flag == 'arch' {
|
|
||||||
println('V error: The `-arch` flag is not supported on the x64 backend.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
parse_executable_options(flag, mut f, mut prefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn parse_executable_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
|
||||||
match flag {
|
|
||||||
'os', 'target-os' {
|
|
||||||
f.is_equivalent_to(['os', 'target-os'])
|
|
||||||
target_os := f.string() or {
|
|
||||||
println('V error: Expected argument after `-$flag`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if target_os == 'cross' {
|
|
||||||
prefs.output_cross_c = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//TODO Remove `tmp` variable when it doesn't error out in C.
|
|
||||||
tmp := pref.os_from_string(target_os) or {
|
|
||||||
println('V error: Unknown operating system target `$target_os`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
prefs.os = tmp
|
|
||||||
}
|
|
||||||
'arch' {
|
|
||||||
target_arch := f.string() or {
|
|
||||||
println('V error: Expected argument after `-arch`.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
match target_arch {
|
|
||||||
'x86' {
|
|
||||||
prefs.cflags += ' -m32'
|
|
||||||
}
|
|
||||||
'x64' {} // Default. Do nothing.
|
|
||||||
else {
|
|
||||||
println('V error: Unknown architecture type. Only x86 and x64 are supported currently.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'freestanding' {
|
|
||||||
prefs.is_bare = f.bool()
|
|
||||||
}
|
|
||||||
'shared' {
|
|
||||||
prefs.is_so = f.bool()
|
|
||||||
}
|
|
||||||
'live' {
|
|
||||||
prefs.is_solive = f.bool()
|
|
||||||
}
|
|
||||||
'manual-free' {
|
|
||||||
prefs.autofree = !f.bool()
|
|
||||||
}
|
|
||||||
'compress' {
|
|
||||||
prefs.compress = f.bool()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// No more fallback. We don't recognize this flag.
|
|
||||||
println('V error: Unknown flag `-$flag` provided.')
|
|
||||||
println('Use `--` to terminate flag list if necessary.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +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 compile
|
|
||||||
|
|
||||||
import (
|
|
||||||
os.cmdline
|
|
||||||
)
|
|
||||||
|
|
||||||
struct Deprecated {
|
|
||||||
old string
|
|
||||||
new string
|
|
||||||
not_exactly bool
|
|
||||||
}
|
|
||||||
|
|
||||||
//parse_and_output_new_format parses the old format and tells the user how to use the new options.
|
|
||||||
//This function exits if it detects the old format and returns if it doesn't.
|
|
||||||
fn parse_and_output_new_format(args []string) {
|
|
||||||
mut list := []Deprecated
|
|
||||||
mut obsolete := []string
|
|
||||||
//Check `-os msvc`
|
|
||||||
os := cmdline.option(args, '-os', '')
|
|
||||||
if os == 'msvc' {
|
|
||||||
list << Deprecated {
|
|
||||||
old: '-os msvc'
|
|
||||||
new: '-cc msvc'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Check simple options
|
|
||||||
//TODO Refactor them to actually just modify mutable arrays
|
|
||||||
list << add_if_found_deprecated(args, '-cache', '-full-rebuild=false')
|
|
||||||
list << add_if_found_deprecated(args, 'translated', '-translated')
|
|
||||||
list << add_if_found_deprecated(args, '-x64', '-backend x64')
|
|
||||||
list << add_if_found_deprecated(args, '-v2', '-backend experimental')
|
|
||||||
list << add_if_found_deprecated(args, '-keep_c', '-csource keep')
|
|
||||||
list << add_if_found_deprecated(args, '-pretty_c', '-csource prettify')
|
|
||||||
list << add_if_found_deprecated(args, '-show_c_cmd', '-v')
|
|
||||||
list << add_if_found_deprecated(args, '-autofree', '-manual-free=false')
|
|
||||||
list << add_if_found_deprecated(args, '-fast', '-cc tcc')
|
|
||||||
list << add_if_found_deprecated(args, '-output-cross-platform-c', '-os cross')
|
|
||||||
list << add_if_found_deprecated(args, '-m32', '-arch x86')
|
|
||||||
list << add_if_found_deprecated(args, '-bare', '-freestanding')
|
|
||||||
obsolete << add_if_found_string(args, '--enable-globals')
|
|
||||||
list << add_if_found_deprecated(args, '-prealloc', '-e prealloc')
|
|
||||||
list << add_if_found_deprecated(args, '-user_mod_path', '-path*')
|
|
||||||
list << add_if_found_deprecated(args, '-vlib-path', '-path*')
|
|
||||||
list << add_if_found_deprecated(args, '-vpath', '-path*')
|
|
||||||
//Nothing to do here
|
|
||||||
if list.len == 0 && obsolete.len == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//Output messages
|
|
||||||
println('V has encountered deprecated/obsolete options. Please edit your command.\n')
|
|
||||||
if list.len > 0 {
|
|
||||||
println('Deprecated options that have been replaced:')
|
|
||||||
for deprecation in list {
|
|
||||||
if deprecation.not_exactly {
|
|
||||||
println(' `$deprecation.old` has been superseded by `$deprecation.new` (see help for more details)')
|
|
||||||
} else {
|
|
||||||
println(' use `$deprecation.new` instead of `$deprecation.old`')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println('')
|
|
||||||
}
|
|
||||||
if obsolete.len > 0 {
|
|
||||||
println('Obsolete options that are no longer supported:')
|
|
||||||
for obsoleted in obsolete {
|
|
||||||
println(' `$obsoleted` has been removed')
|
|
||||||
}
|
|
||||||
println('')
|
|
||||||
}
|
|
||||||
println('For more details, please use the command `v help build` for a list of options.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
//=====
|
|
||||||
//HELPER FUNCTIONS
|
|
||||||
//=====
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn add_if_found_deprecated(args []string, deprecated string, alt string) []Deprecated {
|
|
||||||
if deprecated in args {
|
|
||||||
new := if alt.ends_with('*') {
|
|
||||||
Deprecated {
|
|
||||||
old: deprecated
|
|
||||||
new: alt[..alt.len-1]
|
|
||||||
not_exactly: true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Deprecated {
|
|
||||||
old: deprecated
|
|
||||||
new: alt
|
|
||||||
not_exactly: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [new]
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn add_if_found_string(args []string, deprecated string) []string {
|
|
||||||
if deprecated in args {
|
|
||||||
return [deprecated]
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
|
@ -1,117 +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.
|
|
||||||
|
|
||||||
// This module is designed to be general purpose. The only reason it currently only lives here is because there's no
|
|
||||||
// generics support and all types are defined manually.
|
|
||||||
// TODO Move to vlib once generics are implemented properly.
|
|
||||||
module flag
|
|
||||||
|
|
||||||
const (
|
|
||||||
// List as taken from `pkg.go.dev/flag`
|
|
||||||
truthy = ['1', 't', 'T', 'true', 'TRUE', 'True']
|
|
||||||
falsey = ['0', 'f', 'F', 'false', 'FALSE', 'False']
|
|
||||||
)
|
|
||||||
|
|
||||||
pub struct Instance {
|
|
||||||
args []string
|
|
||||||
mut:
|
|
||||||
current_flag string
|
|
||||||
current_pos int
|
|
||||||
equal_val string
|
|
||||||
encountered map[string]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (p mut Instance) parse_impl(args []string, value voidptr, callback void_cb) ?[]string {
|
|
||||||
for p.current_pos+1 < p.args.len {
|
|
||||||
p.current_pos++
|
|
||||||
next := p.args[p.current_pos]
|
|
||||||
if !next.starts_with('-') || next == '-' {
|
|
||||||
// End of arguments.
|
|
||||||
// Note: - by itself is not considered a flag.
|
|
||||||
return args[p.current_pos..]
|
|
||||||
}
|
|
||||||
if next == '--' {
|
|
||||||
// Terminator. End of arguments.
|
|
||||||
return args[p.current_pos+1..]
|
|
||||||
}
|
|
||||||
// Start parsing flag by determining flag name
|
|
||||||
mut flag_name := ''
|
|
||||||
if idx := next.index('=') {
|
|
||||||
p.equal_val = next[idx+1..]
|
|
||||||
flag_name = next[1..idx]
|
|
||||||
} else {
|
|
||||||
p.equal_val = ''
|
|
||||||
flag_name = next[1..]
|
|
||||||
}
|
|
||||||
p.encountered[flag_name] = true
|
|
||||||
p.current_flag = flag_name
|
|
||||||
callback(flag_name, p, value)
|
|
||||||
}
|
|
||||||
// We didn't hit any exit condition. There's no argument left so nothing.
|
|
||||||
return []string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) string() ?string {
|
|
||||||
if p.equal_val != '' {
|
|
||||||
return p.equal_val
|
|
||||||
}
|
|
||||||
p.current_pos++
|
|
||||||
if p.current_pos >= p.args.len {
|
|
||||||
return error('out of arguments')
|
|
||||||
}
|
|
||||||
return p.args[p.current_pos]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) int() ?int {
|
|
||||||
val := p.string() or {
|
|
||||||
return error(err)
|
|
||||||
}
|
|
||||||
if !val[0].is_digit() {
|
|
||||||
return error('an integer number was expected, but "$val" was found instead.')
|
|
||||||
}
|
|
||||||
return val.int()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) f32() ?f32 {
|
|
||||||
val := p.string() or {
|
|
||||||
return error(err)
|
|
||||||
}
|
|
||||||
return val.f32()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) f64() ?f64 {
|
|
||||||
val := p.string() or {
|
|
||||||
return error(err)
|
|
||||||
}
|
|
||||||
return val.f64()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) i64() ?i64 {
|
|
||||||
val := p.string() or {
|
|
||||||
return error(err)
|
|
||||||
}
|
|
||||||
return val.i64()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) bool() bool {
|
|
||||||
val := p.string() or {
|
|
||||||
// Could not fetch arguments? Parse it as `true`.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if val in truthy {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if val in falsey {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Unrecognized boolean type. Probably is not related to boolean.
|
|
||||||
p.current_pos--
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Instance) is_equivalent_to(flags []string) {
|
|
||||||
for v in flags {
|
|
||||||
p.encountered[v] = true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +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 flag
|
|
||||||
|
|
||||||
import (
|
|
||||||
v.pref
|
|
||||||
)
|
|
||||||
|
|
||||||
type void_cb fn(string, &Instance, voidptr)
|
|
||||||
|
|
||||||
// This file contains all instance of usage in cmd/v. Should be replaced by generics.
|
|
||||||
pub fn parse_pref(args []string, callback fn(string, &Instance, &pref.Preferences), obj &pref.Preferences) ?[]string {
|
|
||||||
mut p := Instance {
|
|
||||||
args: args
|
|
||||||
current_pos: 0
|
|
||||||
}
|
|
||||||
//tmp := p.parse_impl(args, voidptr(obj), void_cb(callback)) or {
|
|
||||||
tmp := p.parse_impl(args, obj, void_cb(callback)) or {
|
|
||||||
return error(err)
|
|
||||||
}
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum MainCmdAction {
|
|
||||||
unspecified
|
|
||||||
version
|
|
||||||
help
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MainCmdPreferences {
|
|
||||||
pub mut:
|
|
||||||
verbosity pref.VerboseLevel
|
|
||||||
action MainCmdAction
|
|
||||||
unknown_flag string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_main_cmd(args []string, callback fn(string, &Instance, &MainCmdPreferences), obj &MainCmdPreferences) ?[]string {
|
|
||||||
mut p := Instance {
|
|
||||||
args: args
|
|
||||||
current_pos: 0
|
|
||||||
}
|
|
||||||
tmp := p.parse_impl(args, obj, void_cb(callback)) or {
|
|
||||||
return error(err)
|
|
||||||
}
|
|
||||||
return tmp
|
|
||||||
}
|
|
50
cmd/v/v.v
50
cmd/v/v.v
|
@ -4,7 +4,7 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
internal.compile
|
//internal.compile
|
||||||
internal.help
|
internal.help
|
||||||
os
|
os
|
||||||
os.cmdline
|
os.cmdline
|
||||||
|
@ -12,6 +12,7 @@ import (
|
||||||
v.doc
|
v.doc
|
||||||
v.pref
|
v.pref
|
||||||
v.util
|
v.util
|
||||||
|
v.builder
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,6 +23,13 @@ const (
|
||||||
'repl',
|
'repl',
|
||||||
'build-tools', 'build-examples', 'build-vbinaries',
|
'build-tools', 'build-examples', 'build-vbinaries',
|
||||||
'setup-freetype']
|
'setup-freetype']
|
||||||
|
|
||||||
|
list_of_flags_that_allow_duplicates = ['cc','d','define','cf','cflags']
|
||||||
|
//list_of_flags contains a list of flags where an argument is expected past it.
|
||||||
|
list_of_flags_with_param = [
|
||||||
|
'o', 'output', 'd', 'define', 'b', 'backend', 'cc', 'os', 'target-os', 'arch',
|
||||||
|
'csource', 'cf', 'cflags', 'path'
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -38,12 +46,12 @@ fn main() {
|
||||||
println(util.full_v_version())
|
println(util.full_v_version())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
prefs2, command := parse_args(args)
|
prefs, command := parse_args(args)
|
||||||
//println('command = $command')
|
//println('main() command = $command')
|
||||||
if prefs2.is_verbose {
|
if prefs.is_verbose {
|
||||||
println(util.full_v_version())
|
println(util.full_v_version())
|
||||||
}
|
}
|
||||||
if prefs2.is_verbose {
|
if prefs.is_verbose {
|
||||||
//println('args= ')
|
//println('args= ')
|
||||||
//println(args) // QTODO
|
//println(args) // QTODO
|
||||||
//println('prefs= ')
|
//println('prefs= ')
|
||||||
|
@ -53,7 +61,7 @@ fn main() {
|
||||||
// Note for future contributors: Please add new subcommands in the `match` block below.
|
// Note for future contributors: Please add new subcommands in the `match` block below.
|
||||||
if command in simple_cmd {
|
if command in simple_cmd {
|
||||||
// External tools
|
// External tools
|
||||||
util.launch_tool(prefs2.is_verbose, 'v' + command)
|
util.launch_tool(prefs.is_verbose, 'v' + command)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
match command {
|
match command {
|
||||||
|
@ -61,7 +69,7 @@ fn main() {
|
||||||
invoke_help_and_exit(args)
|
invoke_help_and_exit(args)
|
||||||
}
|
}
|
||||||
'create', 'init' {
|
'create', 'init' {
|
||||||
util.launch_tool(prefs2.is_verbose, 'vcreate')
|
util.launch_tool(prefs.is_verbose, 'vcreate')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
'translate' {
|
'translate' {
|
||||||
|
@ -69,7 +77,7 @@ fn main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
'search', 'install', 'update', 'remove' {
|
'search', 'install', 'update', 'remove' {
|
||||||
util.launch_tool(prefs2.is_verbose, 'vpm')
|
util.launch_tool(prefs.is_verbose, 'vpm')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
'get' {
|
'get' {
|
||||||
|
@ -96,8 +104,7 @@ fn main() {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
if command in ['run', 'build'] || command.ends_with('.v') || os.exists(command) {
|
if command in ['run', 'build'] || command.ends_with('.v') || os.exists(command) {
|
||||||
arg := join_flags_and_argument()
|
builder.compile(command, prefs)
|
||||||
compile.compile(command, arg)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
eprintln('v $command: unknown command\nRun "v help" for usage.')
|
eprintln('v $command: unknown command\nRun "v help" for usage.')
|
||||||
|
@ -113,6 +120,25 @@ fn parse_args(args []string) (&pref.Preferences, string) {
|
||||||
match arg {
|
match arg {
|
||||||
'-v' { res.is_verbose = true }
|
'-v' { res.is_verbose = true }
|
||||||
'-cg' { res.is_debug = true }
|
'-cg' { res.is_debug = true }
|
||||||
|
'-live' { res.is_solive = true }
|
||||||
|
'-autofree' { res.autofree = true }
|
||||||
|
'-compress' { res.compress = true }
|
||||||
|
'-freestanding' { res.is_bare = true }
|
||||||
|
'-prod' { res.is_prod = true }
|
||||||
|
'-stats' { res.is_stats = true }
|
||||||
|
'-obfuscate' { res.obfuscate = true }
|
||||||
|
'-translated' { res.translated = true }
|
||||||
|
//'-x64' { res.translated = true }
|
||||||
|
'-os' {
|
||||||
|
//TODO Remove `tmp` variable when it doesn't error out in C.
|
||||||
|
target_os := cmdline.option(args, '-os', '')
|
||||||
|
tmp := pref.os_from_string(target_os) or {
|
||||||
|
println('unknown operating system target `$target_os`')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
res.os = tmp
|
||||||
|
i++
|
||||||
|
}
|
||||||
'-cc' {
|
'-cc' {
|
||||||
res.ccompiler = cmdline.option(args, '-cc', 'cc')
|
res.ccompiler = cmdline.option(args, '-cc', 'cc')
|
||||||
i++
|
i++
|
||||||
|
@ -139,6 +165,10 @@ fn parse_args(args []string) (&pref.Preferences, string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if command.ends_with('.v') || os.exists(command) {
|
||||||
|
res.path = command
|
||||||
|
}
|
||||||
|
res.fill_with_defaults()
|
||||||
return res, command
|
return res, command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,14 @@ mut:
|
||||||
module_search_paths []string
|
module_search_paths []string
|
||||||
parsed_files []ast.File
|
parsed_files []ast.File
|
||||||
global_scope &ast.Scope
|
global_scope &ast.Scope
|
||||||
|
out_name_c string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_builder(pref &pref.Preferences) Builder {
|
pub fn new_builder(pref &pref.Preferences) Builder {
|
||||||
|
rdir := os.real_path(pref.path)
|
||||||
|
compiled_dir := if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
|
||||||
table := table.new_table()
|
table := table.new_table()
|
||||||
return Builder{
|
return builder.Builder{
|
||||||
mod_file_cacher: new_mod_file_cacher()
|
mod_file_cacher: new_mod_file_cacher()
|
||||||
pref: pref
|
pref: pref
|
||||||
table: table
|
table: table
|
||||||
|
@ -38,6 +41,7 @@ pub fn new_builder(pref &pref.Preferences) Builder {
|
||||||
global_scope: &ast.Scope{
|
global_scope: &ast.Scope{
|
||||||
parent: 0
|
parent: 0
|
||||||
}
|
}
|
||||||
|
compiled_dir: compiled_dir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +71,7 @@ pub fn (b mut Builder) gen_c(v_files []string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b mut Builder) build_c(v_files []string, out_file string) {
|
pub fn (b mut Builder) build_c(v_files []string, out_file string) {
|
||||||
|
b.out_name_c = out_file
|
||||||
b.info('build_c($out_file)')
|
b.info('build_c($out_file)')
|
||||||
mut f := os.create(out_file) or {
|
mut f := os.create(out_file) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -77,6 +82,10 @@ pub fn (b mut Builder) build_c(v_files []string, out_file string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
|
pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
|
||||||
|
$if !linux {
|
||||||
|
println('v -x64 can only generate Linux binaries for now')
|
||||||
|
println('You are not on a Linux system, so you will not ' + 'be able to run the resulting executable')
|
||||||
|
}
|
||||||
t0 := time.ticks()
|
t0 := time.ticks()
|
||||||
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
||||||
b.parse_imports()
|
b.parse_imports()
|
||||||
|
@ -129,7 +138,7 @@ pub fn (b mut Builder) parse_imports() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b &Builder) v_files_from_dir(dir string) []string {
|
pub fn (b Builder) v_files_from_dir(dir string) []string {
|
||||||
mut res := []string
|
mut res := []string
|
||||||
if !os.exists(dir) {
|
if !os.exists(dir) {
|
||||||
if dir == 'compiler' && os.is_dir('vlib') {
|
if dir == 'compiler' && os.is_dir('vlib') {
|
||||||
|
@ -137,14 +146,13 @@ pub fn (b &Builder) v_files_from_dir(dir string) []string {
|
||||||
println('use `v -o v cmd/v` instead of `v -o v compiler`')
|
println('use `v -o v cmd/v` instead of `v -o v compiler`')
|
||||||
}
|
}
|
||||||
verror("$dir doesn't exist")
|
verror("$dir doesn't exist")
|
||||||
}
|
} else if !os.is_dir(dir) {
|
||||||
else if !os.is_dir(dir) {
|
|
||||||
verror("$dir isn't a directory!")
|
verror("$dir isn't a directory!")
|
||||||
}
|
}
|
||||||
mut files := os.ls(dir) or {
|
mut files := os.ls(dir) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if b.pref.verbosity.is_higher_or_equal(.level_one) {
|
if b.pref.is_verbose {
|
||||||
println('v_files_from_dir ("$dir")')
|
println('v_files_from_dir ("$dir")')
|
||||||
}
|
}
|
||||||
files.sort()
|
files.sort()
|
||||||
|
@ -155,7 +163,8 @@ pub fn (b &Builder) v_files_from_dir(dir string) []string {
|
||||||
if file.ends_with('_test.v') {
|
if file.ends_with('_test.v') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (file.ends_with('_win.v') || file.ends_with('_windows.v')) && b.os != .windows {
|
if (file.ends_with('_win.v') || file.ends_with('_windows.v')) && b.os !=
|
||||||
|
.windows {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (file.ends_with('_lin.v') || file.ends_with('_linux.v')) && b.os != .linux {
|
if (file.ends_with('_lin.v') || file.ends_with('_linux.v')) && b.os != .linux {
|
||||||
|
@ -200,14 +209,14 @@ pub fn (b &Builder) v_files_from_dir(dir string) []string {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b &Builder) log(s string) {
|
pub fn (b Builder) log(s string) {
|
||||||
if b.pref.verbosity.is_higher_or_equal(.level_two) {
|
if b.pref.is_verbose {
|
||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b &Builder) info(s string) {
|
pub fn (b Builder) info(s string) {
|
||||||
if b.pref.verbosity.is_higher_or_equal(.level_one) {
|
if b.pref.is_verbose {
|
||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,15 +227,15 @@ fn module_path(mod string) string {
|
||||||
return mod.replace('.', os.path_separator)
|
return mod.replace('.', os.path_separator)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b &Builder) find_module_path(mod string) ?string {
|
pub fn (b Builder) find_module_path(mod string) ?string {
|
||||||
mod_path := module_path(mod)
|
mod_path := module_path(mod)
|
||||||
for search_path in b.module_search_paths {
|
for search_path in b.module_search_paths {
|
||||||
try_path := os.join_path(search_path, mod_path)
|
try_path := os.join_path(search_path, mod_path)
|
||||||
if b.pref.verbosity.is_higher_or_equal(.level_three) {
|
if b.pref.is_verbose {
|
||||||
println(' >> trying to find $mod in $try_path ..')
|
println(' >> trying to find $mod in $try_path ..')
|
||||||
}
|
}
|
||||||
if os.is_dir(try_path) {
|
if os.is_dir(try_path) {
|
||||||
if b.pref.verbosity.is_higher_or_equal(.level_three) {
|
if b.pref.is_verbose {
|
||||||
println(' << found $try_path .')
|
println(' << found $try_path .')
|
||||||
}
|
}
|
||||||
return try_path
|
return try_path
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module compile
|
module builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
os
|
os
|
||||||
|
@ -14,10 +14,10 @@ import (
|
||||||
fn todo() {
|
fn todo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) no_cc_installed() bool {
|
fn (v &Builder) no_cc_installed() bool {
|
||||||
$if windows {
|
$if windows {
|
||||||
os.exec('$v.pref.ccompiler -v')or{
|
os.exec('$v.pref.ccompiler -v')or{
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
if v.pref.is_verbose {
|
||||||
println('C compiler not found, trying to build with msvc...')
|
println('C compiler not found, trying to build with msvc...')
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -26,10 +26,13 @@ fn (v &V) no_cc_installed() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v mut V) cc() {
|
fn (v mut Builder) cc() {
|
||||||
if os.executable().contains('vfmt') {
|
if os.executable().contains('vfmt') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
println('builder.cc() pref.out_name="$v.pref.out_name"')
|
||||||
|
}
|
||||||
v.build_thirdparty_obj_files()
|
v.build_thirdparty_obj_files()
|
||||||
vexe := pref.vexe_path()
|
vexe := pref.vexe_path()
|
||||||
vdir := os.dir(vexe)
|
vdir := os.dir(vexe)
|
||||||
|
@ -320,7 +323,7 @@ start:
|
||||||
// TODO remove
|
// TODO remove
|
||||||
cmd := '${v.pref.ccompiler} $args'
|
cmd := '${v.pref.ccompiler} $args'
|
||||||
// Run
|
// Run
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
if v.pref.is_verbose {
|
||||||
println('\n==========')
|
println('\n==========')
|
||||||
println(cmd)
|
println(cmd)
|
||||||
}
|
}
|
||||||
|
@ -394,7 +397,7 @@ If you're confident that all of the above is true, please try running V with the
|
||||||
}
|
}
|
||||||
diff := time.ticks() - ticks
|
diff := time.ticks() - ticks
|
||||||
// Print the C command
|
// Print the C command
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
if v.pref.is_verbose {
|
||||||
println('${v.pref.ccompiler} took $diff ms')
|
println('${v.pref.ccompiler} took $diff ms')
|
||||||
println('=========\n')
|
println('=========\n')
|
||||||
}
|
}
|
||||||
|
@ -455,7 +458,7 @@ If you're confident that all of the above is true, please try running V with the
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c mut V) cc_windows_cross() {
|
fn (c mut Builder) cc_windows_cross() {
|
||||||
/*
|
/*
|
||||||
QTODO
|
QTODO
|
||||||
println('Cross compiling for Windows...')
|
println('Cross compiling for Windows...')
|
||||||
|
@ -531,7 +534,7 @@ fn (c mut V) cc_windows_cross() {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c &V) build_thirdparty_obj_files() {
|
fn (c &Builder) build_thirdparty_obj_files() {
|
||||||
for flag in c.get_os_cflags() {
|
for flag in c.get_os_cflags() {
|
||||||
if flag.value.ends_with('.o') {
|
if flag.value.ends_with('.o') {
|
||||||
rest_of_module_flags := c.get_rest_of_module_cflags(flag)
|
rest_of_module_flags := c.get_rest_of_module_cflags(flag)
|
||||||
|
@ -545,7 +548,7 @@ fn (c &V) build_thirdparty_obj_files() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) build_thirdparty_obj_file(path string, moduleflags []CFlag) {
|
fn (v &Builder) build_thirdparty_obj_file(path string, moduleflags []CFlag) {
|
||||||
obj_path := os.real_path(path)
|
obj_path := os.real_path(path)
|
||||||
if os.exists(obj_path) {
|
if os.exists(obj_path) {
|
||||||
return
|
return
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module compile
|
module builder
|
||||||
|
|
||||||
import os
|
import os
|
||||||
// parsed cflag
|
// parsed cflag
|
||||||
|
@ -17,7 +17,7 @@ pub fn (c &CFlag) str() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get flags for current os
|
// get flags for current os
|
||||||
fn (v &V) get_os_cflags() []CFlag {
|
fn (v &Builder) get_os_cflags() []CFlag {
|
||||||
mut flags := []CFlag
|
mut flags := []CFlag
|
||||||
mut ctimedefines := []string
|
mut ctimedefines := []string
|
||||||
if v.pref.compile_defines.len > 0 {
|
if v.pref.compile_defines.len > 0 {
|
||||||
|
@ -38,7 +38,7 @@ fn (v &V) get_os_cflags() []CFlag {
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) get_rest_of_module_cflags(c &CFlag) []CFlag {
|
fn (v &Builder) get_rest_of_module_cflags(c &CFlag) []CFlag {
|
||||||
mut flags := []CFlag
|
mut flags := []CFlag
|
||||||
cflags := v.get_os_cflags()
|
cflags := v.get_os_cflags()
|
||||||
for flag in cflags {
|
for flag in cflags {
|
|
@ -0,0 +1,300 @@
|
||||||
|
// 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 builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
benchmark
|
||||||
|
os
|
||||||
|
v.pref
|
||||||
|
v.util
|
||||||
|
strings
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub struct V {
|
||||||
|
pub mut:
|
||||||
|
mod_file_cacher &builder.ModFileCacher // used during lookup for v.mod to support @VROOT
|
||||||
|
out_name_c string // name of the temporary C file
|
||||||
|
files []string // all V files that need to be parsed and compiled
|
||||||
|
compiled_dir string // contains os.real_path() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
|
||||||
|
pref &pref.Preferences // all the preferences and settings extracted to a struct for reusability
|
||||||
|
vgen_buf strings.Builder // temporary buffer for generated V code (.str() etc)
|
||||||
|
file_parser_idx map[string]int // map absolute file path to v.parsers index
|
||||||
|
gen_parser_idx map[string]int
|
||||||
|
cached_mods []string
|
||||||
|
module_lookup_paths []string
|
||||||
|
|
||||||
|
v_fmt_all bool // << input set by cmd/tools/vfmt.v
|
||||||
|
v_fmt_file string // << file given by the user from cmd/tools/vfmt.v
|
||||||
|
v_fmt_file_result string // >> file with formatted output generated by vlib/compiler/vfmt.v
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_v(pref &pref.Preferences) &V {
|
||||||
|
rdir := os.real_path(pref.path)
|
||||||
|
|
||||||
|
mut out_name_c := get_vtmp_filename(pref.out_name, '.tmp.c')
|
||||||
|
if pref.is_so {
|
||||||
|
out_name_c = get_vtmp_filename(pref.out_name, '.tmp.so.c')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut vgen_buf := strings.new_builder(1000)
|
||||||
|
vgen_buf.writeln('module vgen\nimport strings')
|
||||||
|
compiled_dir:=if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
|
||||||
|
|
||||||
|
return &V{
|
||||||
|
mod_file_cacher: builder.new_mod_file_cacher()
|
||||||
|
compiled_dir:compiled_dir// if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
|
||||||
|
out_name_c: out_name_c
|
||||||
|
pref: pref
|
||||||
|
vgen_buf: vgen_buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
// make v2 from v1
|
||||||
|
fn (v &V) new_v2() builder.Builder {
|
||||||
|
mut b := builder.new_builder(v.pref)
|
||||||
|
b = { b|
|
||||||
|
os: v.pref.os,
|
||||||
|
module_path: pref.default_module_path,
|
||||||
|
compiled_dir: v.compiled_dir,
|
||||||
|
module_search_paths: v.module_lookup_paths
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
fn get_vtmp_folder() string {
|
||||||
|
vtmp := os.join_path(os.temp_dir(), 'v')
|
||||||
|
if !os.is_dir(vtmp) {
|
||||||
|
os.mkdir(vtmp) or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vtmp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_vtmp_filename(base_file_name, postfix string) string {
|
||||||
|
vtmp := get_vtmp_folder()
|
||||||
|
return os.real_path(os.join_path(vtmp, os.file_name(os.real_path(base_file_name)) +
|
||||||
|
postfix))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile(command string, pref &pref.Preferences) {
|
||||||
|
mut remaining := []string
|
||||||
|
// Construct the V object from command line arguments
|
||||||
|
mut b := new_builder(pref)
|
||||||
|
if pref.is_verbose {
|
||||||
|
println('builder.compile() pref:')
|
||||||
|
println(pref)
|
||||||
|
}
|
||||||
|
mut tmark := benchmark.new_benchmark()
|
||||||
|
mut files := []string
|
||||||
|
if pref.backend == .x64 {
|
||||||
|
// v.files << v.v_files_from_dir(os.join_path(v.pref.vlib_path,'builtin','bare'))
|
||||||
|
files << pref.path
|
||||||
|
b.set_module_lookup_paths()
|
||||||
|
b.build_x64(files, pref.out_name)
|
||||||
|
} else {
|
||||||
|
if os.user_os() != 'windows' && pref.ccompiler == 'msvc' {
|
||||||
|
verror('Cannot build with msvc on ${os.user_os()}')
|
||||||
|
}
|
||||||
|
// cgen.genln('// Generated by V')
|
||||||
|
// println('compile2()')
|
||||||
|
if pref.is_verbose {
|
||||||
|
println('all .v files before:')
|
||||||
|
println(files)
|
||||||
|
}
|
||||||
|
// v1 compiler files
|
||||||
|
// v.add_v_files_to_compile()
|
||||||
|
// v.files << v.dir
|
||||||
|
// v2 compiler
|
||||||
|
//b.set_module_lookup_paths()
|
||||||
|
files << b.get_builtin_files()
|
||||||
|
files << b.get_user_files()
|
||||||
|
b.set_module_lookup_paths()
|
||||||
|
if pref.is_verbose {
|
||||||
|
println('all .v files:')
|
||||||
|
println(files)
|
||||||
|
}
|
||||||
|
//b.build_c(files, b.out_name_c) // v.pref.out_name + '.c')
|
||||||
|
b.build_c(files, pref.out_name + '.c')
|
||||||
|
b.cc()
|
||||||
|
}
|
||||||
|
if pref.is_stats {
|
||||||
|
tmark.stop()
|
||||||
|
println('compilation took: ' + tmark.total_duration().str() + 'ms')
|
||||||
|
}
|
||||||
|
if pref.is_test || pref.is_run {
|
||||||
|
b.run_compiled_executable_and_exit(remaining)
|
||||||
|
}
|
||||||
|
// v.finalize_compilation()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b mut Builder) run_compiled_executable_and_exit(remaining []string) {
|
||||||
|
if b.pref.is_verbose {
|
||||||
|
println('============ running $b.pref.out_name ============')
|
||||||
|
}
|
||||||
|
mut cmd := '"${b.pref.out_name}"'
|
||||||
|
for i in 1 .. remaining.len {
|
||||||
|
// Determine if there are spaces in the parameters
|
||||||
|
if remaining[i].index_byte(` `) > 0 {
|
||||||
|
cmd += ' "' + remaining[i] + '"'
|
||||||
|
} else {
|
||||||
|
cmd += ' ' + remaining[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b.pref.is_verbose {
|
||||||
|
println('command to run executable: $cmd')
|
||||||
|
}
|
||||||
|
if b.pref.is_test {
|
||||||
|
ret := os.system(cmd)
|
||||||
|
if ret != 0 {
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b.pref.is_run {
|
||||||
|
ret := os.system(cmd)
|
||||||
|
// TODO: make the runner wrapping as transparent as possible
|
||||||
|
// (i.e. use execve when implemented). For now though, the runner
|
||||||
|
// just returns the same exit code as the child process.
|
||||||
|
exit(ret)
|
||||||
|
}
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'strings' => 'VROOT/vlib/strings'
|
||||||
|
// 'installed_mod' => '~/.vmodules/installed_mod'
|
||||||
|
// 'local_mod' => '/path/to/current/dir/local_mod'
|
||||||
|
fn (v mut Builder) set_module_lookup_paths() {
|
||||||
|
// Module search order:
|
||||||
|
// 0) V test files are very commonly located right inside the folder of the
|
||||||
|
// module, which they test. Adding the parent folder of the module folder
|
||||||
|
// with the _test.v files, *guarantees* that the tested module can be found
|
||||||
|
// without needing to set custom options/flags.
|
||||||
|
// 1) search in the *same* directory, as the compiled final v program source
|
||||||
|
// (i.e. the . in `v .` or file.v in `v file.v`)
|
||||||
|
// 2) search in the modules/ in the same directory.
|
||||||
|
// 3) search in the provided paths
|
||||||
|
// By default, these are what (3) contains:
|
||||||
|
// 3.1) search in vlib/
|
||||||
|
// 3.2) search in ~/.vmodules/ (i.e. modules installed with vpm)
|
||||||
|
v.module_search_paths = []
|
||||||
|
if v.pref.is_test {
|
||||||
|
v.module_search_paths << os.base_dir(v.compiled_dir) // pdir of _test.v
|
||||||
|
}
|
||||||
|
v.module_search_paths << v.compiled_dir
|
||||||
|
x := os.join_path(v.compiled_dir, 'modules')
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
println('x: "$x"')
|
||||||
|
}
|
||||||
|
v.module_search_paths << os.join_path(v.compiled_dir, 'modules')
|
||||||
|
v.module_search_paths << v.pref.lookup_path
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
v.log('v.module_lookup_paths') // : $v.module_lookup_paths')
|
||||||
|
println(v.module_search_paths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (v &Builder) get_builtin_files() []string {
|
||||||
|
//println('get_builtin_files() lookuppath:')
|
||||||
|
//println(v.pref.lookup_path)
|
||||||
|
// Lookup for built-in folder in lookup path.
|
||||||
|
// Assumption: `builtin/` folder implies usable implementation of builtin
|
||||||
|
for location in v.pref.lookup_path {
|
||||||
|
if !os.exists(os.join_path(location, 'builtin')) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v.pref.is_bare {
|
||||||
|
return v.v_files_from_dir(os.join_path(location, 'builtin', 'bare'))
|
||||||
|
}
|
||||||
|
$if js {
|
||||||
|
return v.v_files_from_dir(os.join_path(location, 'builtin', 'js'))
|
||||||
|
}
|
||||||
|
return v.v_files_from_dir(os.join_path(location, 'builtin'))
|
||||||
|
}
|
||||||
|
// Panic. We couldn't find the folder.
|
||||||
|
verror('`builtin/` not included on module lookup path.
|
||||||
|
Did you forget to add vlib to the path? (Use @vlib for default vlib)')
|
||||||
|
panic('Unreachable code reached.')
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (v &Builder) get_user_files() []string {
|
||||||
|
mut dir := v.pref.path
|
||||||
|
v.log('get_v_files($dir)')
|
||||||
|
// Need to store user files separately, because they have to be added after
|
||||||
|
// libs, but we dont know which libs need to be added yet
|
||||||
|
mut user_files := []string
|
||||||
|
// See cmd/tools/preludes/README.md for more info about what preludes are
|
||||||
|
vroot := os.dir(pref.vexe_path())
|
||||||
|
preludes_path := os.join_path(vroot, 'cmd', 'tools', 'preludes')
|
||||||
|
if v.pref.is_live {
|
||||||
|
user_files << os.join_path(preludes_path, 'live_main.v')
|
||||||
|
}
|
||||||
|
if v.pref.is_solive {
|
||||||
|
user_files << os.join_path(preludes_path, 'live_shared.v')
|
||||||
|
}
|
||||||
|
if v.pref.is_test {
|
||||||
|
user_files << os.join_path(preludes_path, 'tests_assertions.v')
|
||||||
|
}
|
||||||
|
if v.pref.is_test && v.pref.is_stats {
|
||||||
|
user_files << os.join_path(preludes_path, 'tests_with_stats.v')
|
||||||
|
}
|
||||||
|
is_test := dir.ends_with('_test.v')
|
||||||
|
mut is_internal_module_test := false
|
||||||
|
if is_test {
|
||||||
|
tcontent := os.read_file(dir) or {
|
||||||
|
panic('$dir does not exist')
|
||||||
|
}
|
||||||
|
slines := tcontent.trim_space().split_into_lines()
|
||||||
|
for sline in slines {
|
||||||
|
line := sline.trim_space()
|
||||||
|
if line.len > 2 {
|
||||||
|
if line[0] == `/` && line[1] == `/` {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if line.starts_with('module ') && !line.starts_with('module main') {
|
||||||
|
is_internal_module_test = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_internal_module_test {
|
||||||
|
// v volt/slack_test.v: compile all .v files to get the environment
|
||||||
|
single_test_v_file := os.real_path(dir)
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
v.log('> Compiling an internal module _test.v file $single_test_v_file .')
|
||||||
|
v.log('> That brings in all other ordinary .v files in the same module too .')
|
||||||
|
}
|
||||||
|
user_files << single_test_v_file
|
||||||
|
dir = os.base_dir(single_test_v_file)
|
||||||
|
}
|
||||||
|
is_real_file := os.exists(dir) && !os.is_dir(dir)
|
||||||
|
if is_real_file && (dir.ends_with('.v') || dir.ends_with('.vsh')) {
|
||||||
|
single_v_file := dir
|
||||||
|
// Just compile one file and get parent dir
|
||||||
|
user_files << single_v_file
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
v.log('> just compile one file: "${single_v_file}"')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
v.log('> add all .v files from directory "${dir}" ...')
|
||||||
|
}
|
||||||
|
// Add .v files from the directory being compiled
|
||||||
|
files := v.v_files_from_dir(dir)
|
||||||
|
for file in files {
|
||||||
|
user_files << file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if user_files.len == 0 {
|
||||||
|
println('No input .v files')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
if v.pref.is_verbose {
|
||||||
|
v.log('user_files: $user_files')
|
||||||
|
}
|
||||||
|
return user_files
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
module compile
|
module builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
os
|
os
|
||||||
time
|
time
|
||||||
)
|
)
|
||||||
|
|
||||||
fn (v &V) generate_hotcode_reloading_compiler_flags() []string {
|
fn (v &Builder) generate_hotcode_reloading_compiler_flags() []string {
|
||||||
mut a := []string
|
mut a := []string
|
||||||
if v.pref.is_live || v.pref.is_so {
|
if v.pref.is_live || v.pref.is_so {
|
||||||
// See 'man dlopen', and test running a GUI program compiled with -live
|
// See 'man dlopen', and test running a GUI program compiled with -live
|
||||||
|
@ -19,7 +19,7 @@ fn (v &V) generate_hotcode_reloading_compiler_flags() []string {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) generate_hotcode_reloading_declarations() {
|
fn (v &Builder) generate_hotcode_reloading_declarations() {
|
||||||
/*
|
/*
|
||||||
QTODO
|
QTODO
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
|
@ -50,7 +50,7 @@ void pthread_mutex_unlock(HANDLE *m) {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) generate_hotcode_reloading_main_caller() {
|
fn (v &Builder) generate_hotcode_reloading_main_caller() {
|
||||||
// QTODO
|
// QTODO
|
||||||
/*
|
/*
|
||||||
if !v.pref.is_live {
|
if !v.pref.is_live {
|
||||||
|
@ -80,7 +80,7 @@ fn (v &V) generate_hotcode_reloading_main_caller() {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) generate_hot_reload_code() {
|
fn (v &Builder) generate_hot_reload_code() {
|
||||||
/*
|
/*
|
||||||
QTODO
|
QTODO
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
|
@ -1,4 +1,4 @@
|
||||||
module compile
|
module builder
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import v.pref
|
import v.pref
|
||||||
|
@ -182,7 +182,7 @@ fn find_msvc() ?MsvcResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (v mut V) cc_msvc() {
|
pub fn (v mut Builder) cc_msvc() {
|
||||||
r := find_msvc()or{
|
r := find_msvc()or{
|
||||||
// TODO: code reuse
|
// TODO: code reuse
|
||||||
if !v.pref.is_keep_c && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' {
|
if !v.pref.is_keep_c && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' {
|
||||||
|
@ -281,7 +281,7 @@ pub fn (v mut V) cc_msvc() {
|
||||||
cmd := '"$r.full_cl_exe_path" $args'
|
cmd := '"$r.full_cl_exe_path" $args'
|
||||||
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
||||||
// Also the double quotes at the start ARE needed.
|
// Also the double quotes at the start ARE needed.
|
||||||
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
if v.pref.is_verbose {
|
||||||
println('\n========== cl cmd line:')
|
println('\n========== cl cmd line:')
|
||||||
println(cmd)
|
println(cmd)
|
||||||
println('==========\n')
|
println('==========\n')
|
|
@ -1207,11 +1207,11 @@ fn (c mut Checker) warn_or_error(s string, pos token.Position, warn bool) {
|
||||||
c.nr_errors++
|
c.nr_errors++
|
||||||
}
|
}
|
||||||
//if c.pref.is_verbose {
|
//if c.pref.is_verbose {
|
||||||
if c.pref.verbosity.is_higher_or_equal(.level_one) {
|
if c.pref.is_verbose {
|
||||||
print_backtrace()
|
print_backtrace()
|
||||||
}
|
}
|
||||||
typ := if warn { 'warning' } else { 'error' }
|
typ := if warn { 'warning' } else { 'error' }
|
||||||
kind := if c.pref.verbosity.is_higher_or_equal(.level_one) {
|
kind := if c.pref.is_verbose {
|
||||||
'checker $typ #$c.nr_errors:'
|
'checker $typ #$c.nr_errors:'
|
||||||
} else {
|
} else {
|
||||||
'$typ:'
|
'$typ:'
|
||||||
|
@ -1228,7 +1228,7 @@ fn (c mut Checker) warn_or_error(s string, pos token.Position, warn bool) {
|
||||||
if !warn {
|
if !warn {
|
||||||
c.error_lines << pos.line_nr
|
c.error_lines << pos.line_nr
|
||||||
}
|
}
|
||||||
if c.pref.verbosity.is_higher_or_equal(.level_one) {
|
if c.pref.is_verbose {
|
||||||
println('\n\n')
|
println('\n\n')
|
||||||
}
|
}
|
||||||
if c.nr_errors >= max_nr_errors {
|
if c.nr_errors >= max_nr_errors {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
const (
|
const (
|
||||||
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t',
|
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t',
|
||||||
'\t\t\t\t\t\t\t']
|
'\t\t\t\t\t\t\t']
|
||||||
max_len = 80
|
max_len = 100
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Fmt {
|
struct Fmt {
|
||||||
|
|
|
@ -508,7 +508,7 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
|
||||||
|
|
||||||
pub fn (p &Parser) error(s string) {
|
pub fn (p &Parser) error(s string) {
|
||||||
mut kind := 'error:'
|
mut kind := 'error:'
|
||||||
if p.pref.verbosity.is_higher_or_equal(.level_one) {
|
if p.pref.is_verbose {
|
||||||
print_backtrace()
|
print_backtrace()
|
||||||
kind = 'parser error:'
|
kind = 'parser error:'
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,12 @@ pub enum Backend {
|
||||||
x64 // The x64 backend
|
x64 // The x64 backend
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum VerboseLevel {
|
|
||||||
clean // `-verbose 0` or unspecified
|
|
||||||
level_one // `-v` or `-verbose 1`
|
|
||||||
level_two // `-vv` or `-verbose 2`
|
|
||||||
level_three // `-vvv` or `-verbose 3`
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Preferences {
|
pub struct Preferences {
|
||||||
pub mut:
|
pub mut:
|
||||||
os OS // the OS to compile for
|
os OS // the OS to compile for
|
||||||
backend Backend
|
backend Backend
|
||||||
build_mode BuildMode
|
build_mode BuildMode
|
||||||
verbosity VerboseLevel
|
//verbosity VerboseLevel
|
||||||
is_verbose bool
|
is_verbose bool
|
||||||
// nofmt bool // disable vfmt
|
// nofmt bool // disable vfmt
|
||||||
is_test bool // `v test string_test.v`
|
is_test bool // `v test string_test.v`
|
||||||
|
@ -108,7 +101,3 @@ pub fn backend_from_string(s string) ?Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
|
||||||
pub fn (v VerboseLevel) is_higher_or_equal(other VerboseLevel) bool {
|
|
||||||
return int(v) >= int(other)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue