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
|
2020-06-24 15:19:30 +02:00
|
|
|
import v.token
|
2020-04-14 19:32:23 +02:00
|
|
|
import strings
|
2020-07-01 00:53:53 +02:00
|
|
|
import v.util
|
2020-02-17 22:50:04 +01:00
|
|
|
|
|
|
|
const (
|
2020-05-28 05:50:57 +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-07-19 19:58:34 +02:00
|
|
|
'\t\t\t\t\t\t\t\t',
|
2020-05-28 05:50:57 +02:00
|
|
|
]
|
2020-06-19 19:54:26 +02:00
|
|
|
// when to break a line dependant on penalty
|
2020-06-25 22:24:28 +02:00
|
|
|
max_len = [0, 35, 85, 93, 100]
|
2020-02-17 22:50:04 +01:00
|
|
|
)
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub struct Fmt {
|
|
|
|
pub mut:
|
2020-07-11 15:09:12 +02:00
|
|
|
table &table.Table
|
2020-06-01 17:24:38 +02:00
|
|
|
out_imports strings.Builder
|
|
|
|
out strings.Builder
|
2020-06-23 17:54:39 +02:00
|
|
|
out_save strings.Builder
|
2020-05-24 04:43:00 +02:00
|
|
|
indent int
|
|
|
|
empty_line bool
|
|
|
|
line_len int
|
2020-06-24 15:19:30 +02:00
|
|
|
buffering bool // expressions will be analyzed later by adjust_complete_line() before finally written
|
|
|
|
expr_bufs []string // and stored here in the meantime (expr_bufs.len-1 = penalties.len = precedences.len)
|
|
|
|
penalties []int // how hard should it be to break line after each expression
|
|
|
|
precedences []int // operator/parenthese precedences for operator at end of each expression
|
|
|
|
par_level int // how many parentheses are put around the current expression
|
2020-07-09 22:36:49 +02:00
|
|
|
array_init_break []bool // line breaks after elements in hierarchy level of multi dimensional array
|
|
|
|
array_init_depth int // current level of hierarchie in array init
|
2020-05-24 04:43:00 +02:00
|
|
|
single_line_if bool
|
|
|
|
cur_mod string
|
|
|
|
file ast.File
|
|
|
|
did_imports bool
|
|
|
|
is_assign bool
|
2020-06-18 18:48:23 +02:00
|
|
|
is_inside_interp bool
|
2020-05-24 04:43:00 +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
|
|
|
|
used_imports []string // to remove unused imports
|
|
|
|
is_debug bool
|
|
|
|
mod2alias map[string]string // for `import time as t`, will contain: 'time'=>'t'
|
|
|
|
use_short_fn_args bool
|
2020-06-18 20:07:48 +02:00
|
|
|
it_name string // the name to replace `it` with
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
|
2020-05-04 16:22:41 +02:00
|
|
|
pub fn fmt(file ast.File, table &table.Table, is_debug bool) string {
|
2020-04-21 05:11:50 +02:00
|
|
|
mut 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-05-04 16:22:41 +02:00
|
|
|
is_debug: is_debug
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-06-15 17:28:00 +02:00
|
|
|
f.process_file_imports(file)
|
2020-07-11 15:09:12 +02:00
|
|
|
f.set_current_module_name('main')
|
2020-04-28 15:04:37 +02:00
|
|
|
for stmt in file.stmts {
|
2020-04-30 09:33:43 +02:00
|
|
|
if stmt is ast.Import {
|
|
|
|
// Just remember the position of the imports for now
|
|
|
|
f.import_pos = f.out.len
|
|
|
|
// f.imports(f.file.imports)
|
2020-04-12 17:45:04 +02:00
|
|
|
}
|
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'
|
2020-07-14 18:52:28 +02:00
|
|
|
bounded_import_pos := util.imin(res.len, f.import_pos)
|
2020-07-11 13:53:21 +02:00
|
|
|
return res[..bounded_import_pos] + f.out_imports.str() + res[bounded_import_pos..] // + '\n'
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
|
2020-06-15 17:28:00 +02:00
|
|
|
pub fn (mut f Fmt) process_file_imports(file &ast.File) {
|
|
|
|
for imp in file.imports {
|
|
|
|
f.mod2alias[imp.mod.all_after_last('.')] = imp.alias
|
2020-07-18 21:34:38 +02:00
|
|
|
for sym in imp.syms {
|
|
|
|
f.mod2alias['$imp.mod\.$sym.name'] = sym.name
|
|
|
|
f.mod2alias[sym.name] = sym.name
|
|
|
|
}
|
2020-06-15 17:28:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-05 02:08:10 +02:00
|
|
|
/*
|
2020-06-04 10:35:40 +02:00
|
|
|
fn (mut f Fmt) find_comment(line_nr int) {
|
2020-04-05 02:08:10 +02:00
|
|
|
for comment in f.file.comments {
|
|
|
|
if comment.line_nr == line_nr {
|
|
|
|
f.writeln('// FFF $comment.line_nr $comment.text')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2020-04-21 05:11:50 +02:00
|
|
|
pub fn (mut f Fmt) write(s string) {
|
2020-06-24 20:40:29 +02:00
|
|
|
if !f.buffering {
|
2020-06-23 17:54:39 +02:00
|
|
|
if f.indent > 0 && f.empty_line {
|
|
|
|
if f.indent < tabs.len {
|
|
|
|
f.out.write(tabs[f.indent])
|
|
|
|
} else {
|
|
|
|
// too many indents, do it the slow way:
|
|
|
|
for _ in 0 .. f.indent {
|
|
|
|
f.out.write('\t')
|
|
|
|
}
|
2020-04-28 15:04:37 +02:00
|
|
|
}
|
2020-06-23 17:54:39 +02:00
|
|
|
f.line_len += f.indent * 4
|
2020-04-28 15:04:37 +02:00
|
|
|
}
|
2020-06-23 17:54:39 +02:00
|
|
|
f.out.write(s)
|
|
|
|
f.line_len += s.len
|
|
|
|
f.empty_line = false
|
|
|
|
} else {
|
|
|
|
f.out.write(s)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-21 05:11:50 +02:00
|
|
|
pub fn (mut f Fmt) writeln(s string) {
|
2020-06-24 15:19:30 +02:00
|
|
|
empty_fifo := f.buffering
|
2020-06-23 17:54:39 +02:00
|
|
|
if empty_fifo {
|
|
|
|
f.write(s)
|
|
|
|
f.expr_bufs << f.out.str()
|
|
|
|
f.out = f.out_save
|
|
|
|
f.adjust_complete_line()
|
2020-06-24 15:19:30 +02:00
|
|
|
f.buffering = false
|
2020-06-23 17:54:39 +02:00
|
|
|
for i, p in f.penalties {
|
|
|
|
f.write(f.expr_bufs[i])
|
|
|
|
f.wrap_long_line(p, true)
|
|
|
|
}
|
2020-06-24 14:35:00 +02:00
|
|
|
f.write(f.expr_bufs[f.expr_bufs.len - 1])
|
2020-06-23 17:54:39 +02:00
|
|
|
f.expr_bufs = []string{}
|
|
|
|
f.penalties = []int{}
|
2020-06-24 15:19:30 +02:00
|
|
|
f.precedences = []int{}
|
2020-06-23 17:54:39 +02:00
|
|
|
}
|
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])
|
|
|
|
}
|
2020-06-24 14:35:00 +02:00
|
|
|
f.out.writeln(if empty_fifo {
|
|
|
|
''
|
|
|
|
} else {
|
|
|
|
s
|
|
|
|
})
|
2020-02-17 22:50:04 +01:00
|
|
|
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-06-23 17:54:39 +02:00
|
|
|
// adjustments that can only be done after full line is processed. For now
|
|
|
|
// only prevents line breaks if everything fits in max_len[last] by increasing
|
|
|
|
// penalties to maximum
|
|
|
|
fn (mut f Fmt) adjust_complete_line() {
|
2020-06-24 15:19:30 +02:00
|
|
|
for i, buf in f.expr_bufs {
|
|
|
|
// search for low penalties
|
2020-07-01 20:07:33 +02:00
|
|
|
if i == 0 || f.penalties[i - 1] <= 1 {
|
|
|
|
precedence := if i == 0 { -1 } else { f.precedences[i - 1] }
|
2020-06-24 15:19:30 +02:00
|
|
|
mut len_sub_expr := if i == 0 { buf.len + f.line_len } else { buf.len }
|
|
|
|
mut sub_expr_end_idx := f.penalties.len
|
|
|
|
// search for next position with low penalty and same precedence to form subexpression
|
2020-07-01 20:07:33 +02:00
|
|
|
for j in i .. f.penalties.len {
|
|
|
|
if f.penalties[j] <= 1 &&
|
|
|
|
f.precedences[j] == precedence && len_sub_expr >= max_len[1] {
|
2020-06-24 15:19:30 +02:00
|
|
|
sub_expr_end_idx = j
|
|
|
|
break
|
2020-06-24 20:40:29 +02:00
|
|
|
} else if f.precedences[j] < precedence {
|
|
|
|
// we cannot form a sensible subexpression
|
|
|
|
len_sub_expr = C.INT32_MAX
|
|
|
|
break
|
2020-06-24 15:19:30 +02:00
|
|
|
} else {
|
2020-07-01 20:07:33 +02:00
|
|
|
len_sub_expr += f.expr_bufs[j + 1].len
|
2020-06-24 15:19:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// if subexpression would fit in single line adjust penalties to actually do so
|
2020-07-01 20:07:33 +02:00
|
|
|
if len_sub_expr <= max_len[max_len.len - 1] {
|
|
|
|
for j in i .. sub_expr_end_idx {
|
|
|
|
f.penalties[j] = max_len.len - 1
|
2020-06-24 15:19:30 +02:00
|
|
|
}
|
|
|
|
if i > 0 {
|
2020-07-01 20:07:33 +02:00
|
|
|
f.penalties[i - 1] = 0
|
2020-06-24 15:19:30 +02:00
|
|
|
}
|
|
|
|
if sub_expr_end_idx < f.penalties.len {
|
|
|
|
f.penalties[sub_expr_end_idx] = 0
|
|
|
|
}
|
|
|
|
}
|
2020-06-23 17:54:39 +02:00
|
|
|
}
|
2020-07-01 20:07:33 +02:00
|
|
|
// emergency fallback: decrease penalty in front of long unbreakable parts
|
2020-07-23 00:32:34 +02:00
|
|
|
if i > 0 && buf.len > 55 && f.penalties[i - 1] > 0 {
|
|
|
|
f.penalties[i - 1] = if buf.len >= 72 { 0 } else { 1 }
|
2020-06-25 22:24:28 +02:00
|
|
|
}
|
2020-06-23 17:54:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-14 18:52:28 +02:00
|
|
|
pub fn (mut f Fmt) set_current_module_name(cmodname string) {
|
2020-07-11 15:09:12 +02:00
|
|
|
f.cur_mod = cmodname
|
|
|
|
f.table.cmod_prefix = cmodname + '.'
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) mod(mod ast.Module) {
|
2020-07-11 15:09:12 +02:00
|
|
|
f.set_current_module_name(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-05-19 13:19:37 +02:00
|
|
|
pub fn (mut 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-25 17:49:16 +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 {
|
2020-04-26 06:39:23 +02:00
|
|
|
if imp.mod !in f.used_imports {
|
2020-04-14 18:24:19 +02:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub 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-07-18 21:34:38 +02:00
|
|
|
mut imp_alias_suffix := if is_diff { ' as $imp.alias' } else { '' }
|
|
|
|
if imp.syms.len > 0 {
|
|
|
|
imp_alias_suffix += ' { ' + imp.syms.map(it.name).join(', ') + ' }'
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
return '$imp.mod$imp_alias_suffix'
|
2020-02-18 22:35:14 +01:00
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut 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-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
2020-05-04 16:22:41 +02:00
|
|
|
if f.is_debug {
|
|
|
|
eprintln('stmt: ${node.position():-42} | node: ${typeof(node):-20}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
match node {
|
|
|
|
ast.AssignStmt {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comments(node.comments, {})
|
2020-06-18 20:07:48 +02:00
|
|
|
for i, left in node.left {
|
2020-06-16 13:20:16 +02:00
|
|
|
if left is ast.Ident {
|
2020-07-09 17:14:14 +02:00
|
|
|
var_info := left.var_info()
|
2020-06-16 13:20:16 +02:00
|
|
|
if var_info.is_mut {
|
2020-07-09 22:41:45 +02:00
|
|
|
f.write(var_info.share.str() + ' ')
|
2020-06-16 13:20:16 +02:00
|
|
|
}
|
|
|
|
f.expr(left)
|
2020-06-18 20:07:48 +02:00
|
|
|
} else {
|
2020-06-16 13:20:16 +02:00
|
|
|
f.expr(left)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-07-14 18:11:16 +02:00
|
|
|
if i < node.left.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-05 23:00:17 +02:00
|
|
|
f.is_assign = true
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(' $node.op.str() ')
|
|
|
|
for i, val in node.right {
|
2020-07-02 14:06:29 +02:00
|
|
|
f.prefix_expr_cast_expr(val)
|
2020-06-18 20:07:48 +02:00
|
|
|
if i < node.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 ')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.expr)
|
2020-04-07 18:51:39 +02:00
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-04-05 23:00:17 +02:00
|
|
|
ast.Block {
|
2020-08-02 13:06:44 +02:00
|
|
|
if node.is_unsafe {
|
|
|
|
f.write('unsafe ')
|
|
|
|
}
|
2020-04-05 23:00:17 +02:00
|
|
|
f.writeln('{')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.stmts(node.stmts)
|
2020-04-05 23:00:17 +02:00
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-18 03:28:39 +01:00
|
|
|
ast.BranchStmt {
|
2020-06-18 20:07:48 +02:00
|
|
|
match node.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
|
|
|
}
|
|
|
|
}
|
2020-07-25 00:02:44 +02:00
|
|
|
ast.CompFor {
|
|
|
|
typ := f.no_cur_mod(f.table.type_to_str(it.typ))
|
|
|
|
f.writeln('\$for $it.val_var in ${typ}($it.kind.str()) {')
|
|
|
|
f.stmts(it.stmts)
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.ConstDecl {
|
2020-05-12 00:09:59 +02:00
|
|
|
f.const_decl(it)
|
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-07-17 19:13:22 +02:00
|
|
|
f.comments(it.comments, {
|
2020-07-20 16:48:33 +02:00
|
|
|
inline: true
|
2020-07-17 19:13:22 +02:00
|
|
|
level: .indent
|
|
|
|
})
|
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-07-17 19:13:22 +02:00
|
|
|
f.comments(field.comments, {
|
2020-07-20 16:48:33 +02:00
|
|
|
inline: true
|
2020-07-17 19:13:22 +02:00
|
|
|
has_nl: false
|
|
|
|
level: .indent
|
|
|
|
})
|
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 {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comments(it.comments, {})
|
2020-02-17 22:50:04 +01:00
|
|
|
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-25 17:49:16 +02:00
|
|
|
f.fn_decl(it)
|
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('; ')
|
2020-06-16 13:20:16 +02:00
|
|
|
f.stmt(it.inc)
|
2020-07-02 14:29:52 +02:00
|
|
|
f.remove_new_line()
|
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-05-01 11:25:18 +02:00
|
|
|
f.writeln('')
|
2020-04-07 18:51:39 +02:00
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
ast.GoStmt {
|
|
|
|
f.write('go ')
|
|
|
|
f.expr(it.call_expr)
|
|
|
|
f.writeln('')
|
|
|
|
}
|
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
|
|
|
}
|
2020-04-22 20:20:49 +02:00
|
|
|
ast.InterfaceDecl {
|
2020-07-14 18:52:28 +02:00
|
|
|
f.interface_decl(it)
|
2020-04-22 20:20:49 +02:00
|
|
|
}
|
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 {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comments(it.comments, {})
|
2020-02-17 22:50:04 +01:00
|
|
|
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('')
|
|
|
|
}
|
2020-06-28 12:36:08 +02:00
|
|
|
ast.SqlStmt {
|
|
|
|
f.write('sql ')
|
|
|
|
f.expr(it.db_expr)
|
|
|
|
f.writeln(' {')
|
|
|
|
match it.kind as k {
|
|
|
|
.insert {
|
2020-07-01 00:53:53 +02:00
|
|
|
f.writeln('\tinsert $it.object_var_name into ${util.strip_mod_name(it.table_name)}')
|
2020-06-28 12:36:08 +02:00
|
|
|
}
|
|
|
|
.update {
|
2020-07-01 00:53:53 +02:00
|
|
|
f.write('\tupdate ${util.strip_mod_name(it.table_name)} set ')
|
2020-06-28 12:36:08 +02:00
|
|
|
for i, col in it.updated_columns {
|
|
|
|
f.write('$col = ')
|
|
|
|
f.expr(it.update_exprs[i])
|
|
|
|
if i < it.updated_columns.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
} else {
|
|
|
|
f.write(' ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write('where ')
|
|
|
|
f.expr(it.where_expr)
|
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
.delete {
|
|
|
|
// TODO delete
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.writeln('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
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-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
|
2020-03-07 17:37:55 +01:00
|
|
|
match node {
|
|
|
|
ast.AliasTypeDecl {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.is_pub {
|
2020-03-07 17:37:55 +01:00
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
ptype := f.type_to_str(node.parent_type)
|
|
|
|
f.write('type $node.name $ptype')
|
2020-03-07 17:37:55 +01:00
|
|
|
}
|
2020-04-25 20:58:00 +02:00
|
|
|
ast.FnTypeDecl {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.is_pub {
|
2020-04-25 20:58:00 +02:00
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
typ_sym := f.table.get_type_symbol(node.typ)
|
2020-04-25 20:58:00 +02:00
|
|
|
fn_typ_info := typ_sym.info as table.FnType
|
|
|
|
fn_info := fn_typ_info.func
|
2020-07-11 15:09:12 +02:00
|
|
|
fn_name := f.no_cur_mod(node.name)
|
2020-04-25 20:58:00 +02:00
|
|
|
f.write('type $fn_name = fn (')
|
|
|
|
for i, arg in fn_info.args {
|
2020-08-04 15:08:47 +02:00
|
|
|
if arg.is_mut {
|
|
|
|
f.write(arg.typ.share().str() + ' ')
|
|
|
|
}
|
2020-04-25 20:58:00 +02:00
|
|
|
f.write(arg.name)
|
2020-07-11 01:42:57 +02:00
|
|
|
mut s := f.no_cur_mod(f.table.type_to_str(arg.typ))
|
2020-04-25 20:58:00 +02:00
|
|
|
if arg.is_mut {
|
|
|
|
if s.starts_with('&') {
|
|
|
|
s = s[1..]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is_last_arg := i == fn_info.args.len - 1
|
2020-06-24 14:35:00 +02:00
|
|
|
should_add_type := is_last_arg || fn_info.args[i + 1].typ != arg.typ ||
|
|
|
|
(fn_info.is_variadic && i == fn_info.args.len - 2)
|
2020-04-25 20:58:00 +02:00
|
|
|
if should_add_type {
|
|
|
|
if fn_info.is_variadic && is_last_arg {
|
|
|
|
f.write(' ...' + s)
|
|
|
|
} else {
|
|
|
|
f.write(' ' + s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !is_last_arg {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write(')')
|
|
|
|
if fn_info.return_type.idx() != table.void_type_idx {
|
2020-07-11 01:42:57 +02:00
|
|
|
ret_str := f.no_cur_mod(f.table.type_to_str(fn_info.return_type))
|
2020-08-03 18:28:48 +02:00
|
|
|
f.write(' $ret_str')
|
|
|
|
} else if fn_info.return_type.has_flag(.optional) {
|
|
|
|
f.write(' ?')
|
2020-04-25 20:58:00 +02:00
|
|
|
}
|
|
|
|
}
|
2020-03-07 17:37:55 +01:00
|
|
|
ast.SumTypeDecl {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.is_pub {
|
2020-03-07 17:37:55 +01:00
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write('type $node.name = ')
|
2020-04-26 09:17:13 +02:00
|
|
|
mut sum_type_names := []string{}
|
2020-06-18 20:07:48 +02:00
|
|
|
for t in node.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-04-25 20:58:00 +02:00
|
|
|
sum_type_names.sort()
|
2020-05-18 18:08:28 +02:00
|
|
|
for i, name in sum_type_names {
|
|
|
|
f.write(name)
|
|
|
|
if i < sum_type_names.len - 1 {
|
|
|
|
f.write(' | ')
|
|
|
|
}
|
2020-06-19 19:54:26 +02:00
|
|
|
f.wrap_long_line(2, true)
|
2020-05-18 18:08:28 +02:00
|
|
|
}
|
|
|
|
// f.write(sum_type_names.join(' | '))
|
2020-03-07 17:37:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
f.writeln('\n')
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
2020-08-04 20:10:22 +02:00
|
|
|
f.attrs(node.attrs)
|
2020-02-29 17:51:35 +01:00
|
|
|
if node.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
2020-06-02 07:41:02 +02:00
|
|
|
f.write('struct ')
|
|
|
|
f.write_language_prefix(node.language)
|
2020-04-05 02:08:10 +02:00
|
|
|
name := node.name.after('.')
|
2020-06-02 07:41:02 +02:00
|
|
|
f.writeln('$name {')
|
2020-04-21 05:11:50 +02:00
|
|
|
mut max := 0
|
2020-08-10 12:13:42 +02:00
|
|
|
mut max_type := 0
|
|
|
|
mut field_types := []string{cap: node.fields.len}
|
2020-02-17 22:50:04 +01:00
|
|
|
for field in node.fields {
|
2020-06-23 18:01:56 +02:00
|
|
|
end_pos := field.pos.pos + field.pos.len
|
|
|
|
mut comments_len := 0 // Length of comments between field name and type
|
|
|
|
for comment in field.comments {
|
2020-06-24 14:35:00 +02:00
|
|
|
if comment.pos.pos >= end_pos {
|
|
|
|
break
|
|
|
|
}
|
2020-06-23 18:01:56 +02:00
|
|
|
if comment.pos.pos > field.pos.pos {
|
2020-06-24 14:35:00 +02:00
|
|
|
comments_len += '/* $comment.text */ '.len
|
2020-06-23 18:01:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if comments_len + field.name.len > max {
|
|
|
|
max = comments_len + field.name.len
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-08-10 12:13:42 +02:00
|
|
|
ft := f.type_to_str(field.typ)
|
|
|
|
field_types << ft
|
|
|
|
if ft.len > max_type {
|
|
|
|
max_type = ft.len
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
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-06-23 18:01:56 +02:00
|
|
|
end_pos := field.pos.pos + field.pos.len
|
|
|
|
comments := field.comments
|
|
|
|
if comments.len == 0 {
|
|
|
|
f.write('\t$field.name ')
|
|
|
|
f.write(strings.repeat(` `, max - field.name.len))
|
2020-08-10 12:13:42 +02:00
|
|
|
f.write(field_types[i])
|
2020-08-19 14:33:42 +02:00
|
|
|
if field.attrs.len > 0 && field.attrs[0].name != 'ref_only' { // TODO a bug with [ref_only] attr being added to fields, fix it
|
2020-08-10 12:13:42 +02:00
|
|
|
f.write(strings.repeat(` `, max_type - field_types[i].len))
|
|
|
|
f.inline_attrs(field.attrs)
|
|
|
|
}
|
2020-06-23 18:01:56 +02:00
|
|
|
if field.has_default_expr {
|
|
|
|
f.write(' = ')
|
2020-07-02 14:06:29 +02:00
|
|
|
f.prefix_expr_cast_expr(field.default_expr)
|
2020-06-23 18:01:56 +02:00
|
|
|
}
|
|
|
|
f.write('\n')
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// Handle comments before field
|
|
|
|
mut j := 0
|
|
|
|
for j < comments.len && comments[j].pos.pos < field.pos.pos {
|
|
|
|
f.indent++
|
|
|
|
f.empty_line = true
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comment(comments[j], {
|
|
|
|
inline: true
|
|
|
|
})
|
2020-07-17 19:13:22 +02:00
|
|
|
f.writeln('')
|
2020-06-23 18:01:56 +02:00
|
|
|
f.indent--
|
|
|
|
j++
|
2020-04-05 02:08:10 +02:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
f.write('\t$field.name ')
|
2020-06-23 18:01:56 +02:00
|
|
|
// Handle comments between field name and type
|
|
|
|
mut comments_len := 0
|
|
|
|
for j < comments.len && comments[j].pos.pos < end_pos {
|
|
|
|
comment := '/* ${comments[j].text} */ ' // TODO: handle in a function
|
|
|
|
comments_len += comment.len
|
|
|
|
f.write(comment)
|
|
|
|
j++
|
|
|
|
}
|
|
|
|
f.write(strings.repeat(` `, max - field.name.len - comments_len))
|
2020-08-10 12:13:42 +02:00
|
|
|
f.write(field_types[i])
|
2020-08-04 20:10:22 +02:00
|
|
|
f.inline_attrs(field.attrs)
|
2020-04-12 12:35:54 +02:00
|
|
|
if field.has_default_expr {
|
2020-05-18 15:37:06 +02:00
|
|
|
f.write(' = ')
|
2020-07-02 14:06:29 +02:00
|
|
|
f.prefix_expr_cast_expr(field.default_expr)
|
2020-04-10 00:30:43 +02:00
|
|
|
}
|
2020-06-23 18:01:56 +02:00
|
|
|
// Handle comments after field type (same line)
|
2020-06-24 14:35:00 +02:00
|
|
|
for j < comments.len && field.pos.line_nr == comments[j].pos.line_nr {
|
2020-06-23 18:01:56 +02:00
|
|
|
f.write(' // ${comments[j].text}') // TODO: handle in a function
|
|
|
|
j++
|
2020-04-05 12:25:33 +02:00
|
|
|
}
|
2020-06-23 18:01:56 +02:00
|
|
|
f.write('\n')
|
|
|
|
}
|
2020-08-27 14:07:49 +02:00
|
|
|
f.comments_after_last_field(node.end_comments)
|
|
|
|
f.writeln('}\n')
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut f Fmt) comments_after_last_field(comments []ast.Comment) {
|
2020-06-24 12:54:39 +02:00
|
|
|
// Handle comments after last field
|
2020-08-27 14:07:49 +02:00
|
|
|
for comment in comments {
|
2020-06-23 18:01:56 +02:00
|
|
|
f.indent++
|
|
|
|
f.empty_line = true
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comment(comment, {
|
|
|
|
inline: true
|
|
|
|
})
|
2020-07-17 19:13:22 +02:00
|
|
|
f.writeln('')
|
2020-06-23 18:01:56 +02:00
|
|
|
f.indent--
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-14 18:52:28 +02:00
|
|
|
pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
|
|
|
|
if node.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
|
|
|
name := node.name.after('.')
|
|
|
|
f.writeln('interface $name {')
|
|
|
|
for method in node.methods {
|
|
|
|
f.write('\t')
|
|
|
|
f.writeln(method.stringify(f.table, f.cur_mod).after('fn '))
|
|
|
|
}
|
|
|
|
f.writeln('}\n')
|
|
|
|
}
|
|
|
|
|
2020-07-02 14:06:29 +02:00
|
|
|
pub fn (mut f Fmt) prefix_expr_cast_expr(fexpr ast.Expr) {
|
2020-05-30 21:29:59 +02:00
|
|
|
mut is_pe_amp_ce := false
|
|
|
|
mut ce := ast.CastExpr{}
|
|
|
|
if fexpr is ast.PrefixExpr {
|
2020-07-09 17:14:14 +02:00
|
|
|
if fexpr.right is ast.CastExpr && fexpr.op == .amp {
|
|
|
|
ce = fexpr.right as ast.CastExpr
|
2020-07-02 14:06:29 +02:00
|
|
|
ce.typname = f.table.get_type_symbol(ce.typ).name
|
2020-05-30 21:29:59 +02:00
|
|
|
is_pe_amp_ce = true
|
|
|
|
f.expr(ce)
|
|
|
|
}
|
2020-09-08 00:36:05 +02:00
|
|
|
} else if fexpr is ast.CastExpr {
|
|
|
|
last := f.out.cut_last(1)
|
|
|
|
if last != '&' {
|
|
|
|
f.out.write(last)
|
|
|
|
}
|
2020-05-30 21:29:59 +02:00
|
|
|
}
|
|
|
|
if !is_pe_amp_ce {
|
|
|
|
f.expr(fexpr)
|
2020-09-08 00:36:05 +02:00
|
|
|
if fexpr is ast.PrefixExpr {
|
|
|
|
f.or_expr(fexpr.or_block)
|
|
|
|
}
|
2020-05-30 21:29:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-19 10:36:45 +02:00
|
|
|
pub fn (f &Fmt) type_to_str(t table.Type) string {
|
2020-04-21 05:11:50 +02:00
|
|
|
mut res := f.table.type_to_str(t)
|
2020-07-10 23:59:19 +02:00
|
|
|
cur_mod := f.cur_mod + '.'
|
2020-08-28 00:54:16 +02:00
|
|
|
//
|
|
|
|
map_prefix := 'map[string]'
|
2020-07-10 23:59:19 +02:00
|
|
|
has_map_prefix := res.starts_with(map_prefix)
|
|
|
|
if has_map_prefix {
|
|
|
|
res = res.replace(map_prefix, '')
|
|
|
|
}
|
2020-08-28 00:54:16 +02:00
|
|
|
//
|
|
|
|
chan_prefix := 'chan '
|
|
|
|
has_chan_prefix := res.starts_with(chan_prefix)
|
|
|
|
if has_chan_prefix {
|
|
|
|
res = res.replace(chan_prefix, '')
|
|
|
|
}
|
|
|
|
//
|
2020-07-10 23:59:19 +02:00
|
|
|
no_symbols := res.trim_left('&[]')
|
|
|
|
should_shorten := no_symbols.starts_with(cur_mod)
|
|
|
|
//
|
2020-06-13 00:01:44 +02:00
|
|
|
for res.ends_with('_ptr') {
|
2020-05-20 21:39:59 +02:00
|
|
|
// type_ptr => &type
|
2020-04-25 17:49:16 +02:00
|
|
|
res = res[0..res.len - 4]
|
2020-04-16 07:28:41 +02:00
|
|
|
start_pos := 2 * res.count('[]')
|
2020-04-25 17:49:16 +02:00
|
|
|
res = res[0..start_pos] + '&' + res[start_pos..res.len]
|
2020-04-16 07:28:41 +02:00
|
|
|
}
|
2020-05-28 08:06:20 +02:00
|
|
|
if res.starts_with('[]fixed_') {
|
|
|
|
prefix := '[]fixed_'
|
|
|
|
res = res[prefix.len..]
|
|
|
|
last_underscore_idx := res.last_index('_') or {
|
2020-07-10 23:59:19 +02:00
|
|
|
return '[]' + if should_shorten { res.replace_once(cur_mod, '') } else { res }
|
2020-05-28 08:06:20 +02:00
|
|
|
}
|
|
|
|
limit := res[last_underscore_idx + 1..]
|
|
|
|
res = '[' + limit + ']' + res[..last_underscore_idx]
|
|
|
|
}
|
2020-07-10 23:59:19 +02:00
|
|
|
if should_shorten {
|
|
|
|
res = res.replace_once(cur_mod, '')
|
|
|
|
}
|
2020-08-28 00:54:16 +02:00
|
|
|
if has_chan_prefix {
|
|
|
|
res = chan_prefix + res
|
|
|
|
}
|
2020-07-10 23:59:19 +02:00
|
|
|
if has_map_prefix {
|
|
|
|
res = map_prefix + res
|
|
|
|
}
|
|
|
|
return res
|
2020-02-21 19:56:37 +01:00
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) expr(node ast.Expr) {
|
2020-05-04 16:22:41 +02:00
|
|
|
if f.is_debug {
|
2020-06-18 20:07:48 +02:00
|
|
|
eprintln('expr: ${node.position():-42} | node: ${typeof(node):-20} | $node.str()')
|
2020-05-04 16:22:41 +02:00
|
|
|
}
|
2020-07-24 07:43:18 +02:00
|
|
|
match mut node {
|
2020-04-25 17:49:16 +02:00
|
|
|
ast.AnonFn {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.fn_decl(node.decl)
|
2020-04-25 17:49:16 +02:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.ArrayInit {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.array_init(node)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-03-06 22:12:15 +01:00
|
|
|
ast.AsCast {
|
2020-06-18 20:07:48 +02:00
|
|
|
type_str := f.type_to_str(node.typ)
|
|
|
|
f.expr(node.expr)
|
2020-03-06 22:12:15 +01:00
|
|
|
f.write(' as $type_str')
|
|
|
|
}
|
2020-02-22 14:39:25 +01:00
|
|
|
ast.Assoc {
|
|
|
|
f.writeln('{')
|
|
|
|
// f.indent++
|
2020-06-18 20:07:48 +02:00
|
|
|
f.writeln('\t$node.var_name |')
|
2020-02-22 14:39:25 +01:00
|
|
|
// TODO StructInit copy pasta
|
2020-06-18 20:07:48 +02:00
|
|
|
for i, field in node.fields {
|
2020-04-09 15:59:19 +02:00
|
|
|
f.write('\t$field: ')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.exprs[i])
|
2020-02-22 14:39:25 +01:00
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
// f.indent--
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.BoolLiteral {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(node.val.str())
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-02-27 18:02:40 +01:00
|
|
|
ast.CastExpr {
|
2020-07-02 14:06:29 +02:00
|
|
|
node.typname = f.table.get_type_symbol(node.typ).name
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(f.type_to_str(node.typ) + '(')
|
|
|
|
f.expr(node.expr)
|
2020-07-30 11:04:55 +02:00
|
|
|
if node.has_arg {
|
|
|
|
f.write(', ')
|
|
|
|
f.expr(node.arg)
|
|
|
|
}
|
2020-02-27 18:02:40 +01:00
|
|
|
f.write(')')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.CallExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.call_expr(node)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-08-14 21:18:42 +02:00
|
|
|
ast.ChanInit {
|
2020-08-27 22:37:33 +02:00
|
|
|
f.chan_init(mut node)
|
2020-08-14 21:18:42 +02:00
|
|
|
}
|
2020-02-27 21:51:40 +01:00
|
|
|
ast.CharLiteral {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write('`$node.val`')
|
2020-02-27 21:51:40 +01:00
|
|
|
}
|
2020-07-17 19:13:22 +02:00
|
|
|
ast.Comment {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comment(node, {
|
|
|
|
inline: true
|
|
|
|
})
|
2020-07-17 19:13:22 +02:00
|
|
|
}
|
2020-06-11 20:26:46 +02:00
|
|
|
ast.ComptimeCall {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.is_vweb {
|
2020-06-11 20:26:46 +02:00
|
|
|
f.write('$' + 'vweb.html()')
|
|
|
|
}
|
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
ast.ConcatExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
for i, val in node.vals {
|
2020-04-25 17:49:16 +02:00
|
|
|
if i != 0 {
|
|
|
|
f.write(' + ')
|
|
|
|
}
|
|
|
|
f.expr(val)
|
|
|
|
}
|
|
|
|
}
|
2020-02-18 03:28:39 +01:00
|
|
|
ast.EnumVal {
|
2020-06-18 20:07:48 +02:00
|
|
|
name := f.short_module(node.enum_name)
|
|
|
|
f.write(name + '.' + node.val)
|
2020-02-18 03:28:39 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.FloatLiteral {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(node.val)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.IfExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.if_expr(node)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.Ident {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write_language_prefix(node.language)
|
|
|
|
if true {
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
if node.name == 'it' && f.it_name != '' {
|
|
|
|
f.write(f.it_name)
|
|
|
|
} else if node.kind == .blank_ident {
|
2020-02-27 21:51:40 +01:00
|
|
|
f.write('_')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else {
|
2020-06-18 20:07:48 +02:00
|
|
|
name := f.short_module(node.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
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
ast.IfGuardExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(node.var_name + ' := ')
|
|
|
|
f.expr(node.expr)
|
2020-04-25 17:49:16 +02:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.InfixExpr {
|
2020-07-19 19:58:34 +02:00
|
|
|
f.infix_expr(node)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.IndexExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.left)
|
2020-02-29 17:45:08 +01:00
|
|
|
f.write('[')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.index)
|
2020-02-29 17:45:08 +01:00
|
|
|
f.write(']')
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.IntegerLiteral {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(node.val)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-07-04 12:44:25 +02:00
|
|
|
ast.LockExpr {
|
2020-07-04 15:13:58 +02:00
|
|
|
f.lock_expr(node)
|
2020-07-04 12:44:25 +02:00
|
|
|
}
|
2020-02-22 14:13:19 +01:00
|
|
|
ast.MapInit {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.keys.len == 0 {
|
|
|
|
mut ktyp := node.key_type
|
|
|
|
mut vtyp := node.value_type
|
2020-05-27 15:26:45 +02:00
|
|
|
if vtyp == 0 {
|
2020-06-18 20:07:48 +02:00
|
|
|
typ_sym := f.table.get_type_symbol(node.typ)
|
2020-05-04 17:26:28 +02:00
|
|
|
minfo := typ_sym.info as table.Map
|
2020-05-27 15:26:45 +02:00
|
|
|
ktyp = minfo.key_type
|
|
|
|
vtyp = minfo.value_type
|
2020-04-14 18:09:59 +02:00
|
|
|
}
|
2020-05-04 17:26:28 +02:00
|
|
|
f.write('map[')
|
2020-05-27 15:26:45 +02:00
|
|
|
f.write(f.type_to_str(ktyp))
|
2020-05-04 17:26:28 +02:00
|
|
|
f.write(']')
|
2020-05-27 15:26:45 +02:00
|
|
|
f.write(f.type_to_str(vtyp))
|
|
|
|
f.write('{}')
|
2020-04-14 18:09:59 +02:00
|
|
|
return
|
|
|
|
}
|
2020-02-22 14:13:19 +01:00
|
|
|
f.writeln('{')
|
|
|
|
f.indent++
|
2020-06-18 20:07:48 +02:00
|
|
|
for i, key in node.keys {
|
2020-02-22 14:13:19 +01:00
|
|
|
f.expr(key)
|
|
|
|
// f.write(strings.repeat(` `, max - field.name.len))
|
|
|
|
f.write(': ')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.vals[i])
|
2020-02-22 14:13:19 +01:00
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
f.indent--
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-02-29 20:43:15 +01:00
|
|
|
ast.MatchExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.match_expr(node)
|
2020-02-29 20:43:15 +01:00
|
|
|
}
|
2020-02-21 17:52:20 +01:00
|
|
|
ast.None {
|
|
|
|
f.write('none')
|
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
ast.OrExpr {
|
|
|
|
// shouldn't happen, an or expression
|
|
|
|
// is always linked to a call expr
|
2020-07-31 02:31:01 +02:00
|
|
|
panic('fmt: OrExpr should be linked to CallExpr')
|
2020-02-27 18:02:40 +01:00
|
|
|
}
|
2020-02-28 15:36:41 +01:00
|
|
|
ast.ParExpr {
|
2020-02-28 14:41:19 +01:00
|
|
|
f.write('(')
|
2020-06-24 15:19:30 +02:00
|
|
|
f.par_level++
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.expr)
|
2020-06-24 15:19:30 +02:00
|
|
|
f.par_level--
|
2020-02-28 14:41:19 +01:00
|
|
|
f.write(')')
|
2020-02-28 15:36:41 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.PostfixExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.expr)
|
2020-09-18 00:58:54 +02:00
|
|
|
// `$if foo ?`
|
|
|
|
if node.op == .question {
|
|
|
|
f.write(' ?')
|
|
|
|
} else {
|
|
|
|
f.write('$node.op')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
ast.PrefixExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(node.op.str())
|
2020-07-27 12:15:29 +02:00
|
|
|
f.prefix_expr_cast_expr(node.right)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-02-29 17:45:08 +01:00
|
|
|
ast.RangeExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.low)
|
2020-02-29 17:45:08 +01:00
|
|
|
f.write('..')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.high)
|
2020-02-29 17:45:08 +01:00
|
|
|
}
|
2020-09-16 15:34:57 +02:00
|
|
|
ast.SelectExpr {
|
|
|
|
// TODO: implement this
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.SelectorExpr {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.expr)
|
2020-02-17 22:50:04 +01:00
|
|
|
f.write('.')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(node.field_name)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-07 18:51:39 +02:00
|
|
|
ast.SizeOf {
|
2020-07-01 20:07:33 +02:00
|
|
|
if node.is_type {
|
2020-07-01 00:53:53 +02:00
|
|
|
f.write('sizeof(')
|
|
|
|
if node.type_name != '' {
|
2020-07-21 15:28:30 +02:00
|
|
|
if f.is_external_name(node.type_name) {
|
|
|
|
f.write(node.type_name)
|
|
|
|
} else {
|
|
|
|
f.write(f.short_module(node.type_name))
|
|
|
|
}
|
2020-07-01 00:53:53 +02:00
|
|
|
} else {
|
|
|
|
f.write(f.type_to_str(node.typ))
|
|
|
|
}
|
|
|
|
f.write(')')
|
2020-04-07 18:51:39 +02:00
|
|
|
} else {
|
2020-07-01 00:53:53 +02:00
|
|
|
f.write('sizeof(')
|
|
|
|
f.expr(node.expr)
|
|
|
|
f.write(')')
|
2020-04-07 18:51:39 +02:00
|
|
|
}
|
|
|
|
}
|
2020-06-28 12:36:08 +02:00
|
|
|
ast.SqlExpr {
|
|
|
|
// sql app.db { select from Contributor where repo == id && user == 0 }
|
|
|
|
f.write('sql ')
|
|
|
|
f.expr(node.db_expr)
|
|
|
|
f.writeln(' {')
|
|
|
|
f.write('\t')
|
|
|
|
f.write('select ')
|
|
|
|
esym := f.table.get_type_symbol(node.table_type)
|
|
|
|
node.table_name = esym.name
|
|
|
|
if node.is_count {
|
|
|
|
f.write('count ')
|
|
|
|
} else {
|
|
|
|
if node.fields.len > 0 {
|
|
|
|
for tfi, tf in node.fields {
|
|
|
|
f.write(tf.name)
|
|
|
|
if tfi < node.fields.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write(' ')
|
|
|
|
}
|
|
|
|
}
|
2020-07-01 00:53:53 +02:00
|
|
|
f.write('from ${util.strip_mod_name(node.table_name)}')
|
2020-06-28 12:36:08 +02:00
|
|
|
if node.has_where {
|
2020-07-28 10:09:42 +02:00
|
|
|
f.write(' where ')
|
2020-06-28 12:36:08 +02:00
|
|
|
f.expr(node.where_expr)
|
|
|
|
}
|
|
|
|
if node.has_limit {
|
2020-07-28 10:09:42 +02:00
|
|
|
f.write(' limit ')
|
2020-06-28 12:36:08 +02:00
|
|
|
f.expr(node.limit_expr)
|
|
|
|
}
|
|
|
|
if node.has_offset {
|
2020-07-28 10:09:42 +02:00
|
|
|
f.write(' offset ')
|
2020-06-28 12:36:08 +02:00
|
|
|
f.expr(node.offset_expr)
|
|
|
|
}
|
|
|
|
f.writeln('')
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.StringLiteral {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.is_raw {
|
2020-05-27 03:10:47 +02:00
|
|
|
f.write('r')
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.val.contains("'") && !node.val.contains('"') {
|
|
|
|
f.write('"$node.val"')
|
2020-04-05 19:35:10 +02:00
|
|
|
} else {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write("'$node.val'")
|
2020-04-05 19:35:10 +02:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-03-24 22:18:58 +01:00
|
|
|
ast.StringInterLiteral {
|
2020-06-17 19:49:13 +02:00
|
|
|
// TODO: this code is very similar to ast.Expr.str()
|
2020-06-18 18:48:23 +02:00
|
|
|
mut contains_single_quote := false
|
2020-06-18 20:07:48 +02:00
|
|
|
for val in node.vals {
|
2020-06-18 18:48:23 +02:00
|
|
|
if val.contains("'") {
|
|
|
|
contains_single_quote = true
|
2020-06-23 23:59:58 +02:00
|
|
|
}
|
|
|
|
if val.contains('"') {
|
|
|
|
contains_single_quote = false
|
2020-06-18 18:48:23 +02:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if contains_single_quote {
|
|
|
|
f.write('"')
|
|
|
|
} else {
|
|
|
|
f.write("'")
|
|
|
|
}
|
|
|
|
f.is_inside_interp = true
|
2020-06-18 20:07:48 +02:00
|
|
|
for i, val in node.vals {
|
2020-03-24 22:18:58 +01:00
|
|
|
f.write(val)
|
2020-06-18 20:07:48 +02:00
|
|
|
if i >= node.exprs.len {
|
2020-06-17 19:49:13 +02:00
|
|
|
break
|
2020-03-24 22:18:58 +01:00
|
|
|
}
|
|
|
|
f.write('$')
|
2020-06-18 20:07:48 +02:00
|
|
|
fspec_str, needs_braces := node.get_fspec_braces(i)
|
2020-06-17 19:49:13 +02:00
|
|
|
if needs_braces {
|
2020-03-24 22:18:58 +01:00
|
|
|
f.write('{')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.exprs[i])
|
2020-06-17 19:49:13 +02:00
|
|
|
f.write(fspec_str)
|
2020-03-24 22:18:58 +01:00
|
|
|
f.write('}')
|
2020-04-05 18:03:36 +02:00
|
|
|
} else {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.exprs[i])
|
2020-03-24 22:18:58 +01:00
|
|
|
}
|
|
|
|
}
|
2020-06-18 18:48:23 +02:00
|
|
|
f.is_inside_interp = false
|
|
|
|
if contains_single_quote {
|
|
|
|
f.write('"')
|
|
|
|
} else {
|
|
|
|
f.write("'")
|
|
|
|
}
|
2020-03-24 22:18:58 +01:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
ast.StructInit {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.struct_init(node)
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
2020-04-05 02:08:10 +02:00
|
|
|
ast.Type {
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write(f.type_to_str(node.typ))
|
2020-04-05 02:08:10 +02:00
|
|
|
}
|
2020-04-03 11:59:53 +02:00
|
|
|
ast.TypeOf {
|
|
|
|
f.write('typeof(')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.expr)
|
2020-04-03 11:59:53 +02:00
|
|
|
f.write(')')
|
|
|
|
}
|
2020-06-09 16:36:18 +02:00
|
|
|
ast.Likely {
|
2020-06-18 20:07:48 +02:00
|
|
|
if node.is_likely {
|
2020-06-09 17:08:31 +02:00
|
|
|
f.write('_likely_')
|
|
|
|
} else {
|
|
|
|
f.write('_unlikely_')
|
|
|
|
}
|
|
|
|
f.write('(')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.expr(node.expr)
|
2020-06-09 16:36:18 +02:00
|
|
|
f.write(')')
|
|
|
|
}
|
2020-07-12 12:58:33 +02:00
|
|
|
ast.UnsafeExpr {
|
2020-08-04 00:29:10 +02:00
|
|
|
f.write('unsafe {')
|
2020-09-19 18:18:36 +02:00
|
|
|
f.expr(node.expr)
|
2020-08-04 00:29:10 +02:00
|
|
|
f.write('}')
|
2020-07-12 12:58:33 +02:00
|
|
|
}
|
2020-02-17 22:50:04 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-22 02:34:37 +01:00
|
|
|
|
2020-06-19 19:54:26 +02:00
|
|
|
pub fn (mut f Fmt) wrap_long_line(penalty int, add_indent bool) bool {
|
|
|
|
if f.line_len <= max_len[penalty] {
|
2020-04-25 17:49:16 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
if f.out.buf[f.out.buf.len - 1] == ` ` {
|
|
|
|
f.out.go_back(1)
|
2020-02-21 16:14:15 +01:00
|
|
|
}
|
2020-06-24 14:35:00 +02:00
|
|
|
f.write('\n' + tabs[f.indent + if add_indent {
|
|
|
|
1
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}])
|
2020-04-25 17:49:16 +02:00
|
|
|
f.line_len = 0
|
|
|
|
return true
|
2020-02-21 16:14:15 +01:00
|
|
|
}
|
2020-03-02 17:09:45 +01:00
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut 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-07-09 22:41:45 +02:00
|
|
|
f.write(arg.share.str() + ' ')
|
2020-03-02 17:09:45 +01:00
|
|
|
}
|
|
|
|
if i > 0 {
|
2020-06-19 19:54:26 +02:00
|
|
|
f.wrap_long_line(2, true)
|
2020-03-02 17:09:45 +01:00
|
|
|
}
|
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 {
|
2020-06-18 18:48:23 +02:00
|
|
|
if f.is_inside_interp {
|
|
|
|
f.write(',')
|
|
|
|
} else {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
2020-03-02 17:09:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) or_expr(or_block ast.OrExpr) {
|
2020-05-23 08:51:15 +02:00
|
|
|
match or_block.kind {
|
|
|
|
.absent {}
|
|
|
|
.block {
|
2020-07-04 13:11:34 +02:00
|
|
|
if or_block.stmts.len == 0 {
|
|
|
|
f.write(' or { }')
|
|
|
|
} else {
|
|
|
|
f.writeln(' or {')
|
|
|
|
f.stmts(or_block.stmts)
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-05-23 08:51:15 +02:00
|
|
|
}
|
|
|
|
.propagate {
|
2020-08-29 01:56:43 +02:00
|
|
|
f.write(' ?')
|
2020-05-23 08:51:15 +02:00
|
|
|
}
|
2020-03-02 17:09:45 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-05 02:08:10 +02:00
|
|
|
|
2020-08-04 20:10:22 +02:00
|
|
|
fn (mut f Fmt) attrs(attrs []table.Attr) {
|
|
|
|
for attr in attrs {
|
2020-08-10 02:00:14 +02:00
|
|
|
f.writeln('[$attr]')
|
2020-08-04 20:10:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (mut f Fmt) inline_attrs(attrs []table.Attr) {
|
|
|
|
if attrs.len == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
f.write(' [')
|
|
|
|
for i, attr in attrs {
|
|
|
|
if i > 0 {
|
2020-08-10 12:13:42 +02:00
|
|
|
f.write('; ')
|
2020-08-04 20:10:22 +02:00
|
|
|
}
|
2020-08-10 02:00:14 +02:00
|
|
|
f.write('$attr')
|
2020-08-04 20:10:22 +02:00
|
|
|
}
|
|
|
|
f.write(']')
|
|
|
|
}
|
|
|
|
|
2020-07-17 19:13:22 +02:00
|
|
|
enum CommentsLevel {
|
|
|
|
keep
|
|
|
|
indent
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CommentsOptions {
|
|
|
|
has_nl bool = true
|
2020-07-20 16:48:33 +02:00
|
|
|
inline bool
|
2020-07-17 19:13:22 +02:00
|
|
|
level CommentsLevel = .keep
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (mut f Fmt) comment(node ast.Comment, options CommentsOptions) {
|
2020-04-05 02:08:10 +02:00
|
|
|
if !node.text.contains('\n') {
|
2020-07-17 19:13:22 +02:00
|
|
|
is_separate_line := !options.inline || node.text.starts_with('|')
|
|
|
|
mut s := if node.text.starts_with('|') { 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
|
|
|
|
}
|
2020-07-02 14:21:09 +02:00
|
|
|
if !is_separate_line && f.indent > 0 {
|
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-07-17 19:13:22 +02:00
|
|
|
f.write(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
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
f.empty_line = true
|
2020-07-17 19:13:22 +02:00
|
|
|
f.write('*/')
|
2020-04-05 02:08:10 +02:00
|
|
|
}
|
2020-04-05 03:37:38 +02:00
|
|
|
|
2020-07-17 19:13:22 +02:00
|
|
|
pub fn (mut f Fmt) comments(comments []ast.Comment, options CommentsOptions) {
|
|
|
|
for i, c in comments {
|
2020-07-02 15:44:03 +02:00
|
|
|
if !f.out.last_n(1)[0].is_space() {
|
|
|
|
f.write('\t')
|
|
|
|
}
|
2020-07-17 19:13:22 +02:00
|
|
|
if options.level == .indent {
|
2020-07-03 16:16:20 +02:00
|
|
|
f.indent++
|
|
|
|
}
|
2020-07-17 19:13:22 +02:00
|
|
|
f.comment(c, options)
|
|
|
|
if i < comments.len - 1 || options.has_nl {
|
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
if options.level == .indent {
|
2020-07-03 16:16:20 +02:00
|
|
|
f.indent--
|
|
|
|
}
|
2020-07-02 16:39:56 +02:00
|
|
|
}
|
2020-07-02 15:44:03 +02:00
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) fn_decl(node ast.FnDecl) {
|
2020-04-25 17:49:16 +02:00
|
|
|
// println('$it.name find_comment($it.pos.line_nr)')
|
|
|
|
// f.find_comment(it.pos.line_nr)
|
2020-08-04 20:10:22 +02:00
|
|
|
f.attrs(node.attrs)
|
2020-07-11 15:09:12 +02:00
|
|
|
f.write(node.stringify(f.table, f.cur_mod)) // `Expr` instead of `ast.Expr` in mod ast
|
2020-05-19 17:12:47 +02:00
|
|
|
if node.language == .v {
|
2020-04-25 17:49:16 +02:00
|
|
|
f.writeln(' {')
|
|
|
|
f.stmts(node.stmts)
|
|
|
|
f.write('}')
|
|
|
|
if !node.is_anon {
|
|
|
|
f.writeln('\n')
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
f.writeln('\n')
|
|
|
|
}
|
|
|
|
// Mark all function's used type so that they are not removed from imports
|
|
|
|
for arg in node.args {
|
|
|
|
f.mark_types_module_as_used(arg.typ)
|
|
|
|
}
|
|
|
|
f.mark_types_module_as_used(node.return_type)
|
|
|
|
}
|
|
|
|
|
2020-07-11 01:42:57 +02:00
|
|
|
pub fn (mut f Fmt) no_cur_mod(typename string) string {
|
2020-07-11 15:09:12 +02:00
|
|
|
return util.no_cur_mod(typename, f.cur_mod)
|
2020-07-11 01:42:57 +02:00
|
|
|
}
|
|
|
|
|
2020-04-05 03:37:38 +02:00
|
|
|
// foo.bar.fn() => bar.fn()
|
2020-05-22 21:18:56 +02:00
|
|
|
pub fn (mut f Fmt) short_module(name string) string {
|
2020-04-05 03:37:38 +02:00
|
|
|
if !name.contains('.') {
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
vals := name.split('.')
|
|
|
|
if vals.len < 2 {
|
|
|
|
return name
|
|
|
|
}
|
2020-05-22 21:18:56 +02:00
|
|
|
mname := vals[vals.len - 2]
|
|
|
|
symname := vals[vals.len - 1]
|
|
|
|
aname := f.mod2alias[mname]
|
2020-05-23 10:56:06 +02:00
|
|
|
if aname == '' {
|
|
|
|
return symname
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
return '${aname}.$symname'
|
2020-04-05 18:03:36 +02:00
|
|
|
}
|
|
|
|
|
2020-07-04 12:44:25 +02:00
|
|
|
pub fn (mut f Fmt) lock_expr(lex ast.LockExpr) {
|
2020-07-09 22:41:45 +02:00
|
|
|
f.write(if lex.is_rlock {
|
|
|
|
'rlock '
|
|
|
|
} else {
|
|
|
|
'lock '
|
|
|
|
})
|
2020-07-04 12:44:25 +02:00
|
|
|
for i, v in lex.lockeds {
|
|
|
|
if i > 0 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
f.expr(v)
|
|
|
|
}
|
|
|
|
f.write(' {')
|
|
|
|
f.writeln('')
|
|
|
|
f.stmts(lex.stmts)
|
|
|
|
f.write('}')
|
|
|
|
}
|
|
|
|
|
2020-07-19 19:58:34 +02:00
|
|
|
pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
|
|
|
|
if f.is_inside_interp {
|
|
|
|
f.expr(node.left)
|
|
|
|
f.write('$node.op.str()')
|
|
|
|
f.expr(node.right)
|
|
|
|
} else {
|
|
|
|
buffering_save := f.buffering
|
|
|
|
if !f.buffering {
|
|
|
|
f.out_save = f.out
|
|
|
|
f.out = strings.new_builder(60)
|
|
|
|
f.buffering = true
|
|
|
|
}
|
|
|
|
f.expr(node.left)
|
|
|
|
is_one_val_array_init := node.op in [.key_in, .not_in] &&
|
|
|
|
node.right is ast.ArrayInit && (node.right as ast.ArrayInit).exprs.len == 1
|
|
|
|
if is_one_val_array_init {
|
|
|
|
// `var in [val]` => `var == val`
|
|
|
|
f.write(if node.op == .key_in {
|
|
|
|
' == '
|
|
|
|
} else {
|
|
|
|
' != '
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
f.write(' $node.op.str() ')
|
|
|
|
}
|
|
|
|
f.expr_bufs << f.out.str()
|
|
|
|
mut penalty := 3
|
2020-07-23 00:32:34 +02:00
|
|
|
match node.left as left {
|
|
|
|
ast.InfixExpr {
|
|
|
|
if int(token.precedences[left.op]) > int(token.precedences[node.op]) {
|
|
|
|
penalty--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast.ParExpr {
|
|
|
|
penalty = 1
|
|
|
|
}
|
|
|
|
else {}
|
2020-07-19 19:58:34 +02:00
|
|
|
}
|
2020-07-23 00:32:34 +02:00
|
|
|
match node.right as right {
|
2020-07-27 12:15:29 +02:00
|
|
|
ast.InfixExpr { penalty-- }
|
|
|
|
ast.ParExpr { penalty = 1 }
|
2020-07-23 00:32:34 +02:00
|
|
|
else {}
|
2020-07-19 19:58:34 +02:00
|
|
|
}
|
|
|
|
f.penalties << penalty
|
|
|
|
// combine parentheses level with operator precedence to form effective precedence
|
|
|
|
f.precedences << int(token.precedences[node.op]) | (f.par_level << 16)
|
|
|
|
f.out = strings.new_builder(60)
|
|
|
|
f.buffering = true
|
|
|
|
if is_one_val_array_init {
|
|
|
|
// `var in [val]` => `var == val`
|
|
|
|
f.expr((node.right as ast.ArrayInit).exprs[0])
|
|
|
|
} else {
|
|
|
|
f.expr(node.right)
|
|
|
|
}
|
|
|
|
if !buffering_save && f.buffering { // now decide if and where to break
|
|
|
|
f.expr_bufs << f.out.str()
|
|
|
|
f.out = f.out_save
|
|
|
|
f.buffering = false
|
|
|
|
f.adjust_complete_line()
|
|
|
|
for i, p in f.penalties {
|
|
|
|
f.write(f.expr_bufs[i])
|
|
|
|
f.wrap_long_line(p, true)
|
|
|
|
}
|
|
|
|
f.write(f.expr_bufs[f.expr_bufs.len - 1])
|
|
|
|
f.expr_bufs = []string{}
|
|
|
|
f.penalties = []int{}
|
|
|
|
f.precedences = []int{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
2020-09-18 00:58:54 +02:00
|
|
|
dollar := if it.is_comptime { '$' } else { '' }
|
2020-07-27 12:15:29 +02:00
|
|
|
single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == 1 &&
|
|
|
|
it.branches[1].stmts.len == 1 &&
|
2020-06-24 14:35:00 +02:00
|
|
|
(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-08-03 17:16:06 +02:00
|
|
|
// Check `sum is T` smartcast
|
|
|
|
mut smartcast_as := false
|
|
|
|
if branch.cond is ast.InfixExpr as infix {
|
|
|
|
if infix.op == .key_is {
|
|
|
|
// left_as_name is either empty, infix.left.str() or the `as` name
|
|
|
|
smartcast_as = branch.left_as_name.len > 0 &&
|
|
|
|
infix.left.str() != branch.left_as_name
|
2020-07-22 18:10:31 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
if i == 0 {
|
2020-08-22 00:00:02 +02:00
|
|
|
// first `if`
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comments(branch.comments, {})
|
2020-08-22 00:00:02 +02:00
|
|
|
} else {
|
|
|
|
// `else`, close previous branch
|
2020-07-20 16:48:33 +02:00
|
|
|
if branch.comments.len > 0 {
|
|
|
|
f.writeln('}')
|
|
|
|
f.comments(branch.comments, {})
|
|
|
|
} else {
|
|
|
|
f.write('} ')
|
|
|
|
}
|
2020-09-18 00:58:54 +02:00
|
|
|
f.write('${dollar}else ')
|
2020-08-22 00:00:02 +02:00
|
|
|
}
|
|
|
|
if i < it.branches.len - 1 || !it.has_else {
|
2020-09-18 00:58:54 +02:00
|
|
|
f.write('${dollar}if ')
|
2020-08-22 00:00:02 +02:00
|
|
|
if branch.mut_name {
|
|
|
|
f.write('mut ')
|
|
|
|
}
|
2020-04-05 18:03:36 +02:00
|
|
|
f.expr(branch.cond)
|
2020-08-03 17:16:06 +02:00
|
|
|
if smartcast_as {
|
2020-07-22 18:10:31 +02:00
|
|
|
f.write(' as $branch.left_as_name')
|
|
|
|
}
|
2020-08-22 00:00:02 +02:00
|
|
|
f.write(' ')
|
2020-04-05 18:03:36 +02:00
|
|
|
}
|
2020-08-22 00:00:02 +02:00
|
|
|
f.write('{')
|
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-07-20 16:48:33 +02:00
|
|
|
if it.post_comments.len > 0 {
|
|
|
|
f.writeln('')
|
|
|
|
f.comments(it.post_comments, {
|
|
|
|
has_nl: false
|
|
|
|
})
|
|
|
|
}
|
2020-04-05 03:37:38 +02:00
|
|
|
}
|
2020-04-12 17:45:04 +02:00
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
2020-05-24 04:43:00 +02:00
|
|
|
/*
|
|
|
|
if node.args.len == 1 && node.expected_arg_types.len == 1 && node.args[0].expr is ast.StructInit &&
|
|
|
|
node.args[0].typ == node.expected_arg_types[0] {
|
|
|
|
// struct_init := node.args[0].expr as ast.StructInit
|
|
|
|
// if struct_init.typ == node.args[0].typ {
|
|
|
|
f.use_short_fn_args = true
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
*/
|
2020-07-20 16:48:33 +02:00
|
|
|
for arg in node.args {
|
|
|
|
f.comments(arg.comments, {})
|
|
|
|
}
|
2020-04-12 17:45:04 +02:00
|
|
|
if node.is_method {
|
2020-06-06 16:05:16 +02:00
|
|
|
/*
|
|
|
|
// x.foo!() experiment
|
|
|
|
mut is_mut := false
|
|
|
|
if node.left is ast.Ident {
|
|
|
|
scope := f.file.scope.innermost(node.pos.pos)
|
|
|
|
x := node.left as ast.Ident
|
|
|
|
var := scope.find_var(x.name) or {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
println(var.typ)
|
|
|
|
if var.typ != 0 {
|
|
|
|
sym := f.table.get_type_symbol(var.typ)
|
|
|
|
if method := f.table.type_find_method(sym, node.name) {
|
|
|
|
is_mut = method.args[0].is_mut
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2020-04-25 17:49:16 +02:00
|
|
|
if node.left is ast.Ident {
|
2020-07-09 17:14:14 +02:00
|
|
|
left := node.left as ast.Ident
|
2020-04-25 17:49:16 +02:00
|
|
|
// `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-07-09 17:14:14 +02:00
|
|
|
if left.name in ['time', 'os', 'strings', 'math', 'json', 'base64'] {
|
|
|
|
if left.name !in f.auto_imports {
|
|
|
|
f.auto_imports << left.name
|
2020-04-25 17:49:16 +02:00
|
|
|
f.file.imports << ast.Import{
|
2020-07-09 17:14:14 +02:00
|
|
|
mod: left.name
|
|
|
|
alias: left.name
|
2020-04-12 17:45:04 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
// for imp in f.file.imports {
|
|
|
|
// println(imp.mod)
|
|
|
|
// }
|
2020-04-12 17:45:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
f.expr(node.left)
|
|
|
|
f.write('.' + node.name + '(')
|
|
|
|
f.call_args(node.args)
|
|
|
|
f.write(')')
|
2020-06-06 16:52:41 +02:00
|
|
|
// if is_mut {
|
|
|
|
// f.write('!')
|
|
|
|
// }
|
2020-04-12 17:45:04 +02:00
|
|
|
f.or_expr(node.or_block)
|
|
|
|
} else {
|
2020-05-28 08:06:20 +02:00
|
|
|
f.write_language_prefix(node.language)
|
2020-08-13 20:05:59 +02:00
|
|
|
if node.left is ast.AnonFn as anon_fn {
|
|
|
|
f.fn_decl(anon_fn.decl)
|
|
|
|
} else {
|
|
|
|
mut name := f.short_module(node.name)
|
|
|
|
f.mark_module_as_used(name)
|
|
|
|
if node.name in f.mod2alias {
|
|
|
|
name = f.mod2alias[node.name]
|
|
|
|
}
|
|
|
|
f.write('$name')
|
2020-07-18 21:34:38 +02:00
|
|
|
}
|
2020-05-21 18:36:25 +02:00
|
|
|
if node.generic_type != 0 && node.generic_type != table.void_type {
|
|
|
|
f.write('<')
|
|
|
|
f.write(f.type_to_str(node.generic_type))
|
|
|
|
f.write('>')
|
|
|
|
}
|
|
|
|
f.write('(')
|
2020-04-12 17:45:04 +02:00
|
|
|
f.call_args(node.args)
|
|
|
|
f.write(')')
|
|
|
|
f.or_expr(node.or_block)
|
|
|
|
}
|
2020-05-24 04:43:00 +02:00
|
|
|
f.use_short_fn_args = false
|
2020-04-12 17:45:04 +02:00
|
|
|
}
|
2020-04-13 15:05:51 +02:00
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
2020-04-17 20:51:16 +02:00
|
|
|
f.write('match ')
|
|
|
|
if it.is_mut {
|
2020-04-21 05:11:50 +02:00
|
|
|
f.write('mut ')
|
2020-04-17 20:51:16 +02:00
|
|
|
}
|
|
|
|
f.expr(it.cond)
|
2020-06-18 20:07:48 +02:00
|
|
|
if it.cond is ast.Ident {
|
|
|
|
ident := it.cond as ast.Ident
|
|
|
|
f.it_name = ident.name
|
2020-06-19 11:46:08 +02:00
|
|
|
} else if it.cond is ast.SelectorExpr {
|
|
|
|
// `x.y as z`
|
|
|
|
// if ident.name != it.var_name && it.var_name != '' {
|
2020-07-04 15:46:46 +02:00
|
|
|
}
|
|
|
|
if it.var_name != '' && f.it_name != it.var_name {
|
|
|
|
f.write(' as $it.var_name')
|
2020-06-18 20:07:48 +02:00
|
|
|
}
|
2020-04-17 20:51:16 +02:00
|
|
|
f.writeln(' {')
|
|
|
|
f.indent++
|
2020-04-21 05:11:50 +02:00
|
|
|
mut single_line := true
|
2020-04-28 15:04:37 +02:00
|
|
|
for branch in it.branches {
|
2020-04-17 20:51:16 +02:00
|
|
|
if branch.stmts.len > 1 {
|
|
|
|
single_line = false
|
|
|
|
break
|
|
|
|
}
|
2020-04-21 04:51:50 +02:00
|
|
|
if branch.stmts.len == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
stmt := branch.stmts[0]
|
|
|
|
if stmt is ast.ExprStmt {
|
|
|
|
// If expressions inside match branches can't be one a single line
|
2020-07-09 17:14:14 +02:00
|
|
|
if !expr_is_single_line(stmt.expr) {
|
2020-04-21 04:51:50 +02:00
|
|
|
single_line = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 20:51:16 +02:00
|
|
|
}
|
2020-04-28 15:04:37 +02:00
|
|
|
for branch in it.branches {
|
2020-04-17 20:51:16 +02:00
|
|
|
if branch.comment.text != '' {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comment(branch.comment, {
|
|
|
|
inline: true
|
|
|
|
})
|
2020-07-17 19:13:22 +02:00
|
|
|
f.writeln('')
|
2020-04-17 20:51:16 +02:00
|
|
|
}
|
|
|
|
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('}')
|
|
|
|
}
|
|
|
|
}
|
2020-07-03 16:16:20 +02:00
|
|
|
if branch.post_comments.len > 0 {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comments(branch.post_comments, {
|
|
|
|
inline: true
|
|
|
|
})
|
2020-07-03 16:16:20 +02:00
|
|
|
}
|
2020-04-17 20:51:16 +02:00
|
|
|
}
|
|
|
|
f.indent--
|
|
|
|
f.write('}')
|
2020-06-18 20:07:48 +02:00
|
|
|
f.it_name = ''
|
2020-04-17 20:51:16 +02:00
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) remove_new_line() {
|
2020-04-21 05:11:50 +02:00
|
|
|
mut i := 0
|
2020-07-04 23:38:12 +02:00
|
|
|
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')
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut 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-05-19 13:19:37 +02:00
|
|
|
pub fn (mut 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')
|
|
|
|
}
|
2020-04-21 04:51:50 +02:00
|
|
|
|
2020-05-28 08:06:20 +02:00
|
|
|
fn (mut f Fmt) write_language_prefix(lang table.Language) {
|
|
|
|
match lang {
|
2020-06-06 12:43:35 +02:00
|
|
|
.c { f.write('C.') }
|
|
|
|
.js { f.write('JS.') }
|
2020-05-28 08:06:20 +02:00
|
|
|
else {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-21 04:51:50 +02:00
|
|
|
fn expr_is_single_line(expr ast.Expr) bool {
|
|
|
|
match expr {
|
|
|
|
ast.IfExpr { return false }
|
2020-07-17 19:13:22 +02:00
|
|
|
ast.Comment { return false }
|
2020-04-21 04:51:50 +02:00
|
|
|
else {}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2020-04-26 07:16:58 +02:00
|
|
|
|
2020-08-27 22:37:33 +02:00
|
|
|
pub fn (mut f Fmt) chan_init(mut it ast.ChanInit) {
|
2020-09-08 00:36:05 +02:00
|
|
|
info := f.table.get_type_symbol(it.typ).chan_info()
|
2020-08-27 22:37:33 +02:00
|
|
|
if it.elem_type == 0 && it.typ > 0 {
|
|
|
|
it.elem_type = info.elem_type
|
|
|
|
}
|
2020-09-08 00:36:05 +02:00
|
|
|
is_mut := info.is_mut
|
|
|
|
el_typ := if is_mut { it.elem_type.set_nr_muls(it.elem_type.nr_muls() - 1) } else { it.elem_type }
|
2020-08-27 22:37:33 +02:00
|
|
|
f.write('chan ')
|
2020-09-08 00:36:05 +02:00
|
|
|
if is_mut {
|
|
|
|
f.write('mut ')
|
|
|
|
}
|
|
|
|
f.write(f.type_to_str(el_typ))
|
2020-08-27 22:37:33 +02:00
|
|
|
f.write('{')
|
|
|
|
if it.has_cap {
|
|
|
|
f.write('cap: ')
|
|
|
|
f.expr(it.cap_expr)
|
|
|
|
}
|
|
|
|
f.write('}')
|
|
|
|
}
|
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
|
2020-04-26 07:16:58 +02:00
|
|
|
if it.exprs.len == 0 && it.typ != 0 && it.typ != table.void_type {
|
|
|
|
// `x := []string`
|
2020-05-04 17:26:28 +02:00
|
|
|
typ_sym := f.table.get_type_symbol(it.typ)
|
|
|
|
if typ_sym.kind == .array && typ_sym.name.starts_with('array_map') {
|
|
|
|
ainfo := typ_sym.info as table.Array
|
2020-05-05 15:06:51 +02:00
|
|
|
map_typ_sym := f.table.get_type_symbol(ainfo.elem_type)
|
2020-05-04 17:26:28 +02:00
|
|
|
minfo := map_typ_sym.info as table.Map
|
|
|
|
mk := f.table.get_type_symbol(minfo.key_type).name
|
|
|
|
mv := f.table.get_type_symbol(minfo.value_type).name
|
2020-05-05 15:06:51 +02:00
|
|
|
for _ in 0 .. ainfo.nr_dims {
|
2020-05-04 17:26:28 +02:00
|
|
|
f.write('[]')
|
|
|
|
}
|
2020-06-18 20:07:48 +02:00
|
|
|
f.write('map[$mk]$mv')
|
2020-05-04 17:26:28 +02:00
|
|
|
f.write('{')
|
2020-05-13 16:11:52 +02:00
|
|
|
if it.has_len {
|
|
|
|
f.write('len: ')
|
|
|
|
f.expr(it.len_expr)
|
|
|
|
}
|
2020-05-04 17:26:28 +02:00
|
|
|
if it.has_cap {
|
|
|
|
f.write('cap: ')
|
|
|
|
f.expr(it.cap_expr)
|
|
|
|
}
|
2020-05-13 16:11:52 +02:00
|
|
|
if it.has_default {
|
2020-05-13 22:00:24 +02:00
|
|
|
f.write('init: ')
|
2020-05-13 16:11:52 +02:00
|
|
|
f.expr(it.default_expr)
|
|
|
|
}
|
2020-05-04 17:26:28 +02:00
|
|
|
f.write('}')
|
|
|
|
return
|
|
|
|
}
|
2020-04-26 07:16:58 +02:00
|
|
|
f.write(f.type_to_str(it.typ))
|
2020-04-29 12:20:22 +02:00
|
|
|
f.write('{')
|
2020-05-13 16:11:52 +02:00
|
|
|
// TODO copypasta
|
|
|
|
if it.has_len {
|
|
|
|
f.write('len: ')
|
|
|
|
f.expr(it.len_expr)
|
|
|
|
if it.has_cap || it.has_default {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
2020-04-29 12:20:22 +02:00
|
|
|
if it.has_cap {
|
|
|
|
f.write('cap: ')
|
|
|
|
f.expr(it.cap_expr)
|
2020-05-13 16:11:52 +02:00
|
|
|
if it.has_default {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if it.has_default {
|
2020-05-13 22:00:24 +02:00
|
|
|
f.write('init: ')
|
2020-05-13 16:11:52 +02:00
|
|
|
f.expr(it.default_expr)
|
2020-04-29 12:20:22 +02:00
|
|
|
}
|
|
|
|
f.write('}')
|
2020-04-26 07:16:58 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
// `[1,2,3]`
|
|
|
|
// type_sym := f.table.get_type_symbol(it.typ)
|
|
|
|
f.write('[')
|
|
|
|
mut inc_indent := false
|
|
|
|
mut last_line_nr := it.pos.line_nr // to have the same newlines between array elements
|
2020-07-09 22:36:49 +02:00
|
|
|
f.array_init_depth++
|
2020-04-26 07:16:58 +02:00
|
|
|
for i, expr in it.exprs {
|
|
|
|
line_nr := expr.position().line_nr
|
2020-07-09 22:36:49 +02:00
|
|
|
if i == 0 {
|
|
|
|
if f.array_init_depth > f.array_init_break.len {
|
|
|
|
f.array_init_break << (last_line_nr < line_nr)
|
|
|
|
}
|
2020-07-09 19:47:12 +02:00
|
|
|
}
|
2020-07-09 22:36:49 +02:00
|
|
|
mut penalty := if f.array_init_break[f.array_init_depth - 1] { 0 } else { 3 }
|
2020-07-09 19:47:12 +02:00
|
|
|
if penalty > 0 {
|
2020-07-27 12:15:29 +02:00
|
|
|
if i == 0 || it.exprs[i - 1] is ast.ArrayInit || it.exprs[i - 1] is ast.StructInit ||
|
2020-07-09 19:47:12 +02:00
|
|
|
it.exprs[i - 1] is ast.MapInit || it.exprs[i - 1] is ast.CallExpr {
|
|
|
|
penalty--
|
|
|
|
}
|
|
|
|
if expr is ast.ArrayInit ||
|
2020-07-27 12:15:29 +02:00
|
|
|
expr is ast.StructInit || expr is ast.MapInit || expr is ast.CallExpr {
|
2020-07-09 19:47:12 +02:00
|
|
|
penalty--
|
|
|
|
}
|
2020-06-19 19:54:26 +02:00
|
|
|
}
|
|
|
|
is_new_line := f.wrap_long_line(penalty, !inc_indent)
|
|
|
|
if is_new_line && !inc_indent {
|
|
|
|
f.indent++
|
|
|
|
inc_indent = true
|
2020-04-26 07:16:58 +02:00
|
|
|
}
|
|
|
|
if !is_new_line && i > 0 {
|
|
|
|
f.write(' ')
|
|
|
|
}
|
|
|
|
f.expr(expr)
|
|
|
|
if i == it.exprs.len - 1 {
|
|
|
|
if is_new_line {
|
2020-07-17 19:13:22 +02:00
|
|
|
if expr !is ast.Comment {
|
|
|
|
f.write(',')
|
|
|
|
}
|
2020-04-26 07:16:58 +02:00
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-07-17 19:13:22 +02:00
|
|
|
} else if expr !is ast.Comment {
|
2020-04-26 07:16:58 +02:00
|
|
|
f.write(',')
|
|
|
|
}
|
|
|
|
last_line_nr = line_nr
|
|
|
|
}
|
2020-07-09 22:36:49 +02:00
|
|
|
f.array_init_depth--
|
|
|
|
if f.array_init_depth == 0 {
|
|
|
|
f.array_init_break = []
|
|
|
|
}
|
2020-04-26 07:16:58 +02:00
|
|
|
if inc_indent {
|
|
|
|
f.indent--
|
|
|
|
}
|
|
|
|
f.write(']')
|
2020-05-18 16:52:09 +02:00
|
|
|
// `[100]byte`
|
|
|
|
if it.is_fixed {
|
2020-08-23 19:49:16 +02:00
|
|
|
if it.has_val {
|
|
|
|
f.write('!!')
|
|
|
|
return
|
|
|
|
}
|
2020-05-18 16:52:09 +02:00
|
|
|
f.write(f.type_to_str(it.elem_type))
|
2020-08-15 11:01:54 +02:00
|
|
|
if it.has_default {
|
|
|
|
f.write('{init: $it.default_expr}')
|
|
|
|
} else {
|
|
|
|
f.write('{}')
|
|
|
|
}
|
2020-05-18 16:52:09 +02:00
|
|
|
}
|
2020-04-26 07:16:58 +02:00
|
|
|
}
|
2020-05-05 15:06:51 +02:00
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) struct_init(it ast.StructInit) {
|
2020-05-05 15:06:51 +02:00
|
|
|
type_sym := f.table.get_type_symbol(it.typ)
|
|
|
|
// f.write('<old name: $type_sym.name>')
|
2020-07-02 14:06:29 +02:00
|
|
|
mut name := type_sym.name
|
|
|
|
if !name.starts_with('C.') {
|
2020-07-11 01:42:57 +02:00
|
|
|
name = f.no_cur_mod(f.short_module(type_sym.name)) // TODO f.type_to_str?
|
2020-07-02 14:06:29 +02:00
|
|
|
}
|
2020-05-05 15:06:51 +02:00
|
|
|
if name == 'void' {
|
|
|
|
name = ''
|
|
|
|
}
|
|
|
|
if it.fields.len == 0 {
|
|
|
|
// `Foo{}` on one line if there are no fields
|
|
|
|
f.write('$name{}')
|
2020-05-18 15:37:06 +02:00
|
|
|
} else if it.is_short {
|
2020-05-05 15:06:51 +02:00
|
|
|
// `Foo{1,2,3}` (short syntax )
|
|
|
|
// if name != '' {
|
|
|
|
f.write('$name{')
|
|
|
|
// }
|
|
|
|
for i, field in it.fields {
|
2020-07-02 14:06:29 +02:00
|
|
|
f.prefix_expr_cast_expr(field.expr)
|
2020-05-05 15:06:51 +02:00
|
|
|
if i < it.fields.len - 1 {
|
|
|
|
f.write(', ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.write('}')
|
|
|
|
} else {
|
2020-05-24 04:43:00 +02:00
|
|
|
if f.use_short_fn_args {
|
|
|
|
f.writeln('')
|
|
|
|
} else {
|
|
|
|
f.writeln('$name{')
|
|
|
|
}
|
2020-05-05 15:06:51 +02:00
|
|
|
f.indent++
|
|
|
|
for field in it.fields {
|
|
|
|
f.write('$field.name: ')
|
2020-07-02 14:06:29 +02:00
|
|
|
f.prefix_expr_cast_expr(field.expr)
|
2020-05-05 15:06:51 +02:00
|
|
|
f.writeln('')
|
|
|
|
}
|
|
|
|
f.indent--
|
2020-05-24 04:43:00 +02:00
|
|
|
if !f.use_short_fn_args {
|
|
|
|
f.write('}')
|
|
|
|
}
|
2020-05-05 15:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-12 00:09:59 +02:00
|
|
|
|
2020-05-19 13:19:37 +02:00
|
|
|
pub fn (mut f Fmt) const_decl(it ast.ConstDecl) {
|
2020-05-12 00:09:59 +02:00
|
|
|
if it.is_pub {
|
|
|
|
f.write('pub ')
|
|
|
|
}
|
|
|
|
f.writeln('const (')
|
|
|
|
mut max := 0
|
|
|
|
for field in it.fields {
|
|
|
|
if field.name.len > max {
|
|
|
|
max = field.name.len
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.indent++
|
|
|
|
for field in it.fields {
|
2020-06-23 18:01:56 +02:00
|
|
|
comments := field.comments
|
|
|
|
mut j := 0
|
|
|
|
for j < comments.len && comments[j].pos.pos < field.pos.pos {
|
2020-07-20 16:48:33 +02:00
|
|
|
f.comment(comments[j], {
|
|
|
|
inline: true
|
|
|
|
})
|
2020-07-17 19:13:22 +02:00
|
|
|
f.writeln('')
|
2020-06-23 18:01:56 +02:00
|
|
|
j++
|
2020-05-12 00:09:59 +02:00
|
|
|
}
|
|
|
|
name := field.name.after('.')
|
|
|
|
f.write('$name ')
|
|
|
|
f.write(strings.repeat(` `, max - field.name.len))
|
|
|
|
f.write('= ')
|
|
|
|
f.expr(field.expr)
|
|
|
|
f.writeln('')
|
|
|
|
}
|
2020-08-27 14:07:49 +02:00
|
|
|
f.comments_after_last_field(it.end_comments)
|
2020-05-12 00:09:59 +02:00
|
|
|
f.indent--
|
|
|
|
f.writeln(')\n')
|
|
|
|
}
|
2020-07-21 15:28:30 +02:00
|
|
|
|
|
|
|
fn (mut f Fmt) is_external_name(name string) bool {
|
2020-07-27 12:15:29 +02:00
|
|
|
if name.len > 2 && name[0] == `C` && name[1] == `.` {
|
2020-07-21 15:28:30 +02:00
|
|
|
return true
|
|
|
|
}
|
2020-07-27 12:15:29 +02:00
|
|
|
if name.len > 3 && name[0] == `J` && name[1] == `S` && name[2] == `.` {
|
2020-07-21 15:28:30 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|