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:
parent
81045023c4
commit
569b32bd1e
1
v.v
1
v.v
@ -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
|
||||
|
@ -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)})'
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user