1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

tools: new tool to extracts function names declared in V files

This commit is contained in:
Delyan Angelov 2019-10-21 14:14:28 +03:00 committed by Alexander Medvednikov
parent cd8b0d04bb
commit eef73eea22
12 changed files with 184 additions and 40 deletions

76
tools/vnames.v Normal file
View File

@ -0,0 +1,76 @@
module main
import os
import flag
import compiler
const (
tool_version = '0.0.1'
tool_description = ' Extracts the function names declared in a v file.'
)
fn f_to_string(fmod string, f compiler.Fn) ?string {
svisibility := if f.is_public {
'public'
}else{
'private'
}
if fmod != f.v_fn_module() { return none }
if fmod == 'builtin' {
return '$svisibility\t' + f.v_fn_name()
}
return '$svisibility\t' + f.v_fn_module() + '.' + f.v_fn_name()
}
fn analyze_v_file(file string) {
println('')
println('###################### $file ######################')
// main work:
mut v := compiler.new_v_compiler_with_args([file])
v.add_v_files_to_compile()
for f in v.files { v.parse(f, .decl) }
fi := v.get_file_parser_index( file ) or { panic(err) }
fmod := v.parsers[fi].mod
// output:
mut fns :=[]string
for _, f in v.table.fns {
fname := f_to_string(fmod, f) or { continue }
fns << fname
}
fns.sort()
for f in fns { println(f) }
}
fn main(){
toolexe := os.executable()
compiler.set_vroot_folder( os.dir(os.dir(toolexe)) )
mut fp := flag.new_flag_parser(os.args)
fp.application(os.filename(toolexe))
fp.version( tool_version )
fp.description( tool_description )
fp.arguments_description('FILE.v/FOLDER [FILE.v/FOLDER]...')
fp.limit_free_args_to_at_least(1)
fp.skip_executable()
show_help:=fp.bool_('help', `h`, false, 'Show this help screen\n')
if( show_help ){
println( fp.usage() )
exit(0)
}
mut files := []string
locations := fp.finalize() or { eprintln('Error: ' + err) exit(1) }
for xloc in locations {
loc := os.realpath(xloc)
xfiles := if os.is_dir(loc){ os.walk_ext(loc,'.v') } else { [loc] }
filtered_files := xfiles.filter(!it.ends_with('_js.v'))
files << filtered_files
}
for file in files {
analyze_v_file(file)
}
}

View File

