2020-02-03 05:00:36 +01:00
|
|
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
2019-12-22 02:34:37 +01:00
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
module fmt
|
|
|
|
|
2020-04-14 19:32:23 +02:00
|
|
|
import v.ast
|
|
|
|
import v.table
|
|
|
|
import strings
|
2020-02-17 22:50:04 +01:00
|
|
|
|
|
|
|
const (
|
2020-04-09 15:33:46 +02:00
|
|
|
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t']
|
2020-04-07 18:51:39 +02:00
|
|
|
max_len = 90
|
2020-02-17 22:50:04 +01:00
|
|
|
)
|
|
|
|
|
2019-12-22 02:34:37 +01:00
|
|
|
struct Fmt {
|
2020-02-21 16:48:37 +01:00
|
|
|
out strings.Builder
|
2020-04-12 17:45:04 +02:00
|
|
|
out_imports strings.Builder
|
2020-02-21 16:48:37 +01:00
|
|
|
table &table.Table
|
2020-02-17 22:50:04 +01:00
|
|
|
mut:
|
2020-02-21 16:48:37 +01:00
|
|
|
indent int
|
|
|
|
empty_line bool
|
|
|
|
line_len int
|
|
|
|
single_line_if bool
|
2020-02-21 19:56:37 +01:00
|
|
|
cur_mod string
|
2020-04-05 18:03:36 +02:00
|
|
|
file ast.File
|
2020-04-07 15:15:45 +02:00
|
|
|
did_imports bool
|
|
|
|
is_assign bool
|
2020-04-12 17:45:04 +02:00
|
|
|
auto_imports []string // automatically inserted imports that the user forgot to specify
|
|
|
|
import_pos int // position of the imports in the resulting string for later autoimports insertion
|
2020-04-13 15:05:51 +02:00
|
|
|
used_imports []string // to remove unused imports
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
|
2020-02-18 17:54:14 +01:00
|
|
|
pub fn fmt(file ast.File, table &table.Table) string {
|
2020-04-16 15:54:17 +02:00
|
|
|
var f := Fmt{
|
2020-02-17 22:50:04 +01:00
|
|
|
out: strings.new_builder(1000)
|
2020-04-12 17:45:04 +02:00
|
|
|
out_imports: strings.new_builder(200)
|
2020-02-17 22:50:04 +01:00
|
|
|
table: table
|
2020-02-18 22:35:14 +01:00
|
|
|
indent: 0
|
2020-04-05 02:08:10 +02:00
|
|
|
file: file
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-05 21:53:00 +02:00
|
|
|
f.cur_mod = 'main'
|
2020-04-10 22:27:51 +02:00
|
|
|
for i, stmt in file.stmts {
|
2020-04-12 17:45:04 +02:00
|
|
|
// TODO `if stmt is ast.Import`
|
|
|
|
match stmt {
|
|
|
|
ast.Import {
|
|
|
|
// Just remember the position of the imports for now
|
|
|
|
f.import_pos = f.out.len
|
|
|
|
// f.imports(f.file.imports)
|
|
|
|
}
|
|
|
|
else {}
|
|
|
|
}
|
2020-02-19 16:12:39 +01:00
|
|
|
f.stmt(stmt)
|
|
|
|
}
|
2020-04-05 18:15:12 +02:00
|
|
|
// for comment in file.comments { println('$comment.line_nr $comment.text') }
|
2020-04-17 20:53:39 +02:00
|
|
|
f.imports(f.file.imports) // now that we have all autoimports, handle them
|
2020-04-12 17:45:04 +02:00
|
|
|
res := f.out.str().trim_space() + '\n'
|
|
|
|
return res[..f.import_pos] + f.out_imports.str() + res[f.import_pos..]
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
|
2020-04-05 02:08:10 +02:00
|
|
|
/*
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2020-04-17 20:51:16 +02:00
|
|
|
pub fn (var f Fmt) write(s string) {
|
2020-02-17 22:50:04 +01:00
|
|
|
if f.indent > 0 && f.empty_line {
|
|
|
|
f.out.write(tabs[f.indent])
|
2020-02-22 16:59:50 +01:00
|
|
|
f.line_len += f.indent * 4
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
f.out.write(s)
|
2020-02-21 15:32:48 +01:00
|
|
|
f.line_len += s.len
|
2020-02-18 03:28:39 +01:00
|
|
|
f.empty_line = false
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
pub fn (var f Fmt) writeln(s string) {
|
2020-02-18 03:28:39 +01:00
|
|
|
if f.indent > 0 && f.empty_line {
|
|
|
|
// println(f.indent.str() + s)
|
2020-02-17 22:50:04 +01:00
|
|
|
f.out.write(tabs[f.indent])
|
|
|
|
}
|
|
|
|
f.out.writeln(s)
|
|
|
|
f.empty_line = true
|
2020-02-21 15:32:48 +01:00
|
|
|
f.line_len = 0
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) mod(mod ast.Module) {
|
2020-02-21 19:56:37 +01:00
|
|
|
f.cur_mod = mod.name
|
2020-04-10 22:32:52 +02:00
|
|
|
if mod.is_skipped {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
f.writeln('module $mod.name\n')
|
2020-02-18 22:35:14 +01:00
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) imports(imports []ast.Import) {
|
2020-04-14 18:24:19 +02:00
|
|
|
if f.did_imports || imports.len == 0 {
|
2020-04-05 21:53:00 +02:00
|
|
|
return
|
|
|
|
}
|
2020-04-12 17:45:04 +02:00
|
|
|
// f.import_pos = f.out.len
|
2020-04-14 18:24:19 +02:00
|
|
|
f.did_imports = true
|
|
|
|
/*
|
2020-02-18 22:35:14 +01:00
|
|
|
if imports.len == 1 {
|
|
|
|
imp_stmt_str := f.imp_stmt_str(imports[0])
|
2020-04-12 17:45:04 +02:00
|
|
|
f.out_imports.writeln('import ${imp_stmt_str}\n')
|
2020-04-07 15:15:45 +02:00
|
|
|
} else if imports.len > 1 {
|
2020-04-14 18:24:19 +02:00
|
|
|
*/
|
2020-04-14 19:32:23 +02:00
|
|
|
// f.out_imports.writeln('import (')
|
2020-04-14 18:24:19 +02:00
|
|
|
for imp in imports {
|
|
|
|
if !(imp.mod in f.used_imports) {
|
|
|
|
// TODO bring back once only unused imports are removed
|
|
|
|
// continue
|
|
|
|
}
|
2020-04-14 19:32:23 +02:00
|
|
|
// f.out_imports.write('\t')
|
|
|
|
// f.out_imports.writeln(f.imp_stmt_str(imp))
|
|
|
|
f.out_imports.write('import ')
|
2020-04-14 18:24:19 +02:00
|
|
|
f.out_imports.writeln(f.imp_stmt_str(imp))
|
2020-02-18 22:35:14 +01:00
|
|
|
}
|
2020-04-14 19:32:23 +02:00
|
|
|
f.out_imports.writeln('')
|
|
|
|
// f.out_imports.writeln(')\n')
|
2020-04-14 18:24:19 +02:00
|
|
|
// }
|
2020-02-18 22:35:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn (f Fmt) imp_stmt_str(imp ast.Import) string {
|
2020-02-21 20:12:55 +01:00
|
|
|
is_diff := imp.alias != imp.mod && !imp.mod.ends_with('.' + imp.alias)
|
2020-04-07 15:15:45 +02:00
|
|
|
imp_alias_suffix := if is_diff { ' as ${imp.alias}' } else { '' }
|
2020-02-18 22:35:14 +01:00
|
|
|
return '${imp.mod}${imp_alias_suffix}'
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) stmts(stmts []ast.Stmt) {
|
2020-02-17 22:50:04 +01:00
|
|
|
f.indent++
|
|
|
|
for stmt in stmts {
|
|
|
|
f.stmt(stmt)
|
|
|
|
}
|
|
|
|
f.indent--
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) stmt(node ast.Stmt) {
|
2020-02-17 22:50:04 +01:00
|
|
|
match node {
|
|
|
|
ast.AssignStmt {
|
2020-03-22 10:12:43 +01:00
|
|
|
for i, ident in it.left {
|
2020-03-10 12:01:37 +01:00
|
|
|
var_info := ident.var_info()
|
|
|
|
if var_info.is_mut {
|
2020-04-15 01:55:51 +02:00
|
|
|
f.write('var ')
|
2020-02-28 14:41:19 +01:00
|
|
|
}
|
2020-03-10 13:35:25 +01:00
|
|
|
f.expr(ident)
|
2020-03-22 10:12:43 +01:00
|
|
|
if i < it.left.len - 1 {
|
2020-02-17 22:50:04 +01:00
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
2020-04-05 23:00:17 +02:00
|
|
|
f.is_assign = true
|
2020-02-23 11:22:07 +01:00
|
|
|
f.write(' $it.op.str() ')
|
2020-03-22 10:12:43 +01:00
|
|
|
for i, val in it.right {
|
2020-03-10 12:01:37 +01:00
|
|
|
f.expr(val)
|
2020-03-22 10:12:43 +01:00
|
|
|
if i < it.right.len - 1 {
|
2020-03-10 12:01:37 +01:00
|
|
|
f.write(', ')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-07 15:48:13 +02:00
|
|
|
if !f.single_line_if {
|
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-04-05 23:00:17 +02:00
|
|
|
f.is_assign = false
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-07 18:51:39 +02:00
|
|
|
ast.AssertStmt {
|
|
|
|
f.write('assert ')
|
|
|
|
f.expr(it.expr)
|
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-02-24 17:18:14 +01:00
|
|
|
ast.Attr {
|
|
|
|
f.writeln('[$it.name]')
|
|
|
|
}
|
2020-04-05 23:00:17 +02:00
|
|
|
ast.Block {
|
|
|
|
f.writeln('{')
|
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-18 03:28:39 +01:00
|
|
|
ast.BranchStmt {
|
|
|
|
match it.tok.kind {
|
2020-04-17 20:51:16 +02:00
|
|
|
.key_break { f.writeln('break') }
|
|
|
|
.key_continue { f.writeln('continue') }
|
2020-02-18 03:28:39 +01:00
|
|
|
else {}
|
2020-04-05 18:03:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ast.Comment {
|
|
|
|
f.comment(it)
|
2020-02-18 03:28:39 +01:00
|
|
|
}
|
2020-04-07 18:51:39 +02:00
|
|
|
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('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.ConstDecl {
|
2020-02-26 22:43:37 +01:00
|
|
|
if it.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
f.writeln('const (')
|
2020-04-16 15:54:17 +02:00
|
|
|
var max := 0
|
2020-04-09 01:10:08 +02:00
|
|
|
for field in it.fields {
|
|
|
|
if field.name.len > max {
|
|
|
|
max = field.name.len
|
|
|
|
}
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
f.indent++
|
|
|
|
for i, field in it.fields {
|
2020-02-22 16:59:50 +01:00
|
|
|
name := field.name.after('.')
|
2020-04-09 01:10:08 +02:00
|
|
|
f.write('$name ')
|
|
|
|
f.write(strings.repeat(` `, max - field.name.len))
|
|
|
|
f.write('= ')
|
2020-04-04 05:14:40 +02:00
|
|
|
f.expr(field.expr)
|
2020-02-21 20:12:55 +01:00
|
|
|
f.writeln('')
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
f.indent--
|
2020-02-21 22:56:44 +01:00
|
|
|
f.writeln(')\n')
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-02-26 20:44:42 +01:00
|
|
|
ast.DeferStmt {
|
|
|
|
f.writeln('defer {')
|
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-28 17:21:20 +01:00
|
|
|
ast.EnumDecl {
|
2020-02-29 14:38:23 +01:00
|
|
|
if it.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-04-09 15:33:46 +02:00
|
|
|
name := it.name.after('.')
|
|
|
|
f.writeln('enum $name {')
|
2020-04-09 19:23:49 +02:00
|
|
|
for field in it.fields {
|
|
|
|
f.write('\t$field.name')
|
2020-04-10 14:44:01 +02:00
|
|
|
if field.has_expr {
|
2020-04-09 19:23:49 +02:00
|
|
|
f.write(' = ')
|
2020-04-10 14:44:01 +02:00
|
|
|
f.expr(field.expr)
|
2020-04-09 19:23:49 +02:00
|
|
|
}
|
2020-04-12 12:35:54 +02:00
|
|
|
f.writeln('')
|
2020-02-28 17:21:20 +01:00
|
|
|
}
|
|
|
|
f.writeln('}\n')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.ExprStmt {
|
|
|
|
f.expr(it.expr)
|
2020-02-21 16:48:37 +01:00
|
|
|
if !f.single_line_if {
|
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.FnDecl {
|
2020-04-05 18:03:36 +02:00
|
|
|
// println('$it.name find_comment($it.pos.line_nr)')
|
|
|
|
// f.find_comment(it.pos.line_nr)
|
2020-02-28 17:21:20 +01:00
|
|
|
s := it.str(f.table)
|
|
|
|
// f.write(it.str(f.table))
|
2020-04-17 20:53:39 +02:00
|
|
|
f.write(s.replace(f.cur_mod + '.', '')) // `Expr` instead of `ast.Expr` in mod ast
|
2020-04-15 23:16:49 +02:00
|
|
|
if !it.is_c && !it.is_js {
|
2020-04-04 15:36:46 +02:00
|
|
|
f.writeln(' {')
|
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}\n')
|
|
|
|
} else {
|
|
|
|
f.writeln('\n')
|
|
|
|
}
|
2020-04-13 15:05:51 +02:00
|
|
|
// Mark all function's used type so that they are not removed from imports
|
|
|
|
for arg in it.args {
|
|
|
|
f.mark_types_module_as_used(arg.typ)
|
|
|
|
}
|
|
|
|
f.mark_types_module_as_used(it.return_type)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-07 15:48:13 +02:00
|
|
|
ast.ForCStmt {
|
|
|
|
f.write('for ')
|
|
|
|
if it.has_init {
|
2020-04-17 20:53:39 +02:00
|
|
|
f.single_line_if = true // to keep all for ;; exprs on the same line
|
2020-04-07 15:48:13 +02:00
|
|
|
f.stmt(it.init)
|
|
|
|
f.single_line_if = false
|
|
|
|
}
|
|
|
|
f.write('; ')
|
|
|
|
f.expr(it.cond)
|
|
|
|
f.write('; ')
|
|
|
|
f.expr(it.inc)
|
2020-04-08 00:59:28 +02:00
|
|
|
f.writeln(' {')
|
2020-04-07 15:48:13 +02:00
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-22 14:39:25 +01:00
|
|
|
ast.ForInStmt {
|
2020-03-20 20:19:43 +01:00
|
|
|
f.write('for ')
|
|
|
|
if it.key_var != '' {
|
|
|
|
f.write(it.key_var)
|
|
|
|
}
|
2020-02-27 18:02:40 +01:00
|
|
|
if it.val_var != '' {
|
2020-03-20 20:19:43 +01:00
|
|
|
if it.key_var != '' {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
f.write(it.val_var)
|
2020-02-27 18:02:40 +01:00
|
|
|
}
|
|
|
|
f.write(' in ')
|
2020-02-22 16:59:50 +01:00
|
|
|
f.expr(it.cond)
|
2020-02-28 15:36:41 +01:00
|
|
|
if it.is_range {
|
|
|
|
f.write(' .. ')
|
|
|
|
f.expr(it.high)
|
|
|
|
}
|
2020-02-22 16:59:50 +01:00
|
|
|
f.writeln(' {')
|
2020-02-22 14:39:25 +01:00
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-18 03:28:39 +01:00
|
|
|
ast.ForStmt {
|
|
|
|
f.write('for ')
|
|
|
|
f.expr(it.cond)
|
2020-04-10 22:27:51 +02:00
|
|
|
if it.is_inf {
|
|
|
|
f.writeln('{')
|
|
|
|
} else {
|
|
|
|
f.writeln(' {')
|
|
|
|
}
|
2020-02-18 03:28:39 +01:00
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-04-07 18:51:39 +02:00
|
|
|
ast.GlobalDecl {
|
|
|
|
f.write('__global $it.name ')
|
2020-04-09 15:33:46 +02:00
|
|
|
f.write(f.type_to_str(it.typ))
|
2020-04-07 18:51:39 +02:00
|
|
|
if it.has_expr {
|
|
|
|
f.write(' = ')
|
|
|
|
f.expr(it.expr)
|
|
|
|
}
|
|
|
|
}
|
2020-03-02 17:41:32 +01:00
|
|
|
ast.GotoLabel {
|
|
|
|
f.writeln('$it.name:')
|
|
|
|
}
|
|
|
|
ast.GotoStmt {
|
|
|
|
f.writeln('goto $it.name')
|
|
|
|
}
|
2020-04-08 21:21:58 +02:00
|
|
|
ast.HashStmt {
|
|
|
|
f.writeln('#$it.val')
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
ast.Import {
|
2020-04-12 17:45:04 +02:00
|
|
|
// Imports are handled after the file is formatted, to automatically add necessary modules
|
|
|
|
// f.imports(f.file.imports)
|
2020-04-05 18:03:36 +02:00
|
|
|
}
|
|
|
|
ast.Module {
|
|
|
|
f.mod(it)
|
2020-03-24 22:18:58 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.Return {
|
|
|
|
f.write('return')
|
|
|
|
if it.exprs.len > 1 {
|
2020-04-05 18:03:36 +02:00
|
|
|
// multiple returns
|
2020-02-18 03:28:39 +01:00
|
|
|
f.write(' ')
|
2020-02-17 22:50:04 +01:00
|
|
|
for i, expr in it.exprs {
|
|
|
|
f.expr(expr)
|
|
|
|
if i < it.exprs.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
} else if it.exprs.len == 1 {
|
|
|
|
// normal return
|
2020-02-17 22:50:04 +01:00
|
|
|
f.write(' ')
|
|
|
|
f.expr(it.exprs[0])
|
|
|
|
}
|
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
ast.StructDecl {
|
|
|
|
f.struct_decl(it)
|
|
|
|
}
|
2020-03-07 17:37:55 +01:00
|
|
|
ast.TypeDecl {
|
2020-04-05 02:08:10 +02:00
|
|
|
// already handled in f.imports
|
2020-03-22 10:12:43 +01:00
|
|
|
f.type_decl(it)
|
2020-03-07 17:37:55 +01:00
|
|
|
}
|
2020-04-07 18:51:39 +02:00
|
|
|
ast.UnsafeStmt {
|
|
|
|
f.writeln('unsafe {')
|
2020-03-24 22:18:58 +01:00
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
else {
|
2020-04-07 15:48:13 +02:00
|
|
|
eprintln('fmt stmt: unhandled node ' + typeof(node))
|
|
|
|
if typeof(node) != 'unknown v.ast.Expr' {
|
|
|
|
exit(1)
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) type_decl(node ast.TypeDecl) {
|
2020-03-07 17:37:55 +01:00
|
|
|
match node {
|
|
|
|
ast.AliasTypeDecl {
|
|
|
|
if it.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-04-09 15:33:46 +02:00
|
|
|
ptype := f.type_to_str(it.parent_type)
|
2020-03-07 17:37:55 +01:00
|
|
|
f.write('type $it.name $ptype')
|
|
|
|
}
|
|
|
|
ast.SumTypeDecl {
|
|
|
|
if it.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
|
|
|
f.write('type $it.name = ')
|
2020-04-16 15:54:17 +02:00
|
|
|
var sum_type_names := []string
|
2020-03-07 17:37:55 +01:00
|
|
|
for t in it.sub_types {
|
2020-04-09 15:33:46 +02:00
|
|
|
sum_type_names << f.type_to_str(t)
|
2020-03-07 17:37:55 +01:00
|
|
|
}
|
2020-03-22 10:12:43 +01:00
|
|
|
f.write(sum_type_names.join(' | '))
|
2020-03-07 17:37:55 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
eprintln('fmt type_decl: unknown ' + typeof(node))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.writeln('\n')
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) struct_decl(node ast.StructDecl) {
|
2020-02-29 17:51:35 +01:00
|
|
|
if node.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-04-05 02:08:10 +02:00
|
|
|
name := node.name.after('.')
|
|
|
|
f.writeln('struct $name {')
|
2020-04-16 15:54:17 +02:00
|
|
|
var max := 0
|
2020-02-17 22:50:04 +01:00
|
|
|
for field in node.fields {
|
|
|
|
if field.name.len > max {
|
|
|
|
max = field.name.len
|
|
|
|
}
|
|
|
|
}
|
2020-02-22 14:13:19 +01:00
|
|
|
for i, field in node.fields {
|
|
|
|
if i == node.mut_pos {
|
|
|
|
f.writeln('mut:')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else if i == node.pub_pos {
|
2020-02-22 14:13:19 +01:00
|
|
|
f.writeln('pub:')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else if i == node.pub_mut_pos {
|
2020-02-22 14:13:19 +01:00
|
|
|
f.writeln('pub mut:')
|
|
|
|
}
|
2020-04-05 12:25:33 +02:00
|
|
|
if field.comment.text != '' && field.comment.pos.line_nr < field.pos.line_nr {
|
|
|
|
// Comment on the previous line
|
2020-04-05 02:08:10 +02:00
|
|
|
f.write('\t')
|
|
|
|
f.comment(field.comment)
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
f.write('\t$field.name ')
|
|
|
|
f.write(strings.repeat(` `, max - field.name.len))
|
2020-04-05 12:25:33 +02:00
|
|
|
f.write(f.type_to_str(field.typ))
|
2020-04-12 12:35:54 +02:00
|
|
|
if field.has_default_expr {
|
|
|
|
f.write(' = ${field.default_expr.str()}')
|
2020-04-10 00:30:43 +02:00
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
// f.write('// $field.pos.line_nr')
|
2020-04-05 12:25:33 +02:00
|
|
|
if field.comment.text != '' && field.comment.pos.line_nr == field.pos.line_nr {
|
|
|
|
// Same line comment
|
2020-04-05 18:03:36 +02:00
|
|
|
f.write(' ')
|
2020-04-05 12:25:33 +02:00
|
|
|
f.comment(field.comment)
|
|
|
|
} else {
|
2020-04-05 18:03:36 +02:00
|
|
|
// if field.comment.text != '' {
|
|
|
|
// f.write (' // com linenr=$field.comment.pos.line_nr')
|
|
|
|
// }
|
2020-04-05 12:25:33 +02:00
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
f.writeln('}\n')
|
|
|
|
}
|
|
|
|
|
2020-04-09 15:33:46 +02:00
|
|
|
fn (f &Fmt) type_to_str(t table.Type) string {
|
2020-04-17 20:51:16 +02:00
|
|
|
var res := f.table.type_to_str(t)
|
2020-04-16 07:28:41 +02:00
|
|
|
// type_ptr => &type
|
|
|
|
if res.ends_with('_ptr') {
|
2020-04-17 20:51:16 +02:00
|
|
|
res = res[0..res.len - 4]
|
2020-04-16 07:28:41 +02:00
|
|
|
start_pos := 2 * res.count('[]')
|
2020-04-17 20:51:16 +02:00
|
|
|
res = res[0..start_pos] + '&' + res[start_pos..res.len]
|
2020-04-16 07:28:41 +02:00
|
|
|
}
|
2020-02-21 19:56:37 +01:00
|
|
|
return res.replace(f.cur_mod + '.', '')
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) expr(node ast.Expr) {
|
2020-02-17 22:50:04 +01:00
|
|
|
match node {
|
|
|
|
ast.ArrayInit {
|
2020-04-05 03:37:38 +02:00
|
|
|
if it.exprs.len == 0 && it.typ != 0 && it.typ != table.void_type {
|
2020-04-05 18:03:36 +02:00
|
|
|
// `x := []string`
|
2020-04-09 15:33:46 +02:00
|
|
|
f.write(f.type_to_str(it.typ))
|
2020-04-05 18:03:36 +02:00
|
|
|
} else {
|
|
|
|
// `[1,2,3]`
|
2020-02-27 21:00:33 +01:00
|
|
|
// type_sym := f.table.get_type_symbol(it.typ)
|
|
|
|
f.write('[')
|
2020-04-18 23:09:23 +02:00
|
|
|
var inc_indent := false
|
|
|
|
var line_nr := node.position().line_nr // to have the same newlines between array elements
|
2020-02-27 21:00:33 +01:00
|
|
|
for i, expr in it.exprs {
|
2020-04-18 23:09:23 +02:00
|
|
|
pos := expr.position()
|
|
|
|
if i == 0 && line_nr < pos.line_nr {
|
|
|
|
f.writeln('')
|
|
|
|
f.indent++
|
|
|
|
inc_indent = true
|
|
|
|
}
|
2020-02-27 21:00:33 +01:00
|
|
|
if i > 0 && it.exprs.len > 1 {
|
|
|
|
f.wrap_long_line()
|
|
|
|
}
|
|
|
|
f.expr(expr)
|
|
|
|
if i < it.exprs.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
2020-04-18 23:09:23 +02:00
|
|
|
if line_nr < pos.line_nr {
|
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
line_nr = pos.line_nr
|
|
|
|
}
|
|
|
|
if inc_indent {
|
|
|
|
f.indent--
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-02-27 21:00:33 +01:00
|
|
|
f.write(']')
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
2020-03-06 22:12:15 +01:00
|
|
|
ast.AsCast {
|
2020-04-09 15:33:46 +02:00
|
|
|
type_str := f.type_to_str(it.typ)
|
2020-03-06 22:12:15 +01:00
|
|
|
f.expr(it.expr)
|
|
|
|
f.write(' as $type_str')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.AssignExpr {
|
|
|
|
f.expr(it.left)
|
|
|
|
f.write(' $it.op.str() ')
|
|
|
|
f.expr(it.val)
|
|
|
|
}
|
2020-02-22 14:39:25 +01:00
|
|
|
ast.Assoc {
|
|
|
|
f.writeln('{')
|
|
|
|
// f.indent++
|
2020-02-29 18:07:29 +01:00
|
|
|
f.writeln('\t$it.var_name |')
|
2020-02-22 14:39:25 +01:00
|
|
|
// TODO StructInit copy pasta
|
|
|
|
for i, field in it.fields {
|
2020-04-09 15:59:19 +02:00
|
|
|
f.write('\t$field: ')
|
2020-02-22 14:39:25 +01:00
|
|
|
f.expr(it.exprs[i])
|
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
// f.indent--
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.BoolLiteral {
|
|
|
|
f.write(it.val.str())
|
|
|
|
}
|
2020-02-27 18:02:40 +01:00
|
|
|
ast.CastExpr {
|
2020-04-09 15:33:46 +02:00
|
|
|
f.write(f.type_to_str(it.typ) + '(')
|
2020-02-27 18:02:40 +01:00
|
|
|
f.expr(it.expr)
|
|
|
|
f.write(')')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.CallExpr {
|
2020-04-12 17:45:04 +02:00
|
|
|
f.call_expr(it)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-02-27 21:51:40 +01:00
|
|
|
ast.CharLiteral {
|
|
|
|
f.write('`$it.val`')
|
|
|
|
}
|
2020-02-18 03:28:39 +01:00
|
|
|
ast.EnumVal {
|
2020-04-08 19:15:16 +02:00
|
|
|
name := short_module(it.enum_name)
|
2020-04-08 18:55:50 +02:00
|
|
|
f.write(name + '.' + it.val)
|
2020-02-18 03:28:39 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.FloatLiteral {
|
|
|
|
f.write(it.val)
|
|
|
|
}
|
|
|
|
ast.IfExpr {
|
2020-04-05 18:03:36 +02:00
|
|
|
f.if_expr(it)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.Ident {
|
2020-02-27 21:51:40 +01:00
|
|
|
if it.kind == .blank_ident {
|
|
|
|
f.write('_')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else {
|
2020-04-05 03:37:38 +02:00
|
|
|
name := short_module(it.name)
|
2020-04-13 19:59:57 +02:00
|
|
|
// f.write('<$it.name => $name>')
|
2020-04-05 03:37:38 +02:00
|
|
|
f.write(name)
|
2020-04-13 16:36:32 +02:00
|
|
|
if name.contains('.') {
|
|
|
|
f.mark_module_as_used(name)
|
|
|
|
}
|
2020-02-27 21:51:40 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.InfixExpr {
|
|
|
|
f.expr(it.left)
|
|
|
|
f.write(' $it.op.str() ')
|
2020-02-21 16:14:15 +01:00
|
|
|
f.wrap_long_line()
|
2020-02-17 22:50:04 +01:00
|
|
|
f.expr(it.right)
|
|
|
|
}
|
|
|
|
ast.IndexExpr {
|
2020-02-29 17:45:08 +01:00
|
|
|
f.expr(it.left)
|
|
|
|
f.write('[')
|
|
|
|
f.expr(it.index)
|
|
|
|
f.write(']')
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.IntegerLiteral {
|
2020-03-17 02:49:15 +01:00
|
|
|
f.write(it.val)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-02-22 14:13:19 +01:00
|
|
|
ast.MapInit {
|
2020-04-14 18:09:59 +02:00
|
|
|
if it.keys.len == 0 {
|
|
|
|
if it.value_type == 0 {
|
2020-04-17 20:53:39 +02:00
|
|
|
f.write('map[string]int') // TODO
|
2020-04-14 18:09:59 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
f.write('map[string]')
|
|
|
|
f.write(f.type_to_str(it.value_type))
|
|
|
|
return
|
|
|
|
}
|
2020-02-22 14:13:19 +01:00
|
|
|
f.writeln('{')
|
|
|
|
f.indent++
|
|
|
|
for i, key in it.keys {
|
|
|
|
f.expr(key)
|
|
|
|
// f.write(strings.repeat(` `, max - field.name.len))
|
|
|
|
f.write(': ')
|
|
|
|
f.expr(it.vals[i])
|
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
f.indent--
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-02-29 20:43:15 +01:00
|
|
|
ast.MatchExpr {
|
2020-04-17 20:51:16 +02:00
|
|
|
f.match_expr(it)
|
2020-02-29 20:43:15 +01:00
|
|
|
}
|
2020-02-21 17:52:20 +01:00
|
|
|
ast.None {
|
|
|
|
f.write('none')
|
|
|
|
}
|
2020-02-28 15:36:41 +01:00
|
|
|
ast.IfGuardExpr {
|
2020-02-27 18:02:40 +01:00
|
|
|
f.write(it.var_name + ' := ')
|
|
|
|
f.expr(it.expr)
|
|
|
|
}
|
2020-02-28 15:36:41 +01:00
|
|
|
ast.ParExpr {
|
2020-02-28 14:41:19 +01:00
|
|
|
f.write('(')
|
|
|
|
f.expr(it.expr)
|
|
|
|
f.write(')')
|
2020-02-28 15:36:41 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.PostfixExpr {
|
|
|
|
f.expr(it.expr)
|
|
|
|
f.write(it.op.str())
|
|
|
|
}
|
|
|
|
ast.PrefixExpr {
|
|
|
|
f.write(it.op.str())
|
|
|
|
f.expr(it.right)
|
|
|
|
}
|
2020-02-29 17:45:08 +01:00
|
|
|
ast.RangeExpr {
|
|
|
|
f.expr(it.low)
|
|
|
|
f.write('..')
|
|
|
|
f.expr(it.high)
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.SelectorExpr {
|
|
|
|
f.expr(it.expr)
|
|
|
|
f.write('.')
|
|
|
|
f.write(it.field)
|
|
|
|
}
|
2020-04-07 18:51:39 +02:00
|
|
|
ast.SizeOf {
|
2020-04-10 00:30:43 +02:00
|
|
|
f.write('sizeof(')
|
2020-04-07 18:51:39 +02:00
|
|
|
if it.type_name != '' {
|
2020-04-10 00:30:43 +02:00
|
|
|
f.write(it.type_name)
|
2020-04-07 18:51:39 +02:00
|
|
|
} else {
|
2020-04-10 00:30:43 +02:00
|
|
|
f.write(f.type_to_str(it.typ))
|
2020-04-07 18:51:39 +02:00
|
|
|
}
|
2020-04-10 00:30:43 +02:00
|
|
|
f.write(')')
|
2020-04-07 18:51:39 +02:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.StringLiteral {
|
2020-04-05 19:35:10 +02:00
|
|
|
if it.val.contains("'") {
|
|
|
|
f.write('"$it.val"')
|
|
|
|
} else {
|
|
|
|
f.write("'$it.val'")
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-03-24 22:18:58 +01:00
|
|
|
ast.StringInterLiteral {
|
|
|
|
f.write("'")
|
|
|
|
for i, val in it.vals {
|
|
|
|
f.write(val)
|
2020-04-05 18:03:36 +02:00
|
|
|
if i >= it.exprs.len {
|
2020-03-24 22:18:58 +01:00
|
|
|
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('}')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else {
|
2020-03-24 22:18:58 +01:00
|
|
|
f.expr(it.exprs[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write("'")
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.StructInit {
|
|
|
|
type_sym := f.table.get_type_symbol(it.typ)
|
2020-04-13 19:59:57 +02:00
|
|
|
// f.write('<old name: $type_sym.name>')
|
2020-04-17 20:53:39 +02:00
|
|
|
var name := short_module(type_sym.name).replace(f.cur_mod + '.', '') // TODO f.type_to_str?
|
2020-04-10 00:30:43 +02:00
|
|
|
if name == 'void' {
|
|
|
|
name = ''
|
|
|
|
}
|
2020-04-17 02:38:39 +02:00
|
|
|
if it.fields.len == 0 {
|
2020-04-10 00:30:43 +02:00
|
|
|
// `Foo{}` on one line if there are no fields
|
2020-04-05 03:37:38 +02:00
|
|
|
f.write('$name{}')
|
2020-04-10 00:30:43 +02:00
|
|
|
} else if it.fields.len == 0 {
|
|
|
|
// `Foo{1,2,3}` (short syntax )
|
2020-04-10 00:36:50 +02:00
|
|
|
f.write('$name{')
|
2020-04-17 02:38:39 +02:00
|
|
|
for i, field in it.fields {
|
|
|
|
f.expr(field.expr)
|
|
|
|
if i < it.fields.len - 1 {
|
2020-04-10 00:30:43 +02:00
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write('}')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else {
|
2020-04-05 03:37:38 +02:00
|
|
|
f.writeln('$name{')
|
2020-04-08 00:59:28 +02:00
|
|
|
f.indent++
|
2020-02-22 16:59:50 +01:00
|
|
|
for i, field in it.fields {
|
2020-04-17 02:38:39 +02:00
|
|
|
f.write('$field.name: ')
|
|
|
|
f.expr(field.expr)
|
2020-02-22 16:59:50 +01:00
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-04-08 00:59:28 +02:00
|
|
|
f.indent--
|
2020-02-22 16:59:50 +01:00
|
|
|
f.write('}')
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-05 02:08:10 +02:00
|
|
|
ast.Type {
|
2020-04-05 18:03:36 +02:00
|
|
|
f.write(f.type_to_str(it.typ))
|
2020-04-05 02:08:10 +02:00
|
|
|
}
|
2020-04-03 11:59:53 +02:00
|
|
|
ast.TypeOf {
|
|
|
|
f.write('typeof(')
|
|
|
|
f.expr(it.expr)
|
|
|
|
f.write(')')
|
|
|
|
}
|
2020-02-27 18:02:40 +01:00
|
|
|
else {
|
2020-03-07 17:37:55 +01:00
|
|
|
eprintln('fmt expr: unhandled node ' + typeof(node))
|
2020-04-05 02:08:10 +02:00
|
|
|
if typeof(node) != 'unknown v.ast.Expr' {
|
|
|
|
exit(1)
|
|
|
|
}
|
2020-02-27 18:02:40 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-22 02:34:37 +01:00
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) wrap_long_line() {
|
2020-02-21 16:14:15 +01:00
|
|
|
if f.line_len > max_len {
|
2020-04-08 01:04:04 +02:00
|
|
|
if f.out.buf[f.out.buf.len - 1] == ` ` {
|
2020-04-08 00:59:28 +02:00
|
|
|
f.out.go_back(1)
|
|
|
|
}
|
2020-02-21 16:14:15 +01:00
|
|
|
f.write('\n' + tabs[f.indent + 1])
|
|
|
|
f.line_len = 0
|
|
|
|
}
|
|
|
|
}
|
2020-03-02 17:09:45 +01:00
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) call_args(args []ast.CallArg) {
|
2020-03-02 17:09:45 +01:00
|
|
|
for i, arg in args {
|
2020-03-14 11:11:43 +01:00
|
|
|
if arg.is_mut {
|
2020-03-02 17:09:45 +01:00
|
|
|
f.write('mut ')
|
|
|
|
}
|
|
|
|
if i > 0 {
|
|
|
|
f.wrap_long_line()
|
|
|
|
}
|
2020-03-14 11:11:43 +01:00
|
|
|
f.expr(arg.expr)
|
2020-03-02 17:09:45 +01:00
|
|
|
if i < args.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) or_expr(or_block ast.OrExpr) {
|
2020-03-02 17:09:45 +01:00
|
|
|
if or_block.stmts.len > 0 {
|
|
|
|
f.writeln(' or {')
|
|
|
|
f.stmts(or_block.stmts)
|
|
|
|
f.write('}')
|
|
|
|
}
|
|
|
|
}
|
2020-04-05 02:08:10 +02:00
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) comment(node ast.Comment) {
|
2020-04-05 02:08:10 +02:00
|
|
|
if !node.text.contains('\n') {
|
2020-04-05 16:38:29 +02:00
|
|
|
is_separate_line := node.text.starts_with('|')
|
2020-04-16 15:54:17 +02:00
|
|
|
var s := if is_separate_line { node.text[1..] } else { node.text }
|
2020-04-08 14:19:13 +02:00
|
|
|
if s == '' {
|
|
|
|
s = '//'
|
2020-04-05 16:38:29 +02:00
|
|
|
} else {
|
2020-04-08 14:19:13 +02:00
|
|
|
s = '// ' + s
|
|
|
|
}
|
|
|
|
if !is_separate_line {
|
2020-04-17 20:53:39 +02:00
|
|
|
f.remove_new_line() // delete the generated \n
|
|
|
|
f.write(' ')
|
2020-04-05 16:38:29 +02:00
|
|
|
}
|
2020-04-08 14:19:13 +02:00
|
|
|
f.writeln(s)
|
2020-04-05 02:08:10 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
lines := node.text.split_into_lines()
|
|
|
|
f.writeln('/*')
|
|
|
|
for line in lines {
|
|
|
|
f.writeln(line)
|
2020-04-05 19:35:10 +02:00
|
|
|
f.empty_line = false
|
2020-04-05 02:08:10 +02:00
|
|
|
}
|
|
|
|
f.writeln('*/')
|
|
|
|
}
|
2020-04-05 03:37:38 +02:00
|
|
|
|
|
|
|
// foo.bar.fn() => bar.fn()
|
|
|
|
fn short_module(name string) string {
|
|
|
|
if !name.contains('.') {
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
vals := name.split('.')
|
|
|
|
if vals.len < 2 {
|
|
|
|
return name
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
return vals[vals.len - 2] + '.' + vals[vals.len - 1]
|
|
|
|
}
|
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) if_expr(it ast.IfExpr) {
|
2020-04-08 00:59:28 +02:00
|
|
|
single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == 1 &&
|
|
|
|
it.branches[1].stmts.len == 1 && (it.is_expr || f.is_assign)
|
2020-04-05 18:03:36 +02:00
|
|
|
f.single_line_if = single_line
|
|
|
|
for i, branch in it.branches {
|
2020-04-07 15:15:45 +02:00
|
|
|
if branch.comment.text != '' {
|
|
|
|
f.comment(branch.comment)
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
if i == 0 {
|
|
|
|
f.write('if ')
|
|
|
|
f.expr(branch.cond)
|
|
|
|
f.write(' {')
|
|
|
|
} else if i < it.branches.len - 1 || !it.has_else {
|
|
|
|
f.write('} else if ')
|
|
|
|
f.expr(branch.cond)
|
|
|
|
f.write(' {')
|
|
|
|
} else if i == it.branches.len - 1 && it.has_else {
|
|
|
|
f.write('} else {')
|
|
|
|
}
|
2020-04-05 19:35:10 +02:00
|
|
|
if single_line {
|
|
|
|
f.write(' ')
|
|
|
|
} else {
|
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
f.stmts(branch.stmts)
|
|
|
|
if single_line {
|
|
|
|
f.write(' ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write('}')
|
|
|
|
f.single_line_if = false
|
2020-04-05 03:37:38 +02:00
|
|
|
}
|
2020-04-12 17:45:04 +02:00
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) call_expr(node ast.CallExpr) {
|
2020-04-12 17:45:04 +02:00
|
|
|
if node.is_method {
|
|
|
|
match node.left {
|
|
|
|
ast.Ident {
|
|
|
|
// `time.now()` without `time imported` is processed as a method call with `time` being
|
|
|
|
// a `node.left` expression. Import `time` automatically.
|
|
|
|
// TODO fetch all available modules
|
2020-04-13 15:05:51 +02:00
|
|
|
if it.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] {
|
2020-04-12 17:45:04 +02:00
|
|
|
if !(it.name in f.auto_imports) {
|
|
|
|
f.auto_imports << it.name
|
|
|
|
f.file.imports << ast.Import{
|
|
|
|
mod: it.name
|
|
|
|
alias: it.name
|
|
|
|
}
|
|
|
|
}
|
2020-04-12 17:57:05 +02:00
|
|
|
// for imp in f.file.imports {
|
|
|
|
// println(imp.mod)
|
|
|
|
// }
|
2020-04-12 17:45:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {}
|
|
|
|
}
|
|
|
|
f.expr(node.left)
|
|
|
|
f.write('.' + node.name + '(')
|
|
|
|
f.call_args(node.args)
|
|
|
|
f.write(')')
|
|
|
|
f.or_expr(node.or_block)
|
|
|
|
} else {
|
|
|
|
name := short_module(node.name)
|
2020-04-13 15:05:51 +02:00
|
|
|
f.mark_module_as_used(name)
|
2020-04-12 17:45:04 +02:00
|
|
|
f.write('${name}(')
|
|
|
|
f.call_args(node.args)
|
|
|
|
f.write(')')
|
|
|
|
f.or_expr(node.or_block)
|
|
|
|
}
|
|
|
|
}
|
2020-04-13 15:05:51 +02:00
|
|
|
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) match_expr(it ast.MatchExpr) {
|
|
|
|
f.write('match ')
|
|
|
|
if it.is_mut {
|
|
|
|
f.write('var ')
|
|
|
|
}
|
|
|
|
f.expr(it.cond)
|
|
|
|
f.writeln(' {')
|
|
|
|
f.indent++
|
|
|
|
var single_line := true
|
|
|
|
for i, branch in it.branches {
|
|
|
|
if branch.stmts.len > 1 {
|
|
|
|
single_line = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i, branch in it.branches {
|
|
|
|
if branch.comment.text != '' {
|
|
|
|
f.comment(branch.comment)
|
|
|
|
}
|
|
|
|
if !branch.is_else {
|
|
|
|
// normal branch
|
|
|
|
for j, expr in branch.exprs {
|
|
|
|
f.expr(expr)
|
|
|
|
if j < branch.exprs.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// else branch
|
|
|
|
f.write('else')
|
|
|
|
}
|
|
|
|
if branch.stmts.len == 0 {
|
|
|
|
f.writeln(' {}')
|
|
|
|
} else {
|
|
|
|
if single_line {
|
|
|
|
f.write(' { ')
|
|
|
|
} else {
|
|
|
|
f.writeln(' {')
|
|
|
|
}
|
|
|
|
f.stmts(branch.stmts)
|
|
|
|
if single_line {
|
|
|
|
f.remove_new_line()
|
|
|
|
f.writeln(' }')
|
|
|
|
} else {
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.indent--
|
|
|
|
f.write('}')
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (var f Fmt) remove_new_line() {
|
|
|
|
var i := 0
|
|
|
|
for i = f.out.len - 1; i >= 0; i-- {
|
2020-04-17 20:53:39 +02:00
|
|
|
if !f.out.buf[i].is_space() { // != `\n` {
|
2020-04-17 20:51:16 +02:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.out.go_back(f.out.len - i - 1)
|
|
|
|
f.empty_line = false
|
|
|
|
// f.writeln('sdf')
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (var f Fmt) mark_types_module_as_used(typ table.Type) {
|
2020-04-13 15:05:51 +02:00
|
|
|
sym := f.table.get_type_symbol(typ)
|
|
|
|
f.mark_module_as_used(sym.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// `name` is a function (`foo.bar()`) or type (`foo.Bar{}`)
|
2020-04-17 20:51:16 +02:00
|
|
|
fn (var f Fmt) mark_module_as_used(name string) {
|
2020-04-13 15:05:51 +02:00
|
|
|
if !name.contains('.') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
pos := name.last_index('.') or {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
mod := name[..pos]
|
|
|
|
if mod in f.used_imports {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
f.used_imports << mod
|
|
|
|
// println('marking module $mod as used')
|
|
|
|
}
|