vfmt: add support for 64bit int with -new_int (part 2) (#25298)

This commit is contained in:
kbkpbot 2025-09-13 21:46:57 +08:00 committed by GitHub
parent c221b3226b
commit b8260625f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 272 additions and 39 deletions

View File

@ -27,6 +27,7 @@ struct FormatOptions {
is_worker bool // true *only* in the worker processes. Note: workers can crash. is_worker bool // true *only* in the worker processes. Note: workers can crash.
is_backup bool // make a `file.v.bak` copy *before* overwriting a `file.v` in place with `-w` is_backup bool // make a `file.v.bak` copy *before* overwriting a `file.v` in place with `-w`
in_process bool // do not fork a worker process; potentially faster, but more prone to crashes for invalid files in_process bool // do not fork a worker process; potentially faster, but more prone to crashes for invalid files
is_new_int bool // Forcefully cast the `int` type in @[translated] modules or in the definition of `C.func` to the `i32` type.
mut: mut:
diff_cmd string // filled in when -diff or -verify is passed diff_cmd string // filled in when -diff or -verify is passed
} }
@ -55,6 +56,7 @@ fn main() {
is_verify: '-verify' in args is_verify: '-verify' in args
is_backup: '-backup' in args is_backup: '-backup' in args
in_process: '-inprocess' in args in_process: '-inprocess' in args
is_new_int: '-new_int' in args
} }
if term_colors { if term_colors {
os.setenv('VCOLORS', 'always', true) os.setenv('VCOLORS', 'always', true)
@ -184,6 +186,7 @@ fn (foptions &FormatOptions) vlog(msg string) {
fn (foptions &FormatOptions) formated_content_from_file(prefs &pref.Preferences, file string) string { fn (foptions &FormatOptions) formated_content_from_file(prefs &pref.Preferences, file string) string {
mut table := ast.new_table() mut table := ast.new_table()
file_ast := parser.parse_file(file, mut table, .parse_comments, prefs) file_ast := parser.parse_file(file, mut table, .parse_comments, prefs)
table.new_int = foptions.is_new_int
formated_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug) formated_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug)
return formated_content return formated_content
} }
@ -202,6 +205,7 @@ fn (foptions &FormatOptions) format_file(file string) {
prefs, mut table := setup_preferences_and_table() prefs, mut table := setup_preferences_and_table()
file_ast := parser.parse_file(file, mut table, .parse_comments, prefs) file_ast := parser.parse_file(file, mut table, .parse_comments, prefs)
// checker.new_checker(table, prefs).check(file_ast) // checker.new_checker(table, prefs).check(file_ast)
table.new_int = foptions.is_new_int
formatted_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug) formatted_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug)
os.write_file(vfmt_output_path, formatted_content) or { panic(err) } os.write_file(vfmt_output_path, formatted_content) or { panic(err) }
foptions.vlog('fmt.fmt worked and ${formatted_content.len} bytes were written to ${vfmt_output_path} .') foptions.vlog('fmt.fmt worked and ${formatted_content.len} bytes were written to ${vfmt_output_path} .')
@ -214,6 +218,7 @@ fn (foptions &FormatOptions) format_pipe() {
input_text := os.get_raw_lines_joined() input_text := os.get_raw_lines_joined()
file_ast := parser.parse_text(input_text, '', mut table, .parse_comments, prefs) file_ast := parser.parse_text(input_text, '', mut table, .parse_comments, prefs)
// checker.new_checker(table, prefs).check(file_ast) // checker.new_checker(table, prefs).check(file_ast)
table.new_int = foptions.is_new_int
formatted_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug, formatted_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug,
source_text: input_text source_text: input_text
) )

View File

