vdoc using the new parser

pull/3785/head
Alexander Medvednikov 2020-02-19 16:12:39 +01:00
parent 391da0ba07
commit 092c09d81f
11 changed files with 219 additions and 60 deletions

View File

@ -7,6 +7,8 @@ import (
compiler
internal.help
os
v.table
v.doc
)
const (
@ -43,6 +45,12 @@ fn main() {
eprintln('v command: $command')
eprintln('v options: $option')
}
if command == 'doc' {
mod := arg[arg.len-1]
table := table.new_table()
println(doc.doc(mod, table))
return
}
if command in simple_cmd {
// External tools
launch_tool(is_verbose, 'v' + command, command)
@ -60,20 +68,20 @@ fn main() {
launch_tool(is_verbose, 'vrepl', '')
}
'translate' {
println('Translating C to V will be available in V 0.3 (January)')
println('Translating C to V will be available in V 0.3')
}
'search', 'install', 'update', 'remove' {
launch_tool(is_verbose, 'vpm', command)
}
'get' {
println('Use `v install` to install modules from vpm.vlang.io.')
println('Use `v install` to install modules from vpm.vlang.io')
}
'symlink' {
create_symlink()
}
'doc' {
println('Currently unimplemented')
}
//'doc' {
//println('Currently unimplemented')
//}
else {
eprintln('v $command: unknown command\nRun "v help" for usage.')
exit(1)

View File

@ -9,7 +9,7 @@ mut:
children []&Scope
start_pos int
end_pos int
//vars map[string]table.Var
// vars map[string]table.Var
vars map[string]VarDecl
}
@ -46,7 +46,7 @@ pub fn (s &Scope) find_var(name string) ?VarDecl {
pub fn (s mut Scope) register_var(var VarDecl) {
if x := s.find_var(var.name) {
println('existing var: $var.name')
// println('existing var: $var.name')
return
}
s.vars[var.name] = var
@ -61,21 +61,21 @@ pub fn (s &Scope) innermost(pos int) ?&Scope {
if s.contains(pos) {
// binary search
mut first := 0
mut last := s.children.len-1
mut middle := last/2
mut last := s.children.len - 1
mut middle := last / 2
for first <= last {
//println('FIRST: $first, LAST: $last, LEN: $s.children.len-1')
// println('FIRST: $first, LAST: $last, LEN: $s.children.len-1')
s1 := s.children[middle]
if s1.end_pos < pos {
first = middle+1
first = middle + 1
}
else if s1.contains(pos) {
return s1.innermost(pos)
}
else {
last = middle-1
last = middle - 1
}
middle = (first+last)/2
middle = (first + last) / 2
if first > last {
break
}
@ -99,6 +99,7 @@ pub fn (s &Scope) innermost(pos int) ?&Scope {
}
*/
[inline]
fn (s &Scope) contains(pos int) bool {
return pos > s.start_pos && pos < s.end_pos
@ -106,7 +107,7 @@ fn (s &Scope) contains(pos int) bool {
pub fn (sc &Scope) print_vars(level int) {
mut indent := ''
for _ in 0..level*4 {
for _ in 0 .. level * 4 {
indent += ' '
}
println('$indent# $sc.start_pos - $sc.end_pos')
@ -114,6 +115,6 @@ pub fn (sc &Scope) print_vars(level int) {
println('$indent * $var.name - $var.typ')
}
for child in sc.children {
child.print_vars(level+1)
child.print_vars(level + 1)
}
}

36
vlib/v/ast/str.v 100644
View File

@ -0,0 +1,36 @@
module ast
import (
v.table
strings
)
pub fn (node &FnDecl) str(t &table.Table) string {
mut f := strings.new_builder(30)
mut receiver := ''
if node.is_method {
sym := t.get_type_symbol(node.receiver.typ)
name := sym.name.after('.')
m := if node.rec_mut { 'mut ' } else { '' }
receiver = '($node.receiver.name ${m}$name) '
}
f.write('fn ${receiver}${node.name}(')
for i, arg in node.args {
is_last_arg := i == node.args.len - 1
should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ
f.write(arg.name)
if should_add_type {
arg_typ_sym := t.get_type_symbol(arg.typ)
f.write(' ${arg_typ_sym.name}')
}
if !is_last_arg {
f.write(', ')
}
}
f.write(')')
if node.typ != table.void_type {
sym := t.get_type_symbol(node.typ)
f.write(' ' + sym.name)
}
return f.str()
}

View File

@ -11,7 +11,7 @@ fn module_path(mod string) string {
return mod.replace('.', filepath.separator)
}
fn (b &Builder) find_module_path(mod string) ?string {
pub fn (b &Builder) find_module_path(mod string) ?string {
mod_path := module_path(mod)
for search_path in b.module_search_paths {
try_path := filepath.join(search_path,mod_path)

104
vlib/v/doc/doc.v 100644
View File

@ -0,0 +1,104 @@
module doc
import (
strings
// v.builder
// v.pref
v.table
v.parser
v.ast
os
filepath
)
struct Doc {
out strings.Builder
table &table.Table
mod string
mut:
stmts []ast.Stmt // all module statements from all files
}
pub fn doc(mod string, table &table.Table) string {
mut d := Doc{
out: strings.new_builder(1000)
table: table
mod: mod
}
mods_path := filepath.dir(vexe_path()) + '/vlib'
path := filepath.join(mods_path,mod)
if !os.exists(path) {
println('module "$mod" not found')
println(path)
return ''
}
// vfiles := os.walk_ext(path, '.v')
files := os.ls(path) or {
panic(err)
}
for file in files {
if !file.ends_with('.v') {
continue
}
if file.ends_with('_test.v') {
continue
}
file_ast := parser.parse_file(filepath.join(path,file), table)
d.stmts << file_ast.stmts
}
d.print_fns()
d.writeln('')
d.print_methods()
/*
for stmt in file_ast.stmts {
d.stmt(stmt)
}
println(path)
*/
return d.out.str()
}
fn (d mut Doc) writeln(s string) {
d.out.writeln(s)
}
fn (d mut Doc) write_fn_node(f ast.FnDecl) {
d.writeln(f.str(d.table).replace(d.mod + '.', ''))
}
fn (d mut Doc) print_fns() {
for stmt in d.stmts {
match stmt {
ast.FnDecl {
if it.is_pub && !it.is_method {
d.write_fn_node(it)
}
}
else {}
}
}
}
fn (d mut Doc) print_methods() {
for stmt in d.stmts {
match stmt {
ast.FnDecl {
if it.is_pub && it.is_method {
d.write_fn_node(it)
}
}
else {}
}
}
}
pub fn vexe_path() string {
vexe := os.getenv('VEXE')
if '' != vexe {
return vexe
}
real_vexe_path := os.realpath(os.executable())
os.setenv('VEXE', real_vexe_path, true)
return real_vexe_path
}

View File

@ -0,0 +1,9 @@
import (
v.table
v.doc
)
fn test_vdoc() {
table := table.new_table()
println(doc.doc('net', table))
}

View File

@ -28,7 +28,12 @@ pub fn fmt(file ast.File, table &table.Table) string {
table: table
indent: 0
}
return f.process(file)
f.mod(file.mod)
f.imports(file.imports)
for stmt in file.stmts {
f.stmt(stmt)
}
return f.out.str().trim_space() + '\n'
}
pub fn (f mut Fmt) write(s string) {
@ -48,15 +53,6 @@ pub fn (f mut Fmt) writeln(s string) {
f.empty_line = true
}
fn (f mut Fmt) process(file ast.File) string {
f.mod(file.mod)
f.imports(file.imports)
for stmt in file.stmts {
f.stmt(stmt)
}
return f.out.str().trim_space() + '\n'
}
fn (f mut Fmt) mod(mod ast.Module) {
if mod.name != 'main' {
f.writeln('module ${mod.name}\n')
@ -67,7 +63,8 @@ fn (f mut Fmt) imports(imports []ast.Import) {
if imports.len == 1 {
imp_stmt_str := f.imp_stmt_str(imports[0])
f.writeln('import ${imp_stmt_str}\n')
} else if imports.len > 1 {
}
else if imports.len > 1 {
f.writeln('import (')
f.indent++
for imp in imports {
@ -79,11 +76,7 @@ fn (f mut Fmt) imports(imports []ast.Import) {
}
fn (f Fmt) imp_stmt_str(imp ast.Import) string {
imp_alias_suffix := if imp.alias != imp.mod {
' as ${imp.alias}'
} else {
''
}
imp_alias_suffix := if imp.alias != imp.mod { ' as ${imp.alias}' } else { '' }
return '${imp.mod}${imp_alias_suffix}'
}

View File

@ -11,11 +11,7 @@ import (
pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
tok := p.tok
name := p.check_name()
fn_name := if mod.len > 0 {
'${mod}.$name'
} else {
name
}
fn_name := if mod.len > 0 { '${mod}.$name' } else { name }
p.check(.lpar)
args := p.call_args()
node := ast.CallExpr{
@ -193,7 +189,7 @@ fn (p mut Parser) fn_args() ([]ast.Arg,bool) {
// `int, int, string` (no names, just types)
types_only := p.tok.kind in [.amp] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) || p.peek_tok.kind == .rpar
if types_only {
p.warn('types only')
// p.warn('types only')
mut arg_no := 1
for p.tok.kind != .rpar {
arg_name := 'arg_$arg_no'

View File

@ -67,7 +67,7 @@ pub fn (p mut Parser) parse_multi_return_type() table.Type {
}
pub fn (p mut Parser) parse_fn_type() table.Type {
p.warn('parrse fn')
// p.warn('parrse fn')
p.check(.key_fn)
// p.fn_decl()
p.fn_args()
@ -196,7 +196,7 @@ pub fn (p mut Parser) parse_type() table.Type {
}
// not found - add placeholder
idx = p.table.add_placeholder_type(name)
println('NOT FOUND: $name - adding placeholder - $idx')
// println('NOT FOUND: $name - adding placeholder - $idx')
return table.new_type_ptr(idx, nr_muls)
}
}

View File

@ -64,7 +64,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
}
pub fn parse_file(path string, table &table.Table) ast.File {
println('parse_file("$path")')
// println('parse_file("$path")')
text := os.read_file(path) or {
panic(err)
}
@ -95,7 +95,7 @@ pub fn parse_file(path string, table &table.Table) ast.File {
for {
// res := s.scan()
if p.tok.kind == .eof {
println('EOF, breaking')
// println('EOF, breaking')
break
}
// println('stmt at ' + p.tok.str())
@ -642,6 +642,13 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
.key_sizeof {
p.next() // sizeof
p.check(.lpar)
if p.tok.lit == 'C' {
p.next()
p.check(.dot)
}
if p.tok.kind == .amp {
p.next()
}
type_name := p.check_name()
p.check(.rpar)
node = ast.SizeOf{
@ -912,17 +919,17 @@ fn (p mut Parser) for_statement() ast.Stmt {
if p.peek_tok.kind == .decl_assign {
init = p.var_decl()
}
else if p.tok.kind != .semicolon {
// allow `for ;; i++ {`
// Allow `for i = 0; i < ...`
/*
else if p.tok.kind != .semicolon {}
// allow `for ;; i++ {`
// Allow `for i = 0; i < ...`
/*
cond, typ = p.expr(0)
if typ.kind != _bool {
p.error('non-bool used as for condition')
}
*/
println(1)
}
// println(1)
// }
p.check(.semicolon)
if p.tok.kind != .semicolon {
mut typ := table.void_type
@ -973,12 +980,12 @@ fn (p mut Parser) for_statement() ast.Stmt {
table.Map {
elem_type = it.value_type
}
else {
println(1)
// elem_type_sym := p.table.get_type_symbol(elem_type)
// p.error('cannot loop over type: $elem_type_sym.name')
}
}
else {}
// println(1)
// elem_type_sym := p.table.get_type_symbol(elem_type)
// p.error('cannot loop over type: $elem_type_sym.name')
// }
}
}
// 0 .. 10
// start := p.tok.lit.int()
@ -1144,10 +1151,8 @@ fn (p mut Parser) array_init() ast.ArrayInit {
array_type = table.new_type(idx)
}
// []
else {
// TODO ?
println(0)
}
else {}
// TODO ?
}
else {
// [1,2,3]
@ -1177,6 +1182,13 @@ fn (p mut Parser) array_init() ast.ArrayInit {
*/
}
// !
if p.tok.kind == .not {
p.next()
}
if p.tok.kind == .not {
p.next()
}
// idx := if is_fixed { p.table.find_or_register_array_fixed(val_type, fixed_size, 1) } else { p.table.find_or_register_array(val_type, 1) }
// array_type := table.new_type(idx)
return ast.ArrayInit{
@ -1265,7 +1277,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
mut exprs := []ast.Expr
for p.tok.kind != .rpar {
name := p.check_name()
println('const: $name')
// println('const: $name')
p.check(.assign)
expr,typ := p.expr(0)
fields << ast.Field{

View File

@ -87,7 +87,7 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
pub fn (t &Table) register_method(typ &TypeSymbol, new_fn Fn) bool {
// println('register method `$new_fn.name` type=$typ.name idx=$typ.idx')
println('register method `$new_fn.name` type=$typ.name')
// println('register method `$new_fn.name` type=$typ.name')
mut t1 := typ
mut methods := typ.methods
methods << new_fn