vmft2: support for multiline comments, CompIf, AssertStmt, octal literals

pull/4113/head
Delyan Angelov 2020-03-24 23:18:58 +02:00 committed by GitHub
parent 0e240458d3
commit 2a7bc63919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 114 additions and 13 deletions

View File

@ -1,5 +1,9 @@
import os import os
const (
rwxfile = os.join_path( os.temp_dir(), 'rwxfile.exe' )
)
fn testsuite_begin() { fn testsuite_begin() {
cleanup_leftovers() cleanup_leftovers()
} }
@ -259,18 +263,18 @@ fn test_symlink() {
} }
fn test_is_executable_writable_readable() { 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 { mut f := os.create(file_name) or {
eprintln('failed to create file $file_name') eprintln('failed to create file $file_name')
return return
} }
f.close() f.close()
$if !windows { $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_writable(file_name)
assert os.is_readable(file_name) assert os.is_readable(file_name)
assert !os.is_executable(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) assert os.is_executable(file_name)
} $else { } $else {
assert os.is_writable(file_name) assert os.is_writable(file_name)
@ -332,4 +336,8 @@ fn cleanup_leftovers() {
os.rmdir_all('ex2') os.rmdir_all('ex2')
os.rm('ex1.txt') os.rm('ex1.txt')
os.rm('ex2.txt') os.rm('ex2.txt')
if os.exists( rwxfile ) {
os.chmod(rwxfile, 0o777)
os.rm(rwxfile)
}
} }

View File

@ -66,6 +66,7 @@ pub struct StringInterLiteral {
pub: pub:
vals []string vals []string
exprs []Expr exprs []Expr
expr_fmts []string
mut: mut:
expr_types []table.Type expr_types []table.Type
} }

View File

@ -214,6 +214,11 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
ast.LineComment { ast.LineComment {
f.writeln('// $it.text') f.writeln('// $it.text')
} }
ast.MultiLineComment {
f.writeln('/*')
f.writeln(it.text)
f.writeln('*/')
}
ast.Return { ast.Return {
f.write('return') f.write('return')
// multiple returns // multiple returns
@ -246,6 +251,21 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
ast.TypeDecl { ast.TypeDecl {
f.type_decl(it) 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 { else {
eprintln('fmt stmt: unknown node: ' + typeof(node)) eprintln('fmt stmt: unknown node: ' + typeof(node))
// exit(1) // exit(1)
@ -535,6 +555,25 @@ fn (f mut Fmt) expr(node ast.Expr) {
f.write("'$it.val'") 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 { ast.StructInit {
type_sym := f.table.get_type_symbol(it.typ) type_sym := f.table.get_type_symbol(it.typ)
// `Foo{}` on one line if there are no fields // `Foo{}` on one line if there are no fields

View File

@ -0,0 +1,6 @@
fn test_abc() {
assert 2 < 3
assert 2 == 2
assert 'abc' == 'abc'
assert 'abc'.len == 3
}

View File

@ -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.')
}
}

View File

@ -1,4 +1,8 @@
fn main() { fn main() {
x := 0xdeadbeef x := 0xdeadbeef
u := 9978654321 u := 9978654321
o := 0o664
eprintln(' hex constant in decimal: $x')
eprintln(' u constant in decimal: $u')
eprintln('octal constant in decimal: $o')
} }

View File

@ -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')
}

View File

@ -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)
}

View File

@ -311,9 +311,10 @@ pub fn (p mut Parser) top_stmt() ast.Stmt {
return p.line_comment() return p.line_comment()
} }
.mline_comment { .mline_comment {
// p.next() comment := p.tok.lit
p.next()
return ast.MultiLineComment{ return ast.MultiLineComment{
text: p.scanner.line_comment text: comment
} }
} }
else { else {
@ -1271,6 +1272,7 @@ fn (p mut Parser) string_expr() ast.Expr {
} }
mut exprs := []ast.Expr mut exprs := []ast.Expr
mut vals := []string mut vals := []string
mut efmts := []string
// Handle $ interpolation // Handle $ interpolation
for p.tok.kind == .string { for p.tok.kind == .string {
vals << p.tok.lit vals << p.tok.lit
@ -1280,24 +1282,31 @@ fn (p mut Parser) string_expr() ast.Expr {
} }
p.check(.str_dollar) p.check(.str_dollar)
exprs << p.expr(0) exprs << p.expr(0)
mut efmt := []string
if p.tok.kind == .colon { if p.tok.kind == .colon {
efmt << ':'
p.next() p.next()
} }
// ${num:-2d} // ${num:-2d}
if p.tok.kind == .minus { if p.tok.kind == .minus {
efmt << '-'
p.next() p.next()
} }
// ${num:2d} // ${num:2d}
if p.tok.kind == .number { if p.tok.kind == .number {
efmt << p.tok.lit
p.next() p.next()
if p.tok.lit.len == 1 { if p.tok.lit.len == 1 {
efmt << p.tok.lit
p.next() p.next()
} }
} }
efmts << efmt.join('')
} }
node = ast.StringInterLiteral{ node = ast.StringInterLiteral{
vals: vals vals: vals
exprs: exprs exprs: exprs
expr_fmts: efmts
} }
return node return node
} }

View File

@ -116,7 +116,7 @@ fn filter_num_sep(txt byteptr, start int, end int) string {
mut i := start mut i := start
mut i1 := 0 mut i1 := 0
for i < end { for i < end {
if txt[i] != num_sep && txt[i] != `o` { if txt[i] != num_sep {
b[i1] = txt[i] b[i1] = txt[i]
i1++ i1++
} }
@ -741,7 +741,7 @@ pub fn (s mut Scanner) scan() token.Token {
} }
// Multiline comments // Multiline comments
if nextc == `*` { if nextc == `*` {
start := s.pos start := s.pos + 2
mut nest_count := 1 mut nest_count := 1
// Skip comment // Skip comment
for nest_count > 0 { for nest_count > 0 {
@ -763,12 +763,9 @@ pub fn (s mut Scanner) scan() token.Token {
} }
} }
s.pos++ s.pos++
end := s.pos + 1 if s.comments_mode == .parse_comments {
comment := s.text[start..end] comment := s.text[start..(s.pos-1)].trim_space()
// if s.is_fmt { return s.scan_res(.mline_comment, comment)
if false && s.comments_mode == .parse_comments {
s.line_comment = comment
return s.scan_res(.mline_comment, s.line_comment)
} }
// Skip if not in fmt mode // Skip if not in fmt mode
return s.scan() return s.scan()