From 97db4c0e9ae9ae7633ca63e987e65b747bd2332e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 5 Apr 2020 02:08:10 +0200 Subject: [PATCH] vfmt: comments and other fixes --- cmd/tools/vfmt.v | 3 +- vlib/v/ast/ast.v | 26 +++-- vlib/v/fmt/fmt.v | 58 +++++++++-- vlib/v/fmt/tests/integer_literal_keep.vv | 16 +++ vlib/v/gen/cgen.v | 50 ++++----- vlib/v/parser/parser.v | 123 ++++++++++++++++------- vlib/v/scanner/scanner.v | 9 +- vlib/v/token/token.v | 7 +- 8 files changed, 196 insertions(+), 96 deletions(-) diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index a0b768a22a..97b4d099d5 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -54,7 +54,7 @@ fn main() { is_2: '-2' in args is_c: '-c' in args is_l: '-l' in args - is_w: '-w' in args + is_w: '-ww' in args is_diff: '-diff' in args is_verbose: '-verbose' in args || '--verbose' in args is_all: '-all' in args || '--all' in args @@ -153,6 +153,7 @@ fn main() { } exit(1) } + println('vfmt done') } fn (foptions &FormatOptions) format_file(file string) { diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index ddec29ff68..6d350f8811 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -19,7 +19,7 @@ Type | AsCast | TypeOf | StringInterLiteral pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | -LineComment | MultiLineComment | AssertStmt | UnsafeStmt | GoStmt | Block | InterfaceDecl +Comment | AssertStmt | UnsafeStmt | GoStmt | Block | InterfaceDecl pub type ScopeObject = ConstField | GlobalDecl | Var @@ -102,12 +102,21 @@ pub: expr Expr } +pub struct StructField { +pub: + name string + pos token.Position + comment Comment + default_expr Expr +mut: + typ table.Type +} + pub struct Field { pub: name string // type_idx int pos token.Position - already_reported bool mut: typ table.Type // typ2 Type @@ -134,13 +143,12 @@ pub struct StructDecl { pub: pos token.Position name string - fields []Field + fields []StructField is_pub bool mut_pos int // mut: pub_pos int // pub: pub_mut_pos int // pub mut: is_c bool - default_exprs []Expr } pub struct InterfaceDecl { @@ -268,6 +276,7 @@ pub: scope &Scope // TODO: consider parent instead of field global_scope &Scope + //comments []Comment } pub struct IdentFn { @@ -661,14 +670,11 @@ mut: expr_type table.Type } -pub struct LineComment { -pub: - text string -} - -pub struct MultiLineComment { +pub struct Comment { pub: text string + is_multi bool + line_nr int } pub struct ConcatExpr { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 6c94cd0a74..da30981efe 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -24,6 +24,7 @@ mut: line_len int single_line_if bool cur_mod string + file ast.File } pub fn fmt(file ast.File, table &table.Table) string { @@ -31,15 +32,32 @@ pub fn fmt(file ast.File, table &table.Table) string { out: strings.new_builder(1000) table: table indent: 0 + file: file } f.mod(file.mod) f.imports(file.imports) for stmt in file.stmts { f.stmt(stmt) } + /* + for comment in file.comments { + println('$comment.line_nr $comment.text') + } + */ return f.out.str().trim_space() + '\n' } +/* +fn (f mut Fmt) find_comment(line_nr int) { + for comment in f.file.comments { + if comment.line_nr == line_nr { + f.writeln('// FFF $comment.line_nr $comment.text') + return + } + } +} +*/ + pub fn (f mut Fmt) write(s string) { if f.indent > 0 && f.empty_line { f.out.write(tabs[f.indent]) @@ -170,6 +188,8 @@ fn (f mut Fmt) stmt(node ast.Stmt) { } } ast.FnDecl { + //println('$it.name find_comment($it.pos.line_nr)') + //f.find_comment(it.pos.line_nr) s := it.str(f.table) // f.write(it.str(f.table)) f.write(s.replace(f.cur_mod + '.', '')) // `Expr` instead of `ast.Expr` in mod ast @@ -215,13 +235,8 @@ fn (f mut Fmt) stmt(node ast.Stmt) { ast.GotoStmt { f.writeln('goto $it.name') } - ast.LineComment { - f.writeln('// $it.text') - } - ast.MultiLineComment { - f.writeln('/*') - f.writeln(it.text) - f.writeln('*/') + ast.Comment { + f.comment(it) } ast.Return { f.write('return') @@ -251,8 +266,8 @@ fn (f mut Fmt) stmt(node ast.Stmt) { f.writeln('}') } ast.Import {} - // already handled in f.imports ast.TypeDecl { + // already handled in f.imports f.type_decl(it) } ast.AssertStmt { @@ -308,7 +323,8 @@ fn (f mut Fmt) struct_decl(node ast.StructDecl) { if node.is_pub { f.write('pub ') } - f.writeln('struct $node.name {') + name := node.name.after('.') + f.writeln('struct $name {') mut max := 0 for field in node.fields { if field.name.len > max { @@ -325,6 +341,10 @@ fn (f mut Fmt) struct_decl(node ast.StructDecl) { else if i == node.pub_mut_pos { f.writeln('pub mut:') } + if field.comment.text != '' { + f.write('\t') + f.comment(field.comment) + } f.write('\t$field.name ') f.write(strings.repeat(` `, max - field.name.len)) f.writeln(f.type_to_str(field.typ)) @@ -596,6 +616,10 @@ fn (f mut Fmt) expr(node ast.Expr) { f.write('}') } } + ast.Type { + f.writeln(f.type_to_str(it.typ)) + + } ast.TypeOf { f.write('typeof(') f.expr(it.expr) @@ -603,6 +627,9 @@ fn (f mut Fmt) expr(node ast.Expr) { } else { eprintln('fmt expr: unhandled node ' + typeof(node)) + if typeof(node) != 'unknown v.ast.Expr' { + exit(1) + } } } } @@ -636,3 +663,16 @@ fn (f mut Fmt) or_expr(or_block ast.OrExpr) { f.write('}') } } + +fn (f mut Fmt) comment(node ast.Comment) { + if !node.text.contains('\n') { + f.writeln('// $node.text') + return + } + lines := node.text.split_into_lines() + f.writeln('/*') + for line in lines { + f.writeln(line) + } + f.writeln('*/') +} diff --git a/vlib/v/fmt/tests/integer_literal_keep.vv b/vlib/v/fmt/tests/integer_literal_keep.vv index 4785fac899..81ffaa0d09 100644 --- a/vlib/v/fmt/tests/integer_literal_keep.vv +++ b/vlib/v/fmt/tests/integer_literal_keep.vv @@ -1,3 +1,19 @@ +import os + +fn foo(a []os.File) { +} + +struct IfExpr { +} + +struct MatchExpr { +} + +type Expr = IfExpr | MatchExpr + +fn sum_types(a []Expr) { +} + fn main() { x := 0xdeadbeef u := 9978654321 diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index a9339f11dd..0d01e1e564 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -12,12 +12,12 @@ import ( ) const ( - c_reserved = ['delete', 'exit', 'unix', - // 'print', - // 'ok', - 'error', 'calloc', 'malloc', 'free', 'panic', // Full list of C reserved words, from: https://en.cppreference.com/w/c/keyword - 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', ] + c_reserved = ['delete', 'exit', 'unix', + 'error', 'calloc', 'malloc', 'free', 'panic', + 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', + 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'void', + 'volatile', 'while', ] ) struct Gen { @@ -59,6 +59,9 @@ const ( '\t\t\t\t\t\t\t\t'] ) +fn foo(file []ast.File) {} +fn foo2(file []int) {} + pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string { // println('start cgen2') mut g := Gen{ @@ -365,8 +368,9 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.expr(it.expr) expr := it.expr match expr { - // no ; after an if expression - ast.IfExpr {} + ast.IfExpr { + // no ; after an if expression + } else { if !g.inside_ternary { g.writeln(';') @@ -491,8 +495,8 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.stmts(it.stmts) g.writeln('}') } - // TODO: else if it.kind == .array { + // TODO: // `for num in nums {` g.writeln('// FOR IN') i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var } @@ -658,8 +662,8 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } } } - // `a := 1` | `a,b := 1,2` else { + // `a := 1` | `a,b := 1,2` for i, ident in assign_stmt.left { val := assign_stmt.right[i] ident_var_info := ident.var_info() @@ -1128,20 +1132,6 @@ fn (g mut Gen) expr(node ast.Expr) { g.expr(it.right) g.is_amp = false } - /* - ast.UnaryExpr { - // probably not :D - if it.op in [.inc, .dec] { - g.expr(it.left) - g.write(it.op.str()) - } - else { - g.write(it.op.str()) - g.expr(it.left) - } - } - */ - ast.SizeOf { if it.type_name != '' { g.write('sizeof($it.type_name)') @@ -1172,8 +1162,8 @@ fn (g mut Gen) expr(node ast.Expr) { ast.StringInterLiteral { g.string_inter_literal(it) } - // `user := User{name: 'Bob'}` ast.StructInit { + // `user := User{name: 'Bob'}` g.struct_init(it) } ast.SelectorExpr { @@ -1395,8 +1385,8 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { g.write(')') } } - // arr << val else if node.op == .left_shift && g.table.get_type_symbol(node.left_type).kind == .array { + // arr << val tmp := g.new_tmp_var() sym := g.table.get_type_symbol(node.left_type) info := sym.info as table.Array @@ -1840,8 +1830,8 @@ fn (g mut Gen) return_statement(node ast.Return) { g.write(' }, sizeof($styp))') } } - // normal return else if node.exprs.len == 1 { + // normal return g.write(' ') // `return opt_ok(expr)` for functions that expect an optional if fn_return_is_optional && !table.type_is(node.types[0], .optional) { @@ -2187,8 +2177,9 @@ fn (g mut Gen) write_types(types []table.TypeSymbol) { // g.definitions.writeln('};\n') } - // table.Alias, table.SumType { TODO - table.Alias {} + table.Alias { + // table.Alias, table.SumType { TODO + } table.SumType { g.definitions.writeln('// Sum type') g.definitions.writeln(' @@ -2393,10 +2384,9 @@ fn (g mut Gen) method_call(node ast.CallExpr) { g.gen_filter(node) return } - if typ_sym.kind == .array && node.name in // TODO performance, detect `array` method differently + if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', - // 'first', 'last', 'clone', 'reverse', 'slice'] { // && rec_sym.name == 'array' { // && rec_sym.name == 'array' && receiver_name.starts_with('array') { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 82326aa344..e22d817d6c 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -12,9 +12,6 @@ import ( v.util term os - // runtime - // sync - // time ) struct Parser { @@ -22,13 +19,11 @@ struct Parser { file_name string mut: tok token.Token - peek_tok token.Token - // vars []string + peek_tok token.Token // sdfsdf table &table.Table is_c bool - // prefix_parse_fns []PrefixParseFn inside_if bool - pref &pref.Preferences // Preferences shared from V struct + pref &pref.Preferences builtin_mod bool mod string attr string @@ -39,23 +34,37 @@ mut: ast_imports []ast.Import is_amp bool returns bool - inside_match_case bool // to separate `match_expr { }` from `Struct{}` + + inside_match_case bool + comments []ast.Comment + // sdfsdfd + } + + //inside_match_case bool // to separate `match_expr { }` from `Struct{}` + // prefix_parse_fns []PrefixParseFn + // vars []string + + + + + // for tests pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt { s := scanner.new_scanner(text, .skip_comments) + a := 324 mut p := Parser{ scanner: s table: table pref: &pref.Preferences{} scope: scope - // scope: &ast.Scope{start_pos: 0, parent: 0} global_scope: &ast.Scope{ start_pos: 0 parent: 0 } } + // scope: &ast.Scope{start_pos: 0, parent: 0} p.init_parse_fns() p.read_first_token() return p.stmt() @@ -115,6 +124,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment stmts: stmts scope: p.scope global_scope: p.global_scope + //comments: p.comments } } @@ -222,15 +232,23 @@ pub fn (p mut Parser) parse_block_no_scope() []ast.Stmt { return stmts } -fn (p mut Parser) next() { - // for { +/* +fn (p mut Parser) next_with_comment() { p.tok = p.peek_tok p.peek_tok = p.scanner.scan() - // if !(p.tok.kind in [.line_comment, .mline_comment]) { - // break - // } - // } - // println(p.tok.str()) +} +*/ + + +fn (p mut Parser) next() { + p.tok = p.peek_tok + p.peek_tok = p.scanner.scan() + /* + if p.tok.kind==.comment { + p.comments << ast.Comment{text:p.tok.lit, line_nr:p.tok.line_nr} + p.next() + } + */ } fn (p mut Parser) check(expected token.Kind) { @@ -319,15 +337,8 @@ pub fn (p mut Parser) top_stmt() ast.Stmt { .key_union { return p.struct_decl() } - .line_comment { - return p.line_comment() - } - .mline_comment { - comment := p.tok.lit - p.next() - return ast.MultiLineComment{ - text: comment - } + .comment { + return p.comment() } else { // #printf(""); @@ -337,10 +348,18 @@ pub fn (p mut Parser) top_stmt() ast.Stmt { } } -pub fn (p mut Parser) line_comment() ast.LineComment { +// TODO [if vfmt] +pub fn (p mut Parser) check_comment() ast.Comment { + if p.tok.kind == .comment { + return p.comment() + } +} + +pub fn (p mut Parser) comment() ast.Comment { text := p.tok.lit p.next() - return ast.LineComment{ + //p.next_with_comment() + return ast.Comment{ text: text } } @@ -367,8 +386,8 @@ pub fn (p mut Parser) stmt() ast.Stmt { .key_for { return p.for_statement() } - .line_comment { - return p.line_comment() + .comment { + return p.comment() } .key_return { return p.return_stmt() @@ -555,6 +574,9 @@ fn (p mut Parser) struct_init(short_syntax bool) ast.StructInit { is_short_syntax := !(p.peek_tok.kind == .colon || p.tok.kind == .rcbr) // `Vec{a,b,c}` // p.warn(is_short_syntax.str()) for p.tok.kind != .rcbr { + if p.tok.kind == .comment { + p.comment() + } mut field_name := '' if is_short_syntax { expr := p.expr(0) @@ -573,6 +595,9 @@ fn (p mut Parser) struct_init(short_syntax bool) ast.StructInit { if p.tok.kind == .comma { p.check(.comma) } + if p.tok.kind == .comment { + p.comment() + } } node := ast.StructInit{ typ: typ @@ -709,6 +734,11 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr { // println('\n\nparser.expr()') mut typ := table.void_type mut node := ast.Expr{} + //defer { + //if p.tok.kind == .comment { + //p.comment() + //} + //} // Prefix match p.tok.kind { .name { @@ -813,7 +843,10 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr { p.check(.rcbr) } else { - p.error('expr(): bad token `$p.tok.str()`') + if p.tok.kind == .comment { + println(p.tok.lit) + } + p.error('expr(): bad token `$p.tok.kind.str()`') } } // Infix @@ -1317,6 +1350,9 @@ fn (p mut Parser) array_init() ast.ArrayInit { if p.tok.kind == .comma { p.check(.comma) } + if p.tok.kind == .comment { + p.comment() + } } line_nr := p.tok.line_nr p.check(.rsbr) @@ -1421,6 +1457,9 @@ fn (p mut Parser) import_stmt() []ast.Import { p.check(.lpar) for p.tok.kind != .rpar { imports << p.parse_import() + if p.tok.kind == .comment { + p.comment() + } } p.check(.rpar) } @@ -1440,6 +1479,9 @@ fn (p mut Parser) const_decl() ast.ConstDecl { p.check(.lpar) mut fields := []ast.ConstField for p.tok.kind != .rpar { + if p.tok.kind == .comment { + p.comment() + } name := p.prepend_mod(p.check_name()) // name := p.check_name() // println('!!const: $name') @@ -1481,15 +1523,19 @@ fn (p mut Parser) struct_decl() ast.StructDecl { } is_typedef := p.attr == 'typedef' mut name := p.check_name() - mut default_exprs := []ast.Expr // println('struct decl $name') p.check(.lcbr) - mut ast_fields := []ast.Field + mut ast_fields := []ast.StructField mut fields := []table.Field mut mut_pos := -1 mut pub_pos := -1 mut pub_mut_pos := -1 + for p.tok.kind != .rcbr { + mut comment := ast.Comment{} + if p.tok.kind == .comment { + comment = p.comment() + } if p.tok.kind == .key_pub { p.check(.key_pub) if p.tok.kind == .key_mut { @@ -1520,16 +1566,20 @@ fn (p mut Parser) struct_decl() ast.StructDecl { println('XXXX' + s.str()) } */ - - // Default value + mut default_expr := ast.Expr{} if p.tok.kind == .assign { + // Default value p.next() - default_exprs << p.expr(0) + default_expr = p.expr(0) } - ast_fields << ast.Field{ + if p.tok.kind == .comment { + comment = p.comment() + } + ast_fields << ast.StructField{ name: field_name pos: field_pos typ: typ + comment: comment } fields << table.Field{ name: field_name @@ -1574,7 +1624,6 @@ fn (p mut Parser) struct_decl() ast.StructDecl { pub_pos: pub_pos pub_mut_pos: pub_mut_pos is_c: is_c - default_exprs: default_exprs } } diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 36c0cbe31e..5dcfb51837 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -13,7 +13,8 @@ import ( const ( single_quote = `\'` double_quote = `"` - is_fmt = os.getenv('VEXE').contains('vfmt') + //is_fmt = os.getenv('VEXE').contains('vfmt') + is_fmt = os.executable().contains('vfmt') num_sep = `_` // char used as number separator ) @@ -742,8 +743,8 @@ pub fn (s mut Scanner) scan() token.Token { // on the next line s.pos-- // println("'" + s.text[s.pos].str() + "'") - // s.line_nr-- - return s.new_token(.line_comment, comment) + s.line_nr-- + return s.new_token(.comment, comment) } // s.fgenln('// ${s.prev_tok.str()} "$s.line_comment"') // Skip the comment (return the next token) @@ -775,7 +776,7 @@ pub fn (s mut Scanner) scan() token.Token { s.pos++ if s.comments_mode == .parse_comments { comment := s.text[start..(s.pos - 1)].trim_space() - return s.new_token(.mline_comment, comment) + return s.new_token(.comment, comment) } // Skip if not in fmt mode return s.scan() diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index 05a1a893ac..9c94446f19 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -70,9 +70,7 @@ pub enum Kind { lt ge le - // comments - line_comment - mline_comment + comment nl dot dotdot @@ -199,8 +197,7 @@ fn build_token_str() []string { s[Kind.question] = '?' s[Kind.left_shift] = '<<' s[Kind.right_shift] = '>>' - s[Kind.line_comment] = '// line comment' - s[Kind.mline_comment] = '/* mline comment */' + s[Kind.comment] = '// comment' s[Kind.nl] = 'NLL' s[Kind.dollar] = '$' s[Kind.str_dollar] = '$2'