@ -141,7 +141,7 @@ pub fn (s array) left(n int) array {
pub fn (s array) right(n int) array { pub fn (s array) right(n int) array {
if n >= s.len { if n >= s.len {
return s return new_array(0, 0, s.element_size)
} }
return s.slice(n, s.len) return s.slice(n, s.len)
} }

View File

@ -121,6 +121,20 @@ fn test_right() {
assert b[1] == 3 assert b[1] == 3
} }
fn test_right_with_n_bigger_than_array_size() {
a := [1, 2, 3, 4]
mut b := a.right(10)
assert b.len == 0
// also check that the result of a.right
// is an array of the same type/element size as a:
b << 5
b << 6
assert b.len == 2
assert b[0] == 5
assert b[1] == 6
}
fn test_left() { fn test_left() {
a := [1, 2, 3] a := [1, 2, 3]
b := a.left(2) b := a.left(2)

View File

@ -11,7 +11,7 @@ import (
fn (v mut V) cc() { fn (v mut V) cc() {
v.build_thirdparty_obj_files() v.build_thirdparty_obj_files()
vexe := os.executable() vexe := vexe_path()
// Just create a C/JavaScript file and exit // Just create a C/JavaScript file and exit
// for example: `v -o v.c compiler` // for example: `v -o v.c compiler`
if v.out_name.ends_with('.c') || v.out_name.ends_with('.js') { if v.out_name.ends_with('.c') || v.out_name.ends_with('.js') {

View File

@ -12,8 +12,10 @@ const (
MaxLocalVars = 50 MaxLocalVars = 50
) )
struct Fn { struct Fn {
// addr int // addr int
pub:
mut: mut:
name string name string
mod string mod string
@ -49,6 +51,11 @@ mut:
done bool done bool
} }
const (
EmptyFn = Fn{}
MainFn = Fn{ name: 'main' }
)
fn (a []TypeInst) str() string { fn (a []TypeInst) str() string {
mut r := []string mut r := []string
for t in a { for t in a {

View File

@ -211,11 +211,15 @@ pub fn (v mut V) compile() {
cgen.genln('#define _VJS (1) ') cgen.genln('#define _VJS (1) ')
} }
if v.pref.building_v { v_hash := vhash()
$if js {
cgen.genln('const V_COMMIT_HASH = "$v_hash";\n')
} $else {
cgen.genln('#ifndef V_COMMIT_HASH') cgen.genln('#ifndef V_COMMIT_HASH')
cgen.genln('#define V_COMMIT_HASH "' + vhash() + '"') cgen.genln('#define V_COMMIT_HASH "$v_hash"')
cgen.genln('#endif') cgen.genln('#endif')
} }
q := cgen.nogen // TODO hack q := cgen.nogen // TODO hack
cgen.nogen = false cgen.nogen = false
$if js { $if js {
@ -471,13 +475,24 @@ pub fn final_target_out_name(out_name string) string {
} }
pub fn (v V) run_compiled_executable_and_exit() { pub fn (v V) run_compiled_executable_and_exit() {
args := env_vflags_and_os_args()
if v.pref.is_verbose { if v.pref.is_verbose {
println('============ running $v.out_name ============') println('============ running $v.out_name ============')
} }
mut cmd := '"' + final_target_out_name(v.out_name).replace('.exe','') + '"' mut cmd := '"' + final_target_out_name(v.out_name).replace('.exe','') + '"'
if os.args.len > 3 {
cmd += ' ' + os.args.right(3).join(' ') mut args_after := ' '
for i,a in args {
if i == 0 { continue }
if a.starts_with('-') { continue }
if a in ['run','test'] {
args_after += args.right(i+2).join(' ')
break
} }
}
cmd += args_after
if v.pref.is_test { if v.pref.is_test {
ret := os.system(cmd) ret := os.system(cmd)
if ret != 0 { if ret != 0 {
@ -855,7 +870,7 @@ pub fn new_v(args[]string) &V {
_os = os_from_string(target_os) _os = os_from_string(target_os)
} }
// Location of all vlib files // Location of all vlib files
vroot := os.dir(os.executable()) vroot := os.dir(vexe_path())
//println('VROOT=$vroot') //println('VROOT=$vroot')
// v.exe's parent directory should contain vlib // v.exe's parent directory should contain vlib
if !os.dir_exists(vroot) || !os.dir_exists(vroot + '/vlib/builtin') { if !os.dir_exists(vroot) || !os.dir_exists(vroot + '/vlib/builtin') {
@ -933,6 +948,9 @@ pub fn new_v(args[]string) &V {
} }
pub fn env_vflags_and_os_args() []string { pub fn env_vflags_and_os_args() []string {
vosargs := os.getenv('VOSARGS')
if '' != vosargs { return vosargs.split(' ') }
mut args := []string mut args := []string
vflags := os.getenv('VFLAGS') vflags := os.getenv('VFLAGS')
if '' != vflags { if '' != vflags {
@ -949,7 +967,7 @@ pub fn env_vflags_and_os_args() []string {
pub fn update_v() { pub fn update_v() {
println('Updating V...') println('Updating V...')
vroot := os.dir(os.executable()) vroot := os.dir(vexe_path())
s := os.exec('git -C "$vroot" pull --rebase origin master') or { s := os.exec('git -C "$vroot" pull --rebase origin master') or {
verror(err) verror(err)
return return
@ -994,7 +1012,7 @@ pub fn install_v(args[]string) {
return return
} }
names := args.slice(2, args.len) names := args.slice(2, args.len)
vexec := os.executable() vexec := vexe_path()
vroot := os.dir(vexec) vroot := os.dir(vexec)
vget := '$vroot/tools/vget' vget := '$vroot/tools/vget'
if true { if true {
@ -1020,7 +1038,7 @@ pub fn install_v(args[]string) {
} }
pub fn create_symlink() { pub fn create_symlink() {
vexe := os.executable() vexe := vexe_path()
link_path := '/usr/local/bin/v' link_path := '/usr/local/bin/v'
ret := os.system('ln -sf $vexe $link_path') ret := os.system('ln -sf $vexe $link_path')
if ret == 0 { if ret == 0 {
@ -1031,6 +1049,12 @@ pub fn create_symlink() {
} }
} }
pub fn vexe_path() string {
vexe := os.getenv('VEXE')
if '' != vexe { return vexe }
return os.executable()
}
pub fn verror(s string) { pub fn verror(s string) {
println('V error: $s') println('V error: $s')
os.flush_stdout() os.flush_stdout()
@ -1067,3 +1091,21 @@ pub fn os_from_string(os string) OS {
println('bad os $os') // todo panic? println('bad os $os') // todo panic?
return .linux return .linux
} }
//
pub 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:
mut vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
os.setenv('VEXE', os.realpath( [vroot_path, vname].join(os.path_separator) ), true)
}
pub fn new_v_compiler_with_args(args []string) &V {
vexe := vexe_path()
mut allargs := [vexe]
allargs << args
os.setenv('VOSARGS', allargs.join(' '), true)
return new_v(allargs)
}

View File

@ -40,7 +40,6 @@ mut:
import_table FileImportTable // Holds imports for just the file being parsed import_table FileImportTable // Holds imports for just the file being parsed
pass Pass pass Pass
os OS os OS
mod string
inside_const bool inside_const bool
expr_var Var expr_var Var
has_immutable_field bool has_immutable_field bool
@ -80,13 +79,10 @@ mut:
sql_params []string // ("select * from users where id = $1", ***"100"***) sql_params []string // ("select * from users where id = $1", ***"100"***)
sql_types []string // int, string and so on; see sql_params sql_types []string // int, string and so on; see sql_params
is_vh bool // parsing .vh file (for example `const (a int)` is allowed) is_vh bool // parsing .vh file (for example `const (a int)` is allowed)
pub:
mod string
} }
const (
EmptyFn = Fn{}
MainFn= Fn{name:'main'}
)
const ( const (
MaxModuleDepth = 4 MaxModuleDepth = 4
) )
@ -1421,7 +1417,7 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) {
if p.assigned_type != p.expected_type { if p.assigned_type != p.expected_type {
p.error_with_token_index( 'incompatible types: $p.assigned_type != $p.expected_type', errtok) p.error_with_token_index( 'incompatible types: $p.assigned_type != $p.expected_type', errtok)
} }
p.cgen.resetln('memcpy(& $left, $etype{$expr}, sizeof( $left ) );') p.cgen.resetln('memcpy( (& $left), ($etype{$expr}), sizeof( $left ) );')
} }
else if !p.builtin_mod && !p.check_types_no_throw(expr_type, p.assigned_type) { else if !p.builtin_mod && !p.check_types_no_throw(expr_type, p.assigned_type) {
p.error_with_token_index( 'cannot use type `$expr_type` as type `$p.assigned_type` in assignment', errtok) p.error_with_token_index( 'cannot use type `$expr_type` as type `$p.assigned_type` in assignment', errtok)

View File

@ -8,7 +8,7 @@ import os
import strings import strings
struct Table { struct Table {
mut: pub mut:
typesmap map[string]Type typesmap map[string]Type
consts []Var consts []Var
fns map[string]Fn fns map[string]Fn
@ -74,6 +74,7 @@ enum TypeCategory {
} }
struct Var { struct Var {
pub:
mut: mut:
typ string typ string
name string name string
@ -102,6 +103,7 @@ mut:
} }
struct Type { struct Type {
pub:
mut: mut:
mod string mod string
name string name string
@ -198,7 +200,14 @@ fn (f Fn) str() string {
return '$f.name($str_args) $f.typ' return '$f.name($str_args) $f.typ'
} }
fn (t &Table) debug_fns() string { pub fn (f Fn) v_fn_module() string {
return f.mod
}
pub fn (f Fn) v_fn_name() string {
return f.name.replace('${f.mod}__', '')
}
pub fn (t &Table) debug_fns() string {
mut s := strings.new_builder(1000) mut s := strings.new_builder(1000)
for _, f in t.fns { for _, f in t.fns {
s.writeln(f.name) s.writeln(f.name)

View File

@ -1,6 +1,6 @@
module main module main
import vcompiler.tests.repl.runner import compiler.tests.repl.runner
import log import log
import benchmark import benchmark

View File

@ -17,7 +17,7 @@ mut:
pub fn new_test_sesion(vargs string) TestSession { pub fn new_test_sesion(vargs string) TestSession {
return TestSession{ return TestSession{
vexe: os.executable() vexe: vexe_path()
vargs: vargs vargs: vargs
} }
} }
@ -118,7 +118,7 @@ pub fn (ts mut TestSession) test() {
} }
pub fn v_test_v(args_before_test string){ pub fn v_test_v(args_before_test string){
vexe := os.executable() vexe := vexe_path()
parent_dir := os.dir(vexe) parent_dir := os.dir(vexe)
// Changing the current directory is needed for some of the compiler tests, // Changing the current directory is needed for some of the compiler tests,
// compiler/tests/local_test.v and compiler/tests/repl/repl_test.v // compiler/tests/local_test.v and compiler/tests/repl/repl_test.v
@ -163,7 +163,7 @@ pub fn v_test_v(args_before_test string){
pub fn test_vget() { pub fn test_vget() {
/* /*
vexe := os.executable() vexe := vexe_path()
ret := os.system('$vexe install nedpals.args') ret := os.system('$vexe install nedpals.args')
if ret != 0 { if ret != 0 {
println('failed to run v install') println('failed to run v install')

View File

@ -4,7 +4,7 @@
module hash module hash
interface Hash { interface Hasher {
// Sum appends the current hash to b and returns the resulting array. // Sum appends the current hash to b and returns the resulting array.
// It does not change the underlying hash state. // It does not change the underlying hash state.
sum(b []byte) []byte sum(b []byte) []byte
@ -12,10 +12,10 @@ interface Hash {
block_size() int block_size() int
} }
interface Hash32 { interface Hash32er {
sum32() u32 sum32() u32
} }
interface Hash64 { interface Hash64er {
sum64() u64 sum64() u64
} }

View File

@ -30,7 +30,7 @@ struct Asset {
} }
// new_manager returns a new AssetManager // new_manager returns a new AssetManager
pub fn new_manager() *AssetManager { pub fn new_manager() &AssetManager {
return &AssetManager{} return &AssetManager{}
} }