mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
vdoc using the new parser
This commit is contained in:
parent
391da0ba07
commit
092c09d81f
18
cmd/v/v.v
18
cmd/v/v.v
@ -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)
|
||||
|
@ -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
Normal file
36
vlib/v/ast/str.v
Normal 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()
|
||||
}
|
@ -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
Normal file
104
vlib/v/doc/doc.v
Normal 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
|
||||
}
|
9
vlib/v/doc/doc_test.v
Normal file
9
vlib/v/doc/doc_test.v
Normal file
@ -0,0 +1,9 @@
|
||||
import (
|
||||
v.table
|
||||
v.doc
|
||||
)
|
||||
|
||||
fn test_vdoc() {
|
||||
table := table.new_table()
|
||||
println(doc.doc('net', table))
|
||||
}
|
@ -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}'
|
||||
}
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user