From 2a7bc6391927f24367f2a0e028c5b46428095bc2 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 24 Mar 2020 23:18:58 +0200 Subject: [PATCH] vmft2: support for multiline comments, CompIf, AssertStmt, octal literals --- vlib/os/os_test.v | 14 +++++-- vlib/v/ast/ast.v | 1 + vlib/v/fmt/fmt.v | 39 +++++++++++++++++++ vlib/v/fmt/tests/asserts_keep.vv | 6 +++ .../fmt/tests/conditional_compilation_keep.vv | 14 +++++++ vlib/v/fmt/tests/integer_literal_keep.vv | 4 ++ vlib/v/fmt/tests/multiline_comment_keep.vv | 10 +++++ .../string_interpolation_literal_keep.vv | 13 +++++++ vlib/v/parser/parser.v | 13 ++++++- vlib/v/scanner/scanner.v | 13 +++---- 10 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 vlib/v/fmt/tests/asserts_keep.vv create mode 100644 vlib/v/fmt/tests/conditional_compilation_keep.vv create mode 100644 vlib/v/fmt/tests/multiline_comment_keep.vv create mode 100644 vlib/v/fmt/tests/string_interpolation_literal_keep.vv diff --git a/vlib/os/os_test.v b/vlib/os/os_test.v index 079405ade5..5d0c10e52a 100644 --- a/vlib/os/os_test.v +++ b/vlib/os/os_test.v @@ -1,5 +1,9 @@ import os +const ( + rwxfile = os.join_path( os.temp_dir(), 'rwxfile.exe' ) +) + fn testsuite_begin() { cleanup_leftovers() } @@ -259,18 +263,18 @@ fn test_symlink() { } fn test_is_executable_writable_readable() { - file_name := os.temp_dir() + os.path_separator + 'rwxfile.exe' + file_name := rwxfile mut f := os.create(file_name) or { eprintln('failed to create file $file_name') return } f.close() $if !windows { - os.chmod(file_name, 0600) // mark as readable && writable, but NOT executable + os.chmod(file_name, 0o600) // mark as readable && writable, but NOT executable assert os.is_writable(file_name) assert os.is_readable(file_name) assert !os.is_executable(file_name) - os.chmod(file_name, 0700) // mark as executable too + os.chmod(file_name, 0o700) // mark as executable too assert os.is_executable(file_name) } $else { assert os.is_writable(file_name) @@ -332,4 +336,8 @@ fn cleanup_leftovers() { os.rmdir_all('ex2') os.rm('ex1.txt') os.rm('ex2.txt') + if os.exists( rwxfile ) { + os.chmod(rwxfile, 0o777) + os.rm(rwxfile) + } } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 63f68fd709..21c66574f0 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -66,6 +66,7 @@ pub struct StringInterLiteral { pub: vals []string exprs []Expr + expr_fmts []string mut: expr_types []table.Type } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 06c2fff9e1..73f25377db 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -214,6 +214,11 @@ fn (f mut Fmt) stmt(node ast.Stmt) { ast.LineComment { f.writeln('// $it.text') } + ast.MultiLineComment { + f.writeln('/*') + f.writeln(it.text) + f.writeln('*/') + } ast.Return { f.write('return') // multiple returns @@ -246,6 +251,21 @@ fn (f mut Fmt) stmt(node ast.Stmt) { ast.TypeDecl { f.type_decl(it) } + ast.AssertStmt { + f.write('assert ') + f.expr(it.expr) + f.writeln('') + } + ast.CompIf { + inversion := if it.is_not { '!' } else { '' } + f.writeln('\$if ${inversion}${it.val} {') + f.stmts(it.stmts) + if it.has_else { + f.writeln('} \$else {') + f.stmts(it.else_stmts) + } + f.writeln('}') + } else { eprintln('fmt stmt: unknown node: ' + typeof(node)) // exit(1) @@ -535,6 +555,25 @@ fn (f mut Fmt) expr(node ast.Expr) { f.write("'$it.val'") } } + ast.StringInterLiteral { + f.write("'") + for i, val in it.vals { + f.write(val) + if i>=it.exprs.len { + continue + } + f.write('$') + if it.expr_fmts[i].len > 0 { + f.write('{') + f.expr(it.exprs[i]) + f.write(it.expr_fmts[i]) + f.write('}') + }else{ + f.expr(it.exprs[i]) + } + } + f.write("'") + } ast.StructInit { type_sym := f.table.get_type_symbol(it.typ) // `Foo{}` on one line if there are no fields diff --git a/vlib/v/fmt/tests/asserts_keep.vv b/vlib/v/fmt/tests/asserts_keep.vv new file mode 100644 index 0000000000..999c1feae6 --- /dev/null +++ b/vlib/v/fmt/tests/asserts_keep.vv @@ -0,0 +1,6 @@ +fn test_abc() { + assert 2 < 3 + assert 2 == 2 + assert 'abc' == 'abc' + assert 'abc'.len == 3 +} diff --git a/vlib/v/fmt/tests/conditional_compilation_keep.vv b/vlib/v/fmt/tests/conditional_compilation_keep.vv new file mode 100644 index 0000000000..eaed279e0e --- /dev/null +++ b/vlib/v/fmt/tests/conditional_compilation_keep.vv @@ -0,0 +1,14 @@ +fn main() { + $if tinyc { + println('This will be compiled only when the compiler is tcc') + } + $if !windows { + println('This will get compiled on non-windows platforms.') + } + // + $if !linux { + println('Only non linux platforms will get this') + } $else { + println('This part is for linux only.') + } +} diff --git a/vlib/v/fmt/tests/integer_literal_keep.vv b/vlib/v/fmt/tests/integer_literal_keep.vv index 1c4cc43ba7..4785fac899 100644 --- a/vlib/v/fmt/tests/integer_literal_keep.vv +++ b/vlib/v/fmt/tests/integer_literal_keep.vv @@ -1,4 +1,8 @@ fn main() { x := 0xdeadbeef u := 9978654321 + o := 0o664 + eprintln(' hex constant in decimal: $x') + eprintln(' u constant in decimal: $u') + eprintln('octal constant in decimal: $o') } diff --git a/vlib/v/fmt/tests/multiline_comment_keep.vv b/vlib/v/fmt/tests/multiline_comment_keep.vv new file mode 100644 index 0000000000..d210288e4b --- /dev/null +++ b/vlib/v/fmt/tests/multiline_comment_keep.vv @@ -0,0 +1,10 @@ +/* +this is a very long comment +that is on multiple lines + and has some formatting in it + that should be + preserved. +*/ +fn main() { + println('hello') +} diff --git a/vlib/v/fmt/tests/string_interpolation_literal_keep.vv b/vlib/v/fmt/tests/string_interpolation_literal_keep.vv new file mode 100644 index 0000000000..9fa366dbf1 --- /dev/null +++ b/vlib/v/fmt/tests/string_interpolation_literal_keep.vv @@ -0,0 +1,13 @@ +import os + +fn main() { + println('Hello world, args: $os.args') + i := 123 + a := 'abc' + b := 'xyz' + c := 'a: $a b: $b i: $i' + d := 'a: ${a:5s} b: ${b:-5s} i: ${i:20d}' + println('a: $a $b xxx') + eprintln('c: $c') + println(d) +} diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index c4e33901cf..06b6f5c814 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -311,9 +311,10 @@ pub fn (p mut Parser) top_stmt() ast.Stmt { return p.line_comment() } .mline_comment { - // p.next() + comment := p.tok.lit + p.next() return ast.MultiLineComment{ - text: p.scanner.line_comment + text: comment } } else { @@ -1271,6 +1272,7 @@ fn (p mut Parser) string_expr() ast.Expr { } mut exprs := []ast.Expr mut vals := []string + mut efmts := []string // Handle $ interpolation for p.tok.kind == .string { vals << p.tok.lit @@ -1280,24 +1282,31 @@ fn (p mut Parser) string_expr() ast.Expr { } p.check(.str_dollar) exprs << p.expr(0) + mut efmt := []string if p.tok.kind == .colon { + efmt << ':' p.next() } // ${num:-2d} if p.tok.kind == .minus { + efmt << '-' p.next() } // ${num:2d} if p.tok.kind == .number { + efmt << p.tok.lit p.next() if p.tok.lit.len == 1 { + efmt << p.tok.lit p.next() } } + efmts << efmt.join('') } node = ast.StringInterLiteral{ vals: vals exprs: exprs + expr_fmts: efmts } return node } diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index aa0efc0dad..739fe6639e 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -116,7 +116,7 @@ fn filter_num_sep(txt byteptr, start int, end int) string { mut i := start mut i1 := 0 for i < end { - if txt[i] != num_sep && txt[i] != `o` { + if txt[i] != num_sep { b[i1] = txt[i] i1++ } @@ -741,7 +741,7 @@ pub fn (s mut Scanner) scan() token.Token { } // Multiline comments if nextc == `*` { - start := s.pos + start := s.pos + 2 mut nest_count := 1 // Skip comment for nest_count > 0 { @@ -763,12 +763,9 @@ pub fn (s mut Scanner) scan() token.Token { } } s.pos++ - end := s.pos + 1 - comment := s.text[start..end] - // if s.is_fmt { - if false && s.comments_mode == .parse_comments { - s.line_comment = comment - return s.scan_res(.mline_comment, s.line_comment) + if s.comments_mode == .parse_comments { + comment := s.text[start..(s.pos-1)].trim_space() + return s.scan_res(.mline_comment, comment) } // Skip if not in fmt mode return s.scan()