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 compiler
internal.help internal.help
os os
v.table
v.doc
) )
const ( const (
@ -43,6 +45,12 @@ fn main() {
eprintln('v command: $command') eprintln('v command: $command')
eprintln('v options: $option') 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 { if command in simple_cmd {
// External tools // External tools
launch_tool(is_verbose, 'v' + command, command) launch_tool(is_verbose, 'v' + command, command)
@ -60,20 +68,20 @@ fn main() {
launch_tool(is_verbose, 'vrepl', '') launch_tool(is_verbose, 'vrepl', '')
} }
'translate' { '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' { 'search', 'install', 'update', 'remove' {
launch_tool(is_verbose, 'vpm', command) launch_tool(is_verbose, 'vpm', command)
} }
'get' { 'get' {
println('Use `v install` to install modules from vpm.vlang.io.') println('Use `v install` to install modules from vpm.vlang.io')
} }
'symlink' { 'symlink' {
create_symlink() create_symlink()
} }
'doc' { //'doc' {
println('Currently unimplemented') //println('Currently unimplemented')
} //}
else { else {
eprintln('v $command: unknown command\nRun "v help" for usage.') eprintln('v $command: unknown command\nRun "v help" for usage.')
exit(1) exit(1)

View File

@ -9,7 +9,7 @@ mut:
children []&Scope children []&Scope
start_pos int start_pos int
end_pos int end_pos int
//vars map[string]table.Var // vars map[string]table.Var
vars map[string]VarDecl 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) { pub fn (s mut Scope) register_var(var VarDecl) {
if x := s.find_var(var.name) { if x := s.find_var(var.name) {
println('existing var: $var.name') // println('existing var: $var.name')
return return
} }
s.vars[var.name] = var s.vars[var.name] = var
@ -61,21 +61,21 @@ pub fn (s &Scope) innermost(pos int) ?&Scope {
if s.contains(pos) { if s.contains(pos) {
// binary search // binary search
mut first := 0 mut first := 0
mut last := s.children.len-1 mut last := s.children.len - 1
mut middle := last/2 mut middle := last / 2
for first <= last { 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] s1 := s.children[middle]
if s1.end_pos < pos { if s1.end_pos < pos {
first = middle+1 first = middle + 1
} }
else if s1.contains(pos) { else if s1.contains(pos) {
return s1.innermost(pos) return s1.innermost(pos)
} }
else { else {
last = middle-1 last = middle - 1
} }
middle = (first+last)/2 middle = (first + last) / 2
if first > last { if first > last {
break break
} }
@ -99,6 +99,7 @@ pub fn (s &Scope) innermost(pos int) ?&Scope {
} }
*/ */
[inline] [inline]
fn (s &Scope) contains(pos int) bool { fn (s &Scope) contains(pos int) bool {
return pos > s.start_pos && pos < s.end_pos 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) { pub fn (sc &Scope) print_vars(level int) {
mut indent := '' mut indent := ''
for _ in 0..level*4 { for _ in 0 .. level * 4 {
indent += ' ' indent += ' '
} }
println('$indent# $sc.start_pos - $sc.end_pos') 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') println('$indent * $var.name - $var.typ')
} }
for child in sc.children { 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) 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) mod_path := module_path(mod)
for search_path in b.module_search_paths { for search_path in b.module_search_paths {
try_path := filepath.join(search_path,mod_path) 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 table: table
indent: 0 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) { pub fn (f mut Fmt) write(s string) {
@ -48,15 +53,6 @@ pub fn (f mut Fmt) writeln(s string) {
f.empty_line = true 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) { fn (f mut Fmt) mod(mod ast.Module) {
if mod.name != 'main' { if mod.name != 'main' {
f.writeln('module ${mod.name}\n') f.writeln('module ${mod.name}\n')
@ -67,7 +63,8 @@ fn (f mut Fmt) imports(imports []ast.Import) {
if imports.len == 1 { if imports.len == 1 {
imp_stmt_str := f.imp_stmt_str(imports[0]) imp_stmt_str := f.imp_stmt_str(imports[0])
f.writeln('import ${imp_stmt_str}\n') f.writeln('import ${imp_stmt_str}\n')
} else if imports.len > 1 { }
else if imports.len > 1 {
f.writeln('import (') f.writeln('import (')
f.indent++ f.indent++
for imp in imports { 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 { fn (f Fmt) imp_stmt_str(imp ast.Import) string {
imp_alias_suffix := if imp.alias != imp.mod { imp_alias_suffix := if imp.alias != imp.mod { ' as ${imp.alias}' } else { '' }
' as ${imp.alias}'
} else {
''
}
return '${imp.mod}${imp_alias_suffix}' 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 { pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
tok := p.tok tok := p.tok
name := p.check_name() name := p.check_name()
fn_name := if mod.len > 0 { fn_name := if mod.len > 0 { '${mod}.$name' } else { name }
'${mod}.$name'
} else {
name
}
p.check(.lpar) p.check(.lpar)
args := p.call_args() args := p.call_args()
node := ast.CallExpr{ node := ast.CallExpr{
@ -193,7 +189,7 @@ fn (p mut Parser) fn_args() ([]ast.Arg,bool) {
// `int, int, string` (no names, just types) // `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 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 { if types_only {
p.warn('types only') // p.warn('types only')
mut arg_no := 1 mut arg_no := 1
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
arg_name := 'arg_$arg_no' 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 { pub fn (p mut Parser) parse_fn_type() table.Type {
p.warn('parrse fn') // p.warn('parrse fn')
p.check(.key_fn) p.check(.key_fn)
// p.fn_decl() // p.fn_decl()
p.fn_args() p.fn_args()
@ -196,7 +196,7 @@ pub fn (p mut Parser) parse_type() table.Type {
} }
// not found - add placeholder // not found - add placeholder
idx = p.table.add_placeholder_type(name) 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) 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 { 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 { text := os.read_file(path) or {
panic(err) panic(err)
} }
@ -95,7 +95,7 @@ pub fn parse_file(path string, table &table.Table) ast.File {
for { for {
// res := s.scan() // res := s.scan()
if p.tok.kind == .eof { if p.tok.kind == .eof {
println('EOF, breaking') // println('EOF, breaking')
break break
} }
// println('stmt at ' + p.tok.str()) // println('stmt at ' + p.tok.str())
@ -642,6 +642,13 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
.key_sizeof { .key_sizeof {
p.next() // sizeof p.next() // sizeof
p.check(.lpar) 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() type_name := p.check_name()
p.check(.rpar) p.check(.rpar)
node = ast.SizeOf{ node = ast.SizeOf{
@ -912,17 +919,17 @@ fn (p mut Parser) for_statement() ast.Stmt {
if p.peek_tok.kind == .decl_assign { if p.peek_tok.kind == .decl_assign {
init = p.var_decl() init = p.var_decl()
} }
else if p.tok.kind != .semicolon { else if p.tok.kind != .semicolon {}
// allow `for ;; i++ {` // allow `for ;; i++ {`
// Allow `for i = 0; i < ...` // Allow `for i = 0; i < ...`
/* /*
cond, typ = p.expr(0) cond, typ = p.expr(0)
if typ.kind != _bool { if typ.kind != _bool {
p.error('non-bool used as for condition') p.error('non-bool used as for condition')
} }
*/ */
println(1) // println(1)
} // }
p.check(.semicolon) p.check(.semicolon)
if p.tok.kind != .semicolon { if p.tok.kind != .semicolon {
mut typ := table.void_type mut typ := table.void_type
@ -973,12 +980,12 @@ fn (p mut Parser) for_statement() ast.Stmt {
table.Map { table.Map {
elem_type = it.value_type elem_type = it.value_type
} }
else { else {}
println(1) // println(1)
// elem_type_sym := p.table.get_type_symbol(elem_type) // elem_type_sym := p.table.get_type_symbol(elem_type)
// p.error('cannot loop over type: $elem_type_sym.name') // p.error('cannot loop over type: $elem_type_sym.name')
} // }
} }
} }
// 0 .. 10 // 0 .. 10
// start := p.tok.lit.int() // start := p.tok.lit.int()
@ -1144,10 +1151,8 @@ fn (p mut Parser) array_init() ast.ArrayInit {
array_type = table.new_type(idx) array_type = table.new_type(idx)
} }
// [] // []
else { else {}
// TODO ? // TODO ?
println(0)
}
} }
else { else {
// [1,2,3] // [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) } // 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) // array_type := table.new_type(idx)
return ast.ArrayInit{ return ast.ArrayInit{
@ -1265,7 +1277,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
mut exprs := []ast.Expr mut exprs := []ast.Expr
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
name := p.check_name() name := p.check_name()
println('const: $name') // println('const: $name')
p.check(.assign) p.check(.assign)
expr,typ := p.expr(0) expr,typ := p.expr(0)
fields << ast.Field{ 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 { 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 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 t1 := typ
mut methods := typ.methods mut methods := typ.methods
methods << new_fn methods << new_fn