1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

run vfmt on fn.v

This commit is contained in:
Alexander Medvednikov 2019-12-18 09:04:35 +03:00
parent 81045023c4
commit 569b32bd1e
6 changed files with 347 additions and 323 deletions

1
v.v
View File

@ -21,7 +21,6 @@ const (
fn main() {
//t := time.ticks()
//defer { println(time.ticks() - t) }
// There's no `flags` module yet, so args have to be parsed manually
args := compiler.env_vflags_and_os_args()
options, command := compiler.get_v_options_and_main_command( args )
// external tool

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module compiler
import (
@ -56,8 +55,11 @@ mut:
}
const (
EmptyFn = Fn{}
MainFn = Fn{ name: 'main' }
EmptyFn = Fn{
}
MainFn = Fn{
name: 'main'
}
)
pub fn (a []TypeInst) str() string {
@ -165,7 +167,11 @@ fn (p &Parser) known_var_check_new_var(name string) bool {
}
fn (p mut Parser) register_var(v Var) {
mut new_var := {v | idx: p.var_idx, scope_level: p.cur_fn.scope_level}
mut new_var := {
v |
idx:p.var_idx,
scope_level:p.cur_fn.scope_level
}
if v.line_nr == 0 {
new_var.token_idx = p.cur_tok_index()
new_var.line_nr = p.cur_tok().line_nr
@ -189,13 +195,15 @@ fn (p mut Parser) clear_vars() {
}
p.local_vars = []
}
}
// Function signatures are added to the top of the .c file in the first run.
fn (p mut Parser) fn_decl() {
p.clear_vars() // clear local vars every time a new fn is started
defer { p.fgen_nl() p.fgen_nl() }
defer {
p.fgen_nl()
p.fgen_nl()
}
fn_start_idx := p.cur_tok_index()
// If we are in the first pass, create a new function.
// In the second pass fetch the one we created.
@ -208,10 +216,12 @@ fn (p mut Parser) fn_decl() {
else {
}
*/
is_pub := p.tok == .key_pub
mut f := Fn{
mod: p.mod
is_public: is_pub || p.is_vh // functions defined in .vh are always public
is_unsafe: p.attr == 'unsafe_fn'
is_deprecated: p.attr == 'deprecated'
comptime_define: if p.attr.starts_with('if ') {p.attr[3..]}else {''}
@ -228,7 +238,6 @@ fn (p mut Parser) fn_decl() {
// p.gen('/* returns $p.returns */')
p.next()
p.fspace()
// Method receiver
mut receiver_typ := ''
if p.tok == .lpar {
@ -253,8 +262,7 @@ fn (p mut Parser) fn_decl() {
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
}
// Don't allow modifying types from a different module
if !p.first_pass() && !p.builtin_mod && t.mod != p.mod &&
!p.is_vgen // let vgen define methods like .str() on types defined in other modules
if !p.first_pass() && !p.builtin_mod && t.mod != p.mod && !p.is_vgen // let vgen define methods like .str() on types defined in other modules
{
// println('T.mod=$T.mod')
// println('p.mod=$p.mod')
@ -325,9 +333,7 @@ fn (p mut Parser) fn_decl() {
// full mod function name
// `os.exit()` ==> `os__exit()`
// if !is_c && !p.builtin_mod && receiver_typ.len == 0 {
if !is_c && !has_receiver &&
(!p.builtin_mod || (p.builtin_mod && f.name == 'init'))
{
if !is_c && !has_receiver && (!p.builtin_mod || (p.builtin_mod && f.name == 'init')) {
f.name = p.prepend_mod(f.name)
}
if p.first_pass() && receiver_typ.len == 0 {
@ -345,7 +351,8 @@ fn (p mut Parser) fn_decl() {
if p.generic_dispatch.inst.size > 0 {
f.dispatch_of = p.generic_dispatch
rename_generic_fn_instance(mut f, f.dispatch_of)
} else {
}
else {
f.is_generic = true
}
p.next()
@ -358,7 +365,9 @@ fn (p mut Parser) fn_decl() {
p.error('redeclaration of type parameter `$type_par`')
}
f.type_pars << type_par
if p.tok == .gt { break }
if p.tok == .gt {
break
}
p.check(.comma)
}
p.check(.gt)
@ -367,7 +376,8 @@ fn (p mut Parser) fn_decl() {
// Args (...)
p.fn_args(mut f)
if is_op {
if f.args.len != 1 + 1 { // +1 is for the receiver
if f.args.len != 1 + 1 {
// +1 is for the receiver
p.error('operator overloading methods must have only 1 argument')
}
if f.args[0].typ != f.args[1].typ {
@ -460,18 +470,19 @@ fn (p mut Parser) fn_decl() {
}
// println('added generic method r:$rcv.name f:$f.name')
p.add_method(rcv.name, f)
} else {
}
else {
p.table.register_fn(f)
}
}
p.set_current_fn(EmptyFn)
p.skip_fn_body()
return
} else {
}
else {
p.gen_fn_decl(f, typ, str_args)
}
}
if is_fn_header {
p.genln('$typ $fn_name_cgen ($str_args);')
p.fgen_nl()
@ -527,7 +538,6 @@ fn (p mut Parser) fn_decl() {
// p.genln('// live_function body start')
p.genln('pthread_mutex_lock(&live_fn_mutex);')
}
if f.name in ['main__main', 'main', 'WinMain'] {
if p.pref.is_test {
p.error_with_token_index('tests cannot have function `main`', f.fn_name_token_idx)
@ -585,6 +595,7 @@ fn (p mut Parser) fn_decl() {
return
}
*/
p.genln('}')
if !p.builtin_mod && p.mod != 'os' {
p.check_unused_and_mut_vars()
@ -623,13 +634,7 @@ fn (p mut Parser) skip_fn_body() {
}
fn (p &Parser) get_linkage_prefix() string {
return if p.pref.ccompiler == 'msvc' && p.attr == 'live' && p.pref.is_so {
'__declspec(dllexport) '
} else if p.attr == 'inline' {
'static inline '
} else {
''
}
return if p.pref.ccompiler == 'msvc' && p.attr == 'live' && p.pref.is_so {'__declspec(dllexport) '}else if p.attr == 'inline' {'static inline '}else {''}
}
fn (p mut Parser) check_unused_and_mut_vars() {
@ -637,15 +642,10 @@ fn (p mut Parser) check_unused_and_mut_vars() {
if var.name == '' {
break
}
if !var.is_used && !p.pref.is_repl && !var.is_arg &&
!p.pref.translated && var.name != 'tmpl_res' && p.mod != 'vweb'
{
if !var.is_used && !p.pref.is_repl && !var.is_arg && !p.pref.translated && var.name != 'tmpl_res' && p.mod != 'vweb' {
p.production_error_with_token_index('`$var.name` declared and not used', var.token_idx)
}
if !var.is_changed && var.is_mut && !p.pref.is_repl &&
!p.pref.translated && var.typ != 'T*' &&
p.mod != 'ui' && var.typ != 'App*'
{
if !var.is_changed && var.is_mut && !p.pref.is_repl && !p.pref.translated && var.typ != 'T*' && p.mod != 'ui' && var.typ != 'App*' {
p.error_with_token_index('`$var.name` is declared as mutable, but it was never changed', var.token_idx)
}
}
@ -698,12 +698,10 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
}
did_gen_something = true
}
if !did_gen_something {
// Msvc doesnt like empty struct
arg_struct += 'EMPTY_STRUCT_DECLARATION;'
}
arg_struct += '} $arg_struct_name ;'
// Also register the wrapper, so we can use the original function without modifying it
fn_name = p.table.fn_gen_name(f)
@ -733,7 +731,6 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
p.genln('int $tmp2 = pthread_create(& $thread_name, NULL, (void *)$wrapper_name, $parg);')
}
p.check(.rpar)
}
fn (p mut Parser) verify_fn_before_call(f &Fn) {
@ -765,7 +762,8 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
if f.is_c && !p.builtin_mod {
if f.name == 'free' {
p.error('use `free()` instead of `C.free()`')
} else if f.name == 'malloc' {
}
else if f.name == 'malloc' {
p.error('use `malloc()` instead of `C.malloc()`')
}
}
@ -777,7 +775,8 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
for {
if p.tokens[i].tok == .gt {
p.error('explicit type arguments are not allowed; remove `<...>`')
} else if p.tokens[i].tok == .lpar {
}
else if p.tokens[i].tok == .lpar {
// probably a typo, do not concern the user with the above error message
break
}
@ -787,12 +786,10 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
// if p.pref.is_prof {
// p.cur_fn.called_fns << cgen_name
// }
// If we have a method placeholder,
// we need to preappend "method(receiver, ...)"
if f.is_method {
receiver := f.args.first()
mut receiver_is_interface := false
if receiver.typ.ends_with('er') {
// I absolutely love this syntax
@ -820,39 +817,33 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
if receiver.is_mut && !p.expr_var.is_mut {
// println('$method_call recv=$receiver.name recv_mut=$receiver.is_mut')
if p.expr_var.is_for_var {
p.error('`$p.expr_var.name` is immutable, `for` variables' +
' always are')
} else {
p.error('`$p.expr_var.name` is immutable, `for` variables' + ' always are')
}
else {
p.error('`$p.expr_var.name` is immutable, declare it with `mut`')
}
}
if !p.expr_var.is_changed && receiver.is_mut {
p.mark_var_changed(p.expr_var)
}
if !receiver_is_interface {
p.gen_method_call(receiver, receiver_type, cgen_name, f.typ, method_ph)
}
} else {
}
else {
// Normal function call
p.gen('$cgen_name (')
}
// `foo<Bar>()`
// if f is generic, the name is changed to a suitable instance in dispatch_generic_fn_instance()
// we then replace `cgen_name` with the instance's name
generic := f.is_generic
p.fn_call_args(mut f)
if generic {
line := if p.cgen.is_tmp {
p.cgen.tmp_line
} else {
p.cgen.cur_line
}
line := if p.cgen.is_tmp {p.cgen.tmp_line}else {p.cgen.cur_line}
p.cgen.resetln(line.replace('$cgen_name (', '$f.name ('))
// println('calling inst $f.name: $p.cgen.cur_line')
}
// if !is_interface {
p.gen(')')
// }
@ -863,12 +854,13 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
}
// println('end of fn call typ=$f.typ')
}
// for declaration
// update the Fn object's args[]
fn (p mut Parser) fn_args(f mut Fn) {
p.check(.lpar)
defer { p.check(.rpar) }
defer {
p.check(.rpar)
}
if f.is_interface {
interface_arg := Var{
typ: f.receiver_typ
@ -882,7 +874,8 @@ fn (p mut Parser) fn_args(f mut Fn) {
if types_only {
for p.tok != .rpar {
typ := p.get_type()
if typ == '' { //&& !f.is_c {
if typ == '' {
// && !f.is_c {
if p.prev_tok != .ellipsis {
p.error('bad fn arg type')
}
@ -892,6 +885,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
typ: typ
is_arg: true
// is_mut: is_mut
line_nr: p.scanner.line_nr
token_idx: p.cur_tok_index()
}
@ -899,6 +893,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
f.args << v
if p.tok == .comma {
p.next()
p.fspace()
}
}
}
@ -915,6 +910,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
is_mut := p.tok == .key_mut
if is_mut {
p.check(.key_mut)
p.fspace()
}
// variadic arg
if p.tok == .ellipsis {
@ -935,14 +931,14 @@ fn (p mut Parser) fn_args(f mut Fn) {
p.register_vargs_stuct(typ, 0)
}
typ = 'varg_$typ'
} else {
}
else {
typ = '...$typ' // TODO: fix, this is invalid in C
}
}
p.check_and_register_used_imported_type(typ)
if is_mut && is_primitive_type(typ) {
p.error('mutable arguments are only allowed for arrays, maps, and structs.' +
'\nreturn values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`')
p.error('mutable arguments are only allowed for arrays, maps, and structs.' + '\nreturn values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`')
}
for name in names {
if is_mut {
@ -962,6 +958,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
}
if p.tok == .comma {
p.check(.comma)
p.fspace()
}
// unnamed (C definition)
if p.tok == .ellipsis {
@ -1008,17 +1005,15 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
mod_name := p.mod.replace('_dot_', '.')
fn_name := p.cur_fn.name.replace('${p.mod}__', '')
file_path := cescaped_path(p.file_path)
p.cgen.resetln(p.cgen.cur_line.replace(
'v_panic (',
'panic_debug ($p.scanner.line_nr, tos3("$file_path"), tos3("$mod_name"), tos2((byte *)"$fn_name"), '
))
p.cgen.resetln(p.cgen.cur_line.replace('v_panic (', 'panic_debug ($p.scanner.line_nr, tos3("$file_path"), tos3("$mod_name"), tos2((byte *)"$fn_name"), '))
}
mut saved_args := []string
for i,arg in f.args {
// Receiver is the first arg
// Skip the receiver, because it was already generated in the expression
if i == 0 && f.is_method {
if f.args.len > 1 { // && !p.is_js {
if f.args.len > 1 {
// && !p.is_js {
p.gen(', ')
}
// if f.args[0].typ.ends_with('*') {
@ -1036,6 +1031,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
}
}
*/
continue
}
// Reached the final vararg? Quit
@ -1054,15 +1050,13 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
p.mutable_arg_error(i, arg, f)
}
if p.peek() != .name {
p.error('`$arg.name` is a mutable argument, you need to ' +
'provide a variable to modify: `${f.name}(... mut a...)`')
p.error('`$arg.name` is a mutable argument, you need to ' + 'provide a variable to modify: `${f.name}(... mut a...)`')
}
p.check(.key_mut)
p.fspace()
var_name := p.lit
v := p.find_var(var_name) or {
p.error('`$arg.name` is a mutable argument, you need to ' +
'provide a variable to modify: `${f.name}(... mut a...)`')
p.error('`$arg.name` is a mutable argument, you need to ' + 'provide a variable to modify: `${f.name}(... mut a...)`')
exit(1)
}
if !v.is_changed {
@ -1070,17 +1064,14 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
}
}
p.expected_type = arg.typ
clone := p.pref.autofree && p.mod != 'string' && arg.typ == 'string' &&
!p.builtin_mod //&& arg.is_moved
clone := p.pref.autofree && p.mod != 'string' && arg.typ == 'string' && !p.builtin_mod // && arg.is_moved
if clone {
p.gen('/*YY f=$f.name arg=$arg.name is_moved=$arg.is_moved*/string_clone(')
}
// x64 println gen
if p.pref.x64 && i == 0 && f.name == 'println' && p.tok == .str && p.peek() == .rpar {
p.x64.gen_print(p.lit)
}
mut typ := p.bool_expression()
// Register an interface type usage:
// fn run(r Animal) { ... }
@ -1096,12 +1087,9 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
p.table.add_gen_type(arg.typ, typ)
}
}
if clone {
p.gen(')')
}
// Optimize `println`: replace it with `printf` to avoid extra allocations and
// function calls.
// `println(777)` => `printf("%d\n", 777)`
@ -1112,9 +1100,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
}
typ = 'string'
}
if i == 0 && (f.name == 'println' || f.name == 'print') &&
!(typ in ['string', 'ustring', 'void' ])
{
if i == 0 && (f.name == 'println' || f.name == 'print') && !(typ in ['string', 'ustring', 'void']) {
//
T := p.table.find_type(typ)
$if !windows {
@ -1122,8 +1108,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
fmt := p.typ_to_fmt(typ, 0)
if fmt != '' && typ != 'bool' {
nl := if f.name == 'println' {'\\n'}else {''}
p.cgen.resetln(p.cgen.cur_line.replace(f.name +
' (', '/*opt*/printf ("' + fmt + '$nl", '))
p.cgen.resetln(p.cgen.cur_line.replace(f.name + ' (', '/*opt*/printf ("' + fmt + '$nl", '))
continue
}
}
@ -1156,7 +1141,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
p.cgen.set_placeholder(ph, '${typ}_str(')
p.gen(')')
continue
} else {
}
else {
base := p.base_type(T.name)
if base != T.name {
base_type := p.find_type(base)
@ -1184,7 +1170,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
if type_mismatch && f.is_generic {
// println("argument `$arg.name` is generic")
saved_args << got
} else if type_mismatch {
}
else if type_mismatch {
mut j := i
if f.is_method {
j--
@ -1192,14 +1179,16 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
mut nr := '${j+1}th'
if j == 0 {
nr = 'first'
} else if j == 1 {
}
else if j == 1 {
nr = 'second'
} else if j == 2 {
}
else if j == 2 {
nr = 'third'
}
p.error('cannot use type `$typ` as type `$arg.typ` in $nr ' +
'argument to `${f.name}()`')
} else {
p.error('cannot use type `$typ` as type `$arg.typ` in $nr ' + 'argument to `${f.name}()`')
}
else {
saved_args << ''
}
is_interface := p.table.is_interface(arg.typ)
@ -1220,7 +1209,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
// Special case for mutable arrays. We can't `&` function
// results,
// have to use `(array[]){ expr }` hack.
if expected.starts_with('array_') && exp_ptr { //&& !arg.is_mut{
if expected.starts_with('array_') && exp_ptr {
// && !arg.is_mut{
p.cgen.set_placeholder(ph, '& /*111*/ (array[]){')
p.gen('}[0] ')
}
@ -1233,19 +1223,16 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
// println('fn hack expr=$expr')
p.cgen.set_placeholder(ph, '& /*113 e="$expected" g="$got"*/ ($got[]){')
p.gen('}[0] ')
} else {
}
else {
p.cgen.set_placeholder(ph, '& /*114*/')
}
} $else {
p.cgen.set_placeholder(ph, '& /*114*/')
}
}
// println('\ne:"$expected" got:"$got"')
else if ! (expected == 'void*' && got == 'int') &&
! (expected == 'void*' && got == 'byteptr') &&
! (expected == 'byte*' && got.contains(']byte')) &&
! (expected == 'byte*' && got == 'string') &&
else if !(expected == 'void*' && got == 'int') && !(expected == 'void*' && got == 'byteptr') && !(expected == 'byte*' && got.contains(']byte')) && !(expected == 'byte*' && got == 'string') &&
// ! (expected == 'void*' && got == 'array_int') {
!(expected == 'byte*' && got == 'byteptr') && !p.pref.is_bare {
p.cgen.set_placeholder(ph, '& /*112 e="$expected" g="$got" */')
@ -1296,12 +1283,17 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
// From a given generic function and an argument list matching its signature,
// create a type instantiation
fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
mut r := TypeInst{}
mut r := TypeInst{
}
mut i := 0
mut args := args_
if f.typ != 'void' { args << f.typ }
if f.typ != 'void' {
args << f.typ
}
for e in args {
if e == '' { continue }
if e == '' {
continue
}
tp := f.type_pars[i]
mut ti := e
if ti.starts_with('fn (') {
@ -1309,7 +1301,9 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
mut found := false
for fa_ in fn_args {
mut fa := fa_
for fa.starts_with('array_') { fa = fa[6..] }
for fa.starts_with('array_') {
fa = fa[6..]
}
if fa == tp {
r.inst[tp] = fa
found = true
@ -1317,10 +1311,14 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
break
}
}
if found { continue }
if found {
continue
}
ti = ti.all_after(') ')
}
for ti.starts_with('array_') { ti = ti[6..] }
for ti.starts_with('array_') {
ti = ti[6..]
}
if r.inst[tp] != '' {
if r.inst[tp] != ti {
p.error('type parameter `$tp` has type ${r.inst[tp]}, not `$ti`')
@ -1330,7 +1328,9 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
// println("extracted $tp => $ti")
r.inst[tp] = ti
i++
if i >= f.type_pars.len { break }
if i >= f.type_pars.len {
break
}
}
if r.inst[f.typ] == '' && f.typ in f.type_pars {
r.inst[f.typ] = '_ANYTYPE_'
@ -1346,9 +1346,10 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
// replace a generic type using TypeInst
fn replace_generic_type(gen_type string, ti &TypeInst) string {
mut typ := gen_type.replace('map_', '')
.replace('varg_', '').trim_right('*')
for typ.starts_with('array_') { typ = typ[6..] }
mut typ := gen_type.replace('map_', '').replace('varg_', '').trim_right('*')
for typ.starts_with('array_') {
typ = typ[6..]
}
if typ in ti.inst {
typ = gen_type.replace(typ, ti.inst[typ])
return typ
@ -1393,15 +1394,17 @@ fn (p mut Parser) register_vargs_stuct(typ string, len int) string {
if !p.table.known_type(vargs_struct) {
p.table.register_type(varg_type)
p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n'
} else {
}
else {
ex_typ := p.table.find_type(vargs_struct)
ex_len := ex_typ.fields[1].name[5..ex_typ.fields[1].name.len - 1].int()
if ex_len > varg_len { varg_len = ex_len }
if ex_len > varg_len {
varg_len = ex_len
}
p.table.rewrite_type(varg_type)
}
p.table.add_field(vargs_struct, 'len', 'int', false, '', .public)
p.table.add_field(vargs_struct, 'args[$varg_len]', typ, false, '', .public)
return vargs_struct
}
@ -1418,28 +1421,27 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
p.check(.comma)
}
varg_type,varg_value := p.tmp_expr()
if varg_type.starts_with('varg_') &&
(values.len > 0 || p.tok == .comma)
{
if varg_type.starts_with('varg_') && (values.len > 0 || p.tok == .comma) {
p.error('You cannot pass additional vargs when forwarding vargs to another function/method')
}
if !f.is_generic {
p.check_types(last_arg.typ, varg_type)
} else {
}
else {
if types.len > 0 {
for t in types {
p.check_types(varg_type, t)
}
}
}
ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') { '&' }
else if !last_arg.typ.ends_with('*') && varg_type.ends_with('*') { '*' }
else { '' }
ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') {'&'}else if !last_arg.typ.ends_with('*') && varg_type.ends_with('*') {'*'}else {''}
types << varg_type
values << '$ref_deref$varg_value'
}
for va in p.table.varg_access {
if va.fn_name != f.name { continue }
if va.fn_name != f.name {
continue
}
if va.index >= values.len {
p.error_with_token_index('variadic arg index out of range: $va.index/${values.len-1}, vargs are 0 indexed', va.tok_idx)
}
@ -1452,9 +1454,11 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
fn (p mut Parser) fn_gen_caller_vargs(f &Fn, varg_type string, values []string) {
is_varg := varg_type.starts_with('varg_')
if is_varg { // forwarding varg
if is_varg {
// forwarding varg
p.cgen.gen('${values[0]}')
} else {
}
else {
vargs_struct := p.register_vargs_stuct(varg_type, values.len)
p.cgen.gen('&($vargs_struct){.len=$values.len,.args={' + values.join(',') + '}}')
}
@ -1462,10 +1466,12 @@ fn (p mut Parser) fn_gen_caller_vargs(f &Fn, varg_type string, values []string)
fn (p mut Parser) register_multi_return_stuct(types []string) string {
typ := '_V_MulRet_' + types.join('_V_').replace('*', '_PTR_')
if p.table.known_type(typ) { return typ }
if p.table.known_type(typ) {
return typ
}
p.table.register_type(Type{
cat: .struct_,
name: typ,
cat: .struct_
name: typ
mod: p.mod
})
for i,t in typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') {
@ -1516,7 +1522,8 @@ fn (p mut Parser) dispatch_generic_fn_instance(f mut Fn, ti &TypeInst) {
if f.is_method {
// TODO: add_method won't add anything on second pass
// p.add_method(f.args[0].typ.trim_right('*'), f)
} else {
}
else {
p.table.register_fn(f)
}
mut gp := p.v.parsers[f.parser_idx]
@ -1529,7 +1536,6 @@ fn (p mut Parser) dispatch_generic_fn_instance(f mut Fn, ti &TypeInst) {
gp.fn_decl()
p.cgen.lines_extra << p.cgen.lines
p.restore_state(saved_state, false, true)
p.cgen.fns << '${p.fn_signature(f)};'
}
@ -1598,7 +1604,9 @@ fn (p &Parser) find_misspelled_local_var(name string, min_match f32) string {
continue
}
n := name.all_after('.')
if var.name == '' || (n.len - var.name.len > 2 || var.name.len - n.len > 2) { continue }
if var.name == '' || (n.len - var.name.len > 2 || var.name.len - n.len > 2) {
continue
}
c := strings.dice_coefficient(var.name, n)
if c > closest {
closest = c
@ -1616,6 +1624,7 @@ fn (fns []Fn) contains(f Fn) bool {
}
return false
}
fn (p &Parser) fn_signature(f &Fn) string {
return '$f.typ ${f.name}(${f.str_args(p.table)})'
}

View File

@ -1159,6 +1159,20 @@ pub fn vfmt(args[]string) {
println('v fmt can only be used on .v files')
exit(1)
}
println('WIP')
/*
vexe := vexe_path()
//launch_tool('vfmt', '-d vfmt')
vroot := os.dir(vexe)
os.chdir(vroot)
ret := os.system('$vexe -o $vroot/tools/vfmt -d vfmt v.v')
if ret != 0 {
println('err')
return
}
os.exec('$vroot/tools/vfmt $file') or { panic(err) }
//if !os.exists('
*/
}
pub fn create_symlink() {

View File

@ -853,6 +853,9 @@ fn (p &Parser) strtok() string {
return p.lit
}
if p.tok == .chartoken {
if p.lit == '`' {
return '`\\$p.lit`'
}
return '`$p.lit`'
}
if p.tok == .str {
@ -2902,6 +2905,7 @@ fn (p mut Parser) attribute() {
fn (p mut Parser) defer_st() {
p.check(.key_defer)
p.fspace()
p.check(.lcbr)
pos := p.cgen.lines.len
// Save everything inside the defer block to `defer_text`.

View File

@ -75,8 +75,6 @@ fn new_scanner_file(file_path string) &Scanner {
fn new_scanner(text string) &Scanner {
return &Scanner{
text: text
// fmt_out: strings.new_builder(1000)
print_line_on_error: true
print_colored_error: true
print_rel_paths_on_error: true

View File

@ -243,16 +243,16 @@ fn (p &Parser) gen_fmt() {
if s == '' {
return
}
if !p.file_name.contains('scanner.v') {return}
if !p.file_name.contains('fn.v') {return}
path := os.tmpdir() + '/' + p.file_name
println('generating ${path}')
mut out := os.create(path) or {
verror('failed to create fmt.v')
return
}
println('replacing ${p.file_path}...')
os.mv(path, p.file_path)
println('replacing ${p.file_path}...\n')
out.writeln(s)//p.scanner.fmt_out.str().trim_space())
out.close()
os.mv(path, p.file_path)
}