@ -119,6 +119,9 @@ pub fn (t &Table) stringify_fn_decl(node &FnDecl, cur_mod string, m2a map[string
} }
f.write_string(node.receiver.name + ' ') f.write_string(node.receiver.name + ' ')
styp = util.no_cur_mod(styp, cur_mod) styp = util.no_cur_mod(styp, cur_mod)
if t.new_int_fmt_fix && styp == 'int' {
styp = 'i32'
}
f.write_string(styp + ') ') f.write_string(styp + ') ')
} else if node.is_static_type_method { } else if node.is_static_type_method {
mut styp := util.no_cur_mod(t.type_to_code(node.receiver.typ.clear_flag(.shared_f)), mut styp := util.no_cur_mod(t.type_to_code(node.receiver.typ.clear_flag(.shared_f)),
@ -176,6 +179,7 @@ fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_m
if param.is_hidden { if param.is_hidden {
continue continue
} }
param_typ := if t.new_int_fmt_fix && param.typ == int_type { i32_type } else { param.typ }
is_last_param := i == node.params.len - 1 is_last_param := i == node.params.len - 1
is_type_only := param.name == '' is_type_only := param.name == ''
if param.on_newline { if param.on_newline {
@ -187,19 +191,24 @@ fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_m
f.write_string(' ') f.write_string(' ')
} }
if param.is_mut { if param.is_mut {
f.write_string(param.typ.share().str() + ' ') f.write_string(param_typ.share().str() + ' ')
} }
f.write_string(param.name) f.write_string(param.name)
param_sym := t.sym(param.typ) param_sym := t.sym(param_typ)
if param_sym.info is Struct && param_sym.info.is_anon { if param_sym.info is Struct && param_sym.info.is_anon {
if param.typ.has_flag(.option) { if param_typ.has_flag(.option) {
f.write_string(' ?') f.write_string(' ?')
} else { } else {
f.write_string(' ') f.write_string(' ')
} }
f.write_string('struct {') f.write_string('struct {')
for field in param_sym.info.fields { for field in param_sym.info.fields {
f.write_string(' ${field.name} ${t.type_to_str(field.typ)}') field_typ := if t.new_int_fmt_fix && field.typ == int_type {
i32_type
} else {
field.typ
}
f.write_string(' ${field.name} ${t.type_to_str(field_typ)}')
if field.has_default_expr { if field.has_default_expr {
f.write_string(' = ${field.default_expr}') f.write_string(' = ${field.default_expr}')
} }
@ -209,14 +218,14 @@ fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_m
} }
f.write_string('}') f.write_string('}')
} else { } else {
mut s := t.type_to_str(param.typ.clear_flag(.shared_f)) mut s := t.type_to_str(param_typ.clear_flag(.shared_f))
if param.is_mut { if param.is_mut {
if s.starts_with('&') && ((!param_sym.is_number() && param_sym.kind != .bool) if s.starts_with('&') && ((!param_sym.is_number() && param_sym.kind != .bool)
|| node.language != .v || node.language != .v
|| (param.typ.is_ptr() && param_sym.kind == .struct)) { || (param_typ.is_ptr() && param_sym.kind == .struct)) {
s = s[1..] s = s[1..]
} else if param.typ.is_ptr() && param_sym.kind == .struct && !s.contains('[') { } else if param_typ.is_ptr() && param_sym.kind == .struct && !s.contains('[') {
s = t.type_to_str(param.typ.clear_flag(.shared_f).deref()) s = t.type_to_str(param_typ.clear_flag(.shared_f).deref())
} }
} }
s = util.no_cur_mod(s, cur_mod) s = util.no_cur_mod(s, cur_mod)
@ -239,7 +248,12 @@ fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_m
} }
f.write_string(')') f.write_string(')')
if node.return_type != void_type { if node.return_type != void_type {
sreturn_type := util.no_cur_mod(t.type_to_str(node.return_type), cur_mod) return_type := if t.new_int_fmt_fix && node.return_type == int_type {
i32_type
} else {
node.return_type
}
sreturn_type := util.no_cur_mod(t.type_to_str(return_type), cur_mod)
short_sreturn_type := shorten_full_name_based_on_aliases(sreturn_type, m2a) short_sreturn_type := shorten_full_name_based_on_aliases(sreturn_type, m2a)
f.write_string(' ${short_sreturn_type}') f.write_string(' ${short_sreturn_type}')
} }

View File

@ -99,6 +99,8 @@ pub mut:
anon_union_names map[string]int // anon union name -> union sym idx anon_union_names map[string]int // anon union name -> union sym idx
anon_union_counter int anon_union_counter int
comptime_is_true map[string]ComptTimeCondResult // The evaluate cond results for different generic types combination, such as `comptime_is_true['T=int,X=string|main.v|pos ...'] = {true, '!DEFINED(WINDOWS)'}` comptime_is_true map[string]ComptTimeCondResult // The evaluate cond results for different generic types combination, such as `comptime_is_true['T=int,X=string|main.v|pos ...'] = {true, '!DEFINED(WINDOWS)'}`
new_int bool // use 64bit/32bit platform dependent `int`
new_int_fmt_fix bool // vfmt will fix `int` to `i32`
} }
pub struct ComptTimeCondResult { pub struct ComptTimeCondResult {

View File

@ -0,0 +1,70 @@
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
import os
import term
import benchmark
import v.ast
import v.fmt
import v.parser
import v.pref
import v.util.diff
import v.util.vtest
const vroot = @VEXEROOT
const tdir = os.join_path(vroot, 'vlib', 'v', 'fmt')
const fpref = &pref.Preferences{
is_fmt: true
}
fn run_fmt(mut input_files []string) {
fmt_message := 'vfmt new_int tests'
eprintln(term.header(fmt_message, '-'))
tmpfolder := os.temp_dir()
assert input_files.len > 0
input_files = vtest.filter_vtest_only(input_files)
if input_files.len == 0 {
// No need to produce a failing test here.
eprintln('no tests found with VTEST_ONLY filter set to: ' + os.getenv('VTEST_ONLY'))
exit(0)
}
mut fmt_bench := benchmark.new_benchmark()
fmt_bench.set_total_expected_steps(input_files.len)
for istep, ipath in input_files {
fmt_bench.cstep = istep
fmt_bench.step()
opath := ipath.replace('_input.vv', '_expected_new_int.vv')
if !os.exists(opath) {
// skip not exist files
continue
}
expected_ocontent := os.read_file(opath) or {
fmt_bench.fail()
eprintln(fmt_bench.step_message_fail('cannot read from ${opath}'))
continue
}
mut table := ast.new_table()
file_ast := parser.parse_file(ipath, mut table, .parse_comments, fpref)
table.new_int = true
result_ocontent := fmt.fmt(file_ast, mut table, fpref, false)
if expected_ocontent != result_ocontent {
fmt_bench.fail()
eprintln(fmt_bench.step_message_fail('file ${ipath} after formatting, does not look as expected.'))
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_${os.file_name(ipath)}')
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
println(diff.compare_files(opath, vfmt_result_file) or { err.msg() })
continue
}
fmt_bench.ok()
eprintln(fmt_bench.step_message_ok(ipath))
}
fmt_bench.stop()
eprintln(term.h_divider('-'))
eprintln(fmt_bench.total_message(fmt_message))
assert fmt_bench.nfail == 0
}
fn test_new_int_fmt() {
mut input_files := os.walk_ext(os.join_path(tdir, 'tests'), '_input.vv')
run_fmt(mut input_files)
}

View File

@ -53,6 +53,8 @@ pub mut:
source_text string // can be set by `echo "println('hi')" | v fmt`, i.e. when processing source not from a file, but from stdin. In this case, it will contain the entire input text. You can use f.file.path otherwise, and read from that file. source_text string // can be set by `echo "println('hi')" | v fmt`, i.e. when processing source not from a file, but from stdin. In this case, it will contain the entire input text. You can use f.file.path otherwise, and read from that file.
global_processed_imports []string global_processed_imports []string
branch_processed_imports []string branch_processed_imports []string
is_translated_module bool // @[translated]
is_c_function bool // C.func(...)
} }
@[params] @[params]
@ -107,7 +109,7 @@ pub fn fmt(file ast.File, mut table ast.Table, pref_ &pref.Preferences, is_debug
// vfmt has a special type_to_str which calls Table.type_to_str, but does extra work. // vfmt has a special type_to_str which calls Table.type_to_str, but does extra work.
// Having it here and not in Table saves cpu cycles when not running the compiler in vfmt mode. // Having it here and not in Table saves cpu cycles when not running the compiler in vfmt mode.
pub fn (f &Fmt) type_to_str_using_aliases(typ ast.Type, import_aliases map[string]string) string { pub fn (f &Fmt) type_to_str_using_aliases(typ ast.Type, import_aliases map[string]string) string {
mut s := f.table.type_to_str_using_aliases(typ, import_aliases) mut s := f.type_to_str_using_aliases(typ, import_aliases)
if s.contains('Result') { if s.contains('Result') {
println('${s}') println('${s}')
} }
@ -118,9 +120,22 @@ pub fn (f &Fmt) type_to_str_using_aliases(typ ast.Type, import_aliases map[strin
} }
pub fn (f &Fmt) type_to_str(typ ast.Type) string { pub fn (f &Fmt) type_to_str(typ ast.Type) string {
return f.table.type_to_str(typ) return f.type_to_str(typ)
} }
*/ */
fn (f &Fmt) type_to_str_using_aliases(typ ast.Type, import_aliases map[string]string) string {
if f.table.new_int && typ == ast.int_type && (f.is_translated_module || f.is_c_function) {
return f.type_to_str_using_aliases(ast.i32_type, import_aliases)
}
return f.table.type_to_str_using_aliases(typ, import_aliases)
}
fn (f &Fmt) type_to_str(typ ast.Type) string {
if f.table.new_int && typ == ast.int_type && (f.is_translated_module || f.is_c_function) {
return 'i32'
}
return f.table.type_to_str(typ)
}
pub fn (mut f Fmt) process_file_imports(file &ast.File) { pub fn (mut f Fmt) process_file_imports(file &ast.File) {
mut sb := strings.new_builder(128) mut sb := strings.new_builder(128)
@ -232,7 +247,7 @@ fn (mut f Fmt) write_language_prefix(lang ast.Language) {
fn (mut f Fmt) write_generic_types(gtypes []ast.Type) { fn (mut f Fmt) write_generic_types(gtypes []ast.Type) {
if gtypes.len > 0 { if gtypes.len > 0 {
f.write('[') f.write('[')
gtypes_string := gtypes.map(f.table.type_to_str(it)).join(', ') gtypes_string := gtypes.map(f.type_to_str(it)).join(', ')
f.write(gtypes_string) f.write(gtypes_string)
f.write(']') f.write(']')
} }
@ -882,7 +897,7 @@ pub fn (mut f Fmt) branch_stmt(node ast.BranchStmt) {
pub fn (mut f Fmt) comptime_for(node ast.ComptimeFor) { pub fn (mut f Fmt) comptime_for(node ast.ComptimeFor) {
typ := if node.typ != ast.void_type { typ := if node.typ != ast.void_type {
f.no_cur_mod(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.no_cur_mod(f.type_to_str_using_aliases(node.typ, f.mod2alias))
} else { } else {
(node.expr as ast.Ident).name (node.expr as ast.Ident).name
} }
@ -941,7 +956,7 @@ pub fn (mut f Fmt) const_decl(node ast.ConstDecl) {
f.write('${name} ') f.write('${name} ')
if field.is_virtual_c { if field.is_virtual_c {
// f.typ(field.typ) // f.typ(field.typ)
f.write(f.table.type_to_str(field.typ)) f.write(f.type_to_str(field.typ))
} else { } else {
f.write('= ') f.write('= ')
f.expr(field.expr) f.expr(field.expr)
@ -1005,7 +1020,7 @@ pub fn (mut f Fmt) enum_decl(node ast.EnumDecl) {
} }
mut name := node.name.after('.') mut name := node.name.after('.')
if node.typ != ast.int_type && node.typ != ast.invalid_type { if node.typ != ast.int_type && node.typ != ast.invalid_type {
senum_type := f.table.type_to_str_using_aliases(node.typ, f.mod2alias) senum_type := f.type_to_str_using_aliases(node.typ, f.mod2alias)
name += ' as ${senum_type}' name += ' as ${senum_type}'
} }
if node.fields.len == 0 && node.pos.line_nr == node.pos.last_line { if node.fields.len == 0 && node.pos.line_nr == node.pos.last_line {
@ -1082,7 +1097,13 @@ pub fn (mut f Fmt) enum_decl(node ast.EnumDecl) {
pub fn (mut f Fmt) fn_decl(node ast.FnDecl) { pub fn (mut f Fmt) fn_decl(node ast.FnDecl) {
f.attrs(node.attrs) f.attrs(node.attrs)
if node.name.starts_with('C.') {
f.is_c_function = true
}
f.table.new_int_fmt_fix = f.table.new_int && (f.is_translated_module || f.is_c_function)
f.write(f.table.stringify_fn_decl(&node, f.cur_mod, f.mod2alias, true)) f.write(f.table.stringify_fn_decl(&node, f.cur_mod, f.mod2alias, true))
f.table.new_int_fmt_fix = false
f.is_c_function = false
// Handle trailing comments after fn header declarations // Handle trailing comments after fn header declarations
if node.no_body && node.end_comments.len > 0 { if node.no_body && node.end_comments.len > 0 {
first_comment := node.end_comments[0] first_comment := node.end_comments[0]
@ -1107,7 +1128,9 @@ pub fn (mut f Fmt) fn_decl(node ast.FnDecl) {
} }
pub fn (mut f Fmt) anon_fn(node ast.AnonFn) { pub fn (mut f Fmt) anon_fn(node ast.AnonFn) {
f.table.new_int_fmt_fix = f.table.new_int && (f.is_translated_module || f.is_c_function)
f.write(f.table.stringify_anon_decl(&node, f.cur_mod, f.mod2alias)) // `Expr` instead of `ast.Expr` in mod ast f.write(f.table.stringify_anon_decl(&node, f.cur_mod, f.mod2alias)) // `Expr` instead of `ast.Expr` in mod ast
f.table.new_int_fmt_fix = false
f.fn_body(node.decl) f.fn_body(node.decl)
} }
@ -1297,7 +1320,7 @@ pub fn (mut f Fmt) global_decl(node ast.GlobalDecl) {
f.write('= ') f.write('= ')
f.expr(field.expr) f.expr(field.expr)
} else { } else {
f.write('${f.table.type_to_str_using_aliases(field.typ, f.mod2alias)}') f.write('${f.type_to_str_using_aliases(field.typ, f.mod2alias)}')
} }
if node.is_block { if node.is_block {
f.writeln('') f.writeln('')
@ -1382,7 +1405,9 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
for method in node.methods { for method in node.methods {
end_comments := method.comments.filter(it.pos.pos > method.pos.pos) end_comments := method.comments.filter(it.pos.pos > method.pos.pos)
if end_comments.len > 0 { if end_comments.len > 0 {
f.table.new_int_fmt_fix = f.table.new_int && (f.is_translated_module || f.is_c_function)
method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ') method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ')
f.table.new_int_fmt_fix = false
method_comment_align.add_info(method_str.len, method.pos.line_nr, method.has_break_line) method_comment_align.add_info(method_str.len, method.pos.line_nr, method.has_break_line)
} }
} }
@ -1430,7 +1455,7 @@ pub fn (mut f Fmt) calculate_alignment(fields []ast.StructField, mut type_align
// Calculate the alignments first // Calculate the alignments first
mut prev_state := AlignState.plain mut prev_state := AlignState.plain
for field in fields { for field in fields {
ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias)) ft := f.no_cur_mod(f.type_to_str_using_aliases(field.typ, f.mod2alias))
// Handle anon structs recursively // Handle anon structs recursively
field_types << ft field_types << ft
attrs_len := inline_attrs_len(field.attrs) attrs_len := inline_attrs_len(field.attrs)
@ -1477,7 +1502,7 @@ pub fn (mut f Fmt) calculate_alignment(fields []ast.StructField, mut type_align
} }
pub fn (mut f Fmt) interface_field(field ast.StructField, mut type_align FieldAlign, mut comment_align FieldAlign) { pub fn (mut f Fmt) interface_field(field ast.StructField, mut type_align FieldAlign, mut comment_align FieldAlign) {
ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias)) ft := f.no_cur_mod(f.type_to_str_using_aliases(field.typ, f.mod2alias))
mut pre_cmts, mut end_cmts, mut next_line_cmts := []ast.Comment{}, []ast.Comment{}, []ast.Comment{} mut pre_cmts, mut end_cmts, mut next_line_cmts := []ast.Comment{}, []ast.Comment{}, []ast.Comment{}
for cmt in field.comments { for cmt in field.comments {
match true { match true {
@ -1523,7 +1548,9 @@ pub fn (mut f Fmt) interface_method(method ast.FnDecl, mut comment_align FieldAl
f.comments(before_comments, level: .indent) f.comments(before_comments, level: .indent)
} }
f.write('\t') f.write('\t')
f.table.new_int_fmt_fix = f.table.new_int && (f.is_translated_module || f.is_c_function)
method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ') method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ')
f.table.new_int_fmt_fix = false
f.write(method_str) f.write(method_str)
if end_comments.len > 0 { if end_comments.len > 0 {
f.write(' '.repeat(comment_align.max_len(method.pos.line_nr) - method_str.len + 1)) f.write(' '.repeat(comment_align.max_len(method.pos.line_nr) - method_str.len + 1))
@ -1539,6 +1566,7 @@ pub fn (mut f Fmt) module_stmt(mod ast.Module) {
if mod.is_skipped { if mod.is_skipped {
return return
} }
f.is_translated_module = mod.attrs.any(it.name == 'translated')
f.attrs(mod.attrs) f.attrs(mod.attrs)
f.writeln('module ${mod.short_name}\n') f.writeln('module ${mod.short_name}\n')
if f.import_pos == 0 { if f.import_pos == 0 {
@ -1655,7 +1683,7 @@ pub fn (mut f Fmt) alias_type_decl(node ast.AliasTypeDecl) {
return return
} }
} }
ptype := f.table.type_to_str_using_aliases(node.parent_type, f.mod2alias) ptype := f.type_to_str_using_aliases(node.parent_type, f.mod2alias)
f.write('type ${node.name} = ${ptype}') f.write('type ${node.name} = ${ptype}')
f.comments(node.comments, has_nl: false) f.comments(node.comments, has_nl: false)
@ -1681,7 +1709,7 @@ pub fn (mut f Fmt) fn_type_decl(node ast.FnTypeDecl) {
f.write(arg.typ.share().str() + ' ') f.write(arg.typ.share().str() + ' ')
} }
f.write(arg.name) f.write(arg.name)
mut s := f.no_cur_mod(f.table.type_to_str_using_aliases(arg.typ, f.mod2alias)) mut s := f.no_cur_mod(f.type_to_str_using_aliases(arg.typ, f.mod2alias))
if arg.is_mut { if arg.is_mut {
if s.starts_with('&') { if s.starts_with('&') {
s = s[1..] s = s[1..]
@ -1706,8 +1734,7 @@ pub fn (mut f Fmt) fn_type_decl(node ast.FnTypeDecl) {
} }
f.write(')') f.write(')')
if fn_info.return_type.idx() != ast.void_type_idx { if fn_info.return_type.idx() != ast.void_type_idx {
ret_str := f.no_cur_mod(f.table.type_to_str_using_aliases(fn_info.return_type, ret_str := f.no_cur_mod(f.type_to_str_using_aliases(fn_info.return_type, f.mod2alias))
f.mod2alias))
f.write(' ${ret_str}') f.write(' ${ret_str}')
} else if fn_info.return_type.has_flag(.option) { } else if fn_info.return_type.has_flag(.option) {
f.write(' ?') f.write(' ?')
@ -1736,7 +1763,7 @@ pub fn (mut f Fmt) sum_type_decl(node ast.SumTypeDecl) {
mut variants := []Variant{cap: node.variants.len} mut variants := []Variant{cap: node.variants.len}
for i, variant in node.variants { for i, variant in node.variants {
variants << Variant{f.table.type_to_str_using_aliases(variant.typ, f.mod2alias), i} variants << Variant{f.type_to_str_using_aliases(variant.typ, f.mod2alias), i}
} }
// The first variant is now used as the default variant when doing `a:= Sumtype{}`, i.e. a change in semantics. // The first variant is now used as the default variant when doing `a:= Sumtype{}`, i.e. a change in semantics.
// Sorting is disabled, because it is no longer a cosmetic change - it can change the default variant. // Sorting is disabled, because it is no longer a cosmetic change - it can change the default variant.
@ -1787,9 +1814,9 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
if node.exprs.len == 0 && node.typ != 0 && node.typ != ast.void_type { if node.exprs.len == 0 && node.typ != 0 && node.typ != ast.void_type {
// `x := []string{}` // `x := []string{}`
if node.alias_type != ast.void_type { if node.alias_type != ast.void_type {
f.write(f.table.type_to_str_using_aliases(node.alias_type, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.alias_type, f.mod2alias))
} else { } else {
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
} }
f.write('{') f.write('{')
if node.has_len { if node.has_len {
@ -1976,7 +2003,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
f.write('!') f.write('!')
return return
} }
f.write(f.table.type_to_str_using_aliases(node.elem_type, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.elem_type, f.mod2alias))
if node.has_init { if node.has_init {
f.write('{init: ') f.write('{init: ')
f.expr(node.init_expr) f.expr(node.init_expr)
@ -1988,7 +2015,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
} }
pub fn (mut f Fmt) as_cast(node ast.AsCast) { pub fn (mut f Fmt) as_cast(node ast.AsCast) {
type_str := f.table.type_to_str_using_aliases(node.typ, f.mod2alias) type_str := f.type_to_str_using_aliases(node.typ, f.mod2alias)
f.expr(node.expr) f.expr(node.expr)
f.write(' as ${type_str}') f.write(' as ${type_str}')
} }
@ -2070,7 +2097,7 @@ fn (mut f Fmt) write_generic_call_if_require(node ast.CallExpr) {
if node.concrete_types.len > 0 { if node.concrete_types.len > 0 {
f.write('[') f.write('[')
for i, concrete_type in node.concrete_types { for i, concrete_type in node.concrete_types {
mut name := f.table.type_to_str_using_aliases(concrete_type, f.mod2alias) mut name := f.type_to_str_using_aliases(concrete_type, f.mod2alias)
tsym := f.table.sym(concrete_type) tsym := f.table.sym(concrete_type)
if tsym.language != .js && !tsym.name.starts_with('JS.') { if tsym.language != .js && !tsym.name.starts_with('JS.') {
name = f.short_module(name) name = f.short_module(name)
@ -2128,7 +2155,7 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) {
} }
pub fn (mut f Fmt) cast_expr(node ast.CastExpr) { pub fn (mut f Fmt) cast_expr(node ast.CastExpr) {
typ := f.table.type_to_str_using_aliases(node.typ, f.mod2alias) typ := f.type_to_str_using_aliases(node.typ, f.mod2alias)
if typ == 'voidptr' { if typ == 'voidptr' {
// `voidptr(0)` => `nil` // `voidptr(0)` => `nil`
if node.expr is ast.IntegerLiteral { if node.expr is ast.IntegerLiteral {
@ -2166,7 +2193,7 @@ pub fn (mut f Fmt) chan_init(mut node ast.ChanInit) {
if is_mut { if is_mut {
f.write('mut ') f.write('mut ')
} }
f.write(f.table.type_to_str_using_aliases(el_typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(el_typ, f.mod2alias))
f.write('{') f.write('{')
if node.has_cap { if node.has_cap {
f.write('cap: ') f.write('cap: ')
@ -2333,7 +2360,7 @@ pub fn (mut f Fmt) ident(node ast.Ident) {
if node.concrete_types.len > 0 { if node.concrete_types.len > 0 {
f.write('[') f.write('[')
for i, concrete_type in node.concrete_types { for i, concrete_type in node.concrete_types {
typ_name := f.table.type_to_str_using_aliases(concrete_type, f.mod2alias) typ_name := f.type_to_str_using_aliases(concrete_type, f.mod2alias)
f.write(typ_name) f.write(typ_name)
if i != node.concrete_types.len - 1 { if i != node.concrete_types.len - 1 {
f.write(', ') f.write(', ')
@ -2704,7 +2731,7 @@ pub fn (mut f Fmt) lock_expr(node ast.LockExpr) {
pub fn (mut f Fmt) map_init(node ast.MapInit) { pub fn (mut f Fmt) map_init(node ast.MapInit) {
if node.keys.len == 0 && !node.has_update_expr { if node.keys.len == 0 && !node.has_update_expr {
if node.typ > ast.void_type { if node.typ > ast.void_type {
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
} }
if node.pos.line_nr == node.pos.last_line { if node.pos.line_nr == node.pos.last_line {
f.write('{}') f.write('{}')
@ -2837,7 +2864,7 @@ pub fn (mut f Fmt) match_expr(node ast.MatchExpr) {
} }
pub fn (mut f Fmt) offset_of(node ast.OffsetOf) { pub fn (mut f Fmt) offset_of(node ast.OffsetOf) {
f.write('__offsetof(${f.table.type_to_str_using_aliases(node.struct_type, f.mod2alias)}, ${node.field})') f.write('__offsetof(${f.type_to_str_using_aliases(node.struct_type, f.mod2alias)}, ${node.field})')
} }
pub fn (mut f Fmt) or_expr(node ast.OrExpr) { pub fn (mut f Fmt) or_expr(node ast.OrExpr) {
@ -3001,13 +3028,13 @@ pub fn (mut f Fmt) size_of(node ast.SizeOf) {
if node.is_type && !node.guessed_type { if node.is_type && !node.guessed_type {
// the new form was explicitly written in the source code; keep it: // the new form was explicitly written in the source code; keep it:
f.write('[') f.write('[')
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
f.write(']()') f.write(']()')
return return
} }
if node.is_type { if node.is_type {
f.write('(') f.write('(')
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
f.write(')') f.write(')')
} else { } else {
f.write('(') f.write('(')
@ -3021,13 +3048,13 @@ pub fn (mut f Fmt) is_ref_type(node ast.IsRefType) {
if node.is_type && !node.guessed_type { if node.is_type && !node.guessed_type {
// the new form was explicitly written in the source code; keep it: // the new form was explicitly written in the source code; keep it:
f.write('[') f.write('[')
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
f.write(']()') f.write(']()')
return return
} }
if node.is_type { if node.is_type {
f.write('(') f.write('(')
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
f.write(')') f.write(')')
} else { } else {
f.write('(') f.write('(')
@ -3180,7 +3207,7 @@ pub fn (mut f Fmt) string_inter_literal(node ast.StringInterLiteral) {
pub fn (mut f Fmt) type_expr(node ast.TypeNode) { pub fn (mut f Fmt) type_expr(node ast.TypeNode) {
if node.stmt == ast.empty_stmt { if node.stmt == ast.empty_stmt {
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
} else { } else {
f.struct_decl(ast.StructDecl{ fields: (node.stmt as ast.StructDecl).fields }, f.struct_decl(ast.StructDecl{ fields: (node.stmt as ast.StructDecl).fields },
true) true)
@ -3191,7 +3218,7 @@ pub fn (mut f Fmt) type_of(node ast.TypeOf) {
f.write('typeof') f.write('typeof')
if node.is_type { if node.is_type {
f.write('[') f.write('[')
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.type_to_str_using_aliases(node.typ, f.mod2alias))
f.write(']()') f.write(']()')
} else { } else {
f.write('(') f.write('(')

View File

@ -0,0 +1,68 @@
fn C.func(arg i32) i32
fn fn_variadic(arg int, args ...string) {
println('Do nothing')
}
fn fn_with_assign_stmts() {
_, _ := fn_with_multi_return()
}
fn fn_with_multi_return() (int, string) {
return 0, 'test'
}
fn voidfn() {
println('this is a function that does not return anything')
}
fn fn_with_1_arg(arg int) int {
return 0
}
fn fn_with_2a_args(arg1 int, arg2 int) int {
return 0
}
fn fn_with_2_args_to_be_shorten(arg1 int, arg2 int) int {
return 0
}
fn fn_with_2b_args(arg1 string, arg2 int) int {
return 0
}
fn fn_with_3_args(arg1 string, arg2 int, arg3 User) int {
return 0
}
fn (this User) fn_with_receiver() {
println('')
}
fn fn_with_option() ?int {
if true {
return error('true')
}
return 30
}
fn (f Foo) fn_with_option() ?int {
if true {
return error('true')
}
return 40
}
fn mut_array(mut a []int) {
println(1)
}
fn fn_with_ref_return() &Foo {
return &Foo{}
}
@[inline]
fn fn_with_flag() {
println('flag')
}

View File

@ -0,0 +1,5 @@
module main
fn C.abc(a int, b int, c charptr) int
fn abc(a int, b int, c charptr) int

View File

@ -0,0 +1,5 @@
module main
fn C.abc(a i32, b i32, c charptr) i32
fn abc(a int, b int, c charptr) int

View File

@ -0,0 +1,6 @@
module main
fn C.abc(a int, b int, c charptr) int
fn abc(a int, b int, c charptr) int

View File

@ -0,0 +1,9 @@
@[translated]
module aa
fn C.abc(a int, b int)
fn abc(x int, y int) {
s := int(123)
dump(s)
}

View File

@ -0,0 +1,9 @@
@[translated]
module aa
fn C.abc(a i32, b i32)
fn abc(x i32, y i32) {
s := i32(123)
dump(s)
}

View File

@ -0,0 +1,10 @@
@[translated]
module aa
fn C.abc(a int, b int)
fn abc(x int, y int) {
s := int(123)
dump(s)
}

View File

@ -37,6 +37,9 @@ Options:
more memory, but it is faster for thousands of files, since more memory, but it is faster for thousands of files, since
it avoids the interprocess communication overhead. it avoids the interprocess communication overhead.
-new_int Forcefully cast the `int` type in @[translated] modules or
in the definition of `C.func` to the `i32` type.
Environment Variables: Environment Variables:
VDIFF_CMD A custom tool and options that will be used for viewing the VDIFF_CMD A custom tool and options that will be used for viewing the
differences between the original and the temporarily formatted differences between the original and the temporarily formatted