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

pull/2468/head
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 100644
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 {
if n >= s.len {
return s
return new_array(0, 0, s.element_size)
}
return s.slice(n, s.len)
}

View File

@ -121,6 +121,20 @@ fn test_right() {
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() {
a := [1, 2, 3]
b := a.left(2)

View File

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

View File

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

View File

@ -211,11 +211,15 @@ pub fn (v mut V) compile() {
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('#define V_COMMIT_HASH "' + vhash() + '"')
cgen.genln('#define V_COMMIT_HASH "$v_hash"')
cgen.genln('#endif')
}
q := cgen.nogen // TODO hack
cgen.nogen = false
$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() {
args := env_vflags_and_os_args()
if v.pref.is_verbose {
println('============ running $v.out_name ============')
}
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 {
ret := os.system(cmd)
if ret != 0 {
@ -855,7 +870,7 @@ pub fn new_v(args[]string) &V {
_os = os_from_string(target_os)
}
// Location of all vlib files
vroot := os.dir(os.executable())
vroot := os.dir(vexe_path())
//println('VROOT=$vroot')
// v.exe's parent directory should contain vlib
if !os.dir_exists(vroot) || !os.dir_exists(vroot + '/vlib/builtin') {
@ -933,23 +948,26 @@ pub fn new_v(args[]string) &V {
}
pub fn env_vflags_and_os_args() []string {
mut args := []string
vflags := os.getenv('VFLAGS')
if '' != vflags {
args << os.args[0]
args << vflags.split(' ')
if os.args.len > 1 {
args << os.args.right(1)
}
} else{
args << os.args
}
return args
vosargs := os.getenv('VOSARGS')
if '' != vosargs { return vosargs.split(' ') }
mut args := []string
vflags := os.getenv('VFLAGS')
if '' != vflags {
args << os.args[0]
args << vflags.split(' ')
if os.args.len > 1 {
args << os.args.right(1)
}
} else{
args << os.args
}
return args
}
pub fn update_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 {
verror(err)
return
@ -994,7 +1012,7 @@ pub fn install_v(args[]string) {
return
}
names := args.slice(2, args.len)
vexec := os.executable()
vexec := vexe_path()
vroot := os.dir(vexec)
vget := '$vroot/tools/vget'
if true {
@ -1020,7 +1038,7 @@ pub fn install_v(args[]string) {
}
pub fn create_symlink() {
vexe := os.executable()
vexe := vexe_path()
link_path := '/usr/local/bin/v'
ret := os.system('ln -sf $vexe $link_path')
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) {
println('V error: $s')
os.flush_stdout()
@ -1067,3 +1091,21 @@ pub fn os_from_string(os string) OS {
println('bad os $os') // todo panic?
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
pass Pass
os OS
mod string
inside_const bool
expr_var Var
has_immutable_field bool
@ -80,13 +79,10 @@ mut:
sql_params []string // ("select * from users where id = $1", ***"100"***)
sql_types []string // int, string and so on; see sql_params
is_vh bool // parsing .vh file (for example `const (a int)` is allowed)
pub:
mod string
}
const (
EmptyFn = Fn{}
MainFn= Fn{name:'main'}
)
const (
MaxModuleDepth = 4
)
@ -1421,7 +1417,7 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) {
if p.assigned_type != p.expected_type {
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) {
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
struct Table {
mut:
pub mut:
typesmap map[string]Type
consts []Var
fns map[string]Fn
@ -39,7 +39,7 @@ enum NameCategory {
struct Name {
cat NameCategory
idx int // e.g. typ := types[name.idx]
}
}
// Holds import information scoped to the parsed file
struct FileImportTable {
@ -74,6 +74,7 @@ enum TypeCategory {
}
struct Var {
pub:
mut:
typ string
name string
@ -102,6 +103,7 @@ mut:
}
struct Type {
pub:
mut:
mod string
name string
@ -198,7 +200,14 @@ fn (f Fn) str() string {
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)
for _, f in t.fns {
s.writeln(f.name)

View File

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

View File

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

View File

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

View File

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