diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 441259d3f0..8101ea6bbc 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -162,9 +162,7 @@ pub: mut: // func Expr name string - args []Expr - arg_types []table.Type - expr_types []table.Type + args []CallArg is_c bool muts []bool or_block OrExpr @@ -177,15 +175,21 @@ pub: pos token.Position expr Expr // `user` in `user.register()` name string - args []Expr - muts []bool + args []CallArg or_block OrExpr mut: expr_type table.Type // type of `user` receiver_type table.Type // User return_type table.Type - arg_types []table.Type - expr_types []table.Type +} + +pub struct CallArg { +pub: + is_mut bool + expr Expr +mut: + typ table.Type + expected_type table.Type } pub struct Return { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 7b5ef47573..dc1aac8fe7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -229,8 +229,8 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { } call_expr.return_type = f.return_type if f.is_c || call_expr.is_c { - for expr in call_expr.args { - c.expr(expr) + for arg in call_expr.args { + c.expr(arg.expr) } return f.return_type } @@ -242,18 +242,15 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { } // println can print anything if fn_name == 'println' { - call_expr.arg_types = [c.expr(call_expr.args[0])] + call_expr.args[0].typ = c.expr(call_expr.args[0].expr) return f.return_type } - mut arg_types := []table.Type - mut expr_types := []table.Type - for i, arg_expr in call_expr.args { + for i, call_arg in call_expr.args { arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] } c.expected_type = arg.typ - typ := c.expr(arg_expr) - expr_types << typ - // arg_types << typ // arg.typ - arg_types << arg.typ + typ := c.expr(call_arg.expr) + call_expr.args[i].typ = typ + call_expr.args[i].expected_type = arg.typ typ_sym := c.table.get_type_symbol(typ) arg_typ_sym := c.table.get_type_symbol(arg.typ) if !c.table.check(typ, arg.typ) { @@ -270,8 +267,6 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { c.error('!cannot use type `$typ_sym.str()` as type `$arg_typ_sym.str()` in argument ${i+1} to `$fn_name`', call_expr.pos) } } - call_expr.arg_types = arg_types - call_expr.expr_types = expr_types return f.return_type } @@ -281,8 +276,6 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) method_call_expr.expr_type = typ typ_sym := c.table.get_type_symbol(typ) name := method_call_expr.name - mut arg_types := []table.Type - mut expr_types := []table.Type // println('method call $name $method_call_expr.pos.line_nr') if typ_sym.kind == .array && name in ['filter', 'clone', 'repeat'] { if name == 'filter' { @@ -294,7 +287,7 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) }) } else if name == 'repeat' { - c.expr(method_call_expr.args[0]) + c.expr(method_call_expr.args[0].expr) } // need to return `array_xxx` instead of `array` method_call_expr.return_type = typ @@ -316,15 +309,13 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) // if name == 'clone' { // println('CLONE nr args=$method.args.len') // } - for i, arg_expr in method_call_expr.args { + for i, arg in method_call_expr.args { c.expected_type = method.args[i + 1].typ - arg_types << c.expected_type - expr_types << c.expr(arg_expr) + method_call_expr.args[i].expected_type = c.expected_type + method_call_expr.args[i].typ = c.expr(arg.expr) } method_call_expr.receiver_type = method.args[0].typ method_call_expr.return_type = method.return_type - method_call_expr.arg_types = arg_types - method_call_expr.expr_types = expr_types return method.return_type } c.error('type `$typ_sym.name` has no method `$name`', method_call_expr.pos) diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 5e7ba1efdf..eaf5e05c51 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -364,7 +364,7 @@ fn (f mut Fmt) expr(node ast.Expr) { } ast.CallExpr { f.write('${it.name}(') - f.call_args(it.args, it.muts) + f.call_args(it.args) f.write(')') f.or_expr(it.or_block) } @@ -490,7 +490,7 @@ fn (f mut Fmt) expr(node ast.Expr) { ast.MethodCallExpr { f.expr(it.expr) f.write('.' + it.name + '(') - f.call_args(it.args, it.muts) + f.call_args(it.args) f.write(')') f.or_expr(it.or_block) } @@ -561,15 +561,15 @@ fn (f mut Fmt) wrap_long_line() { } } -fn (f mut Fmt) call_args(args []ast.Expr, muts []bool) { +fn (f mut Fmt) call_args(args []ast.CallArg) { for i, arg in args { - if muts[i] { + if arg.is_mut { f.write('mut ') } if i > 0 { f.wrap_long_line() } - f.expr(arg) + f.expr(arg.expr) if i < args.len - 1 { f.write(', ') } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index cb2c5ebbed..d5c73f25b3 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -548,15 +548,15 @@ fn (g mut Gen) expr(node ast.Expr) { name = name[3..] } g.write('${name}(') - if name == 'println' && it.arg_types[0] != table.string_type_idx { + if name == 'println' && it.args[0].typ != table.string_type_idx { // `println(int_str(10))` - sym := g.table.get_type_symbol(it.arg_types[0]) + sym := g.table.get_type_symbol(it.args[0].typ) g.write('${sym.name}_str(') - g.expr(it.args[0]) + g.expr(it.args[0].expr) g.write('))') } else { - g.call_args(it.args, it.muts, it.arg_types, it.expr_types) + g.call_args(it.args) g.write(')') } g.is_c_call = false @@ -778,7 +778,7 @@ fn (g mut Gen) expr(node ast.Expr) { } */ // /////// - g.call_args(it.args, it.muts, it.arg_types, it.expr_types) + g.call_args(it.args) g.write(')') } ast.None { @@ -1125,13 +1125,12 @@ fn (g mut Gen) const_decl(node ast.ConstDecl) { } } -fn (g mut Gen) call_args(args []ast.Expr, muts []bool, arg_types []table.Type, expr_types []table.Type) { - for i, expr in args { - if arg_types.len > 0 { - // typ := arg_types[i] - arg_is_ptr := table.type_is_ptr(arg_types[i]) || arg_types[i] == table.voidptr_type_idx - expr_is_ptr := i < expr_types.len && table.type_is_ptr(expr_types[i]) - if muts[i] && !arg_is_ptr { +fn (g mut Gen) call_args(args []ast.CallArg) { + for i, arg in args { + if arg.expected_type != 0 { + arg_is_ptr := table.type_is_ptr(arg.expected_type) || arg.expected_type == table.voidptr_type_idx + expr_is_ptr := table.type_is_ptr(arg.typ) + if arg.is_mut && !arg_is_ptr { g.write('&/*mut*/') } else if arg_is_ptr && !expr_is_ptr { @@ -1142,7 +1141,7 @@ fn (g mut Gen) call_args(args []ast.Expr, muts []bool, arg_types []table.Type, e g.write('*/*d*/') } } - g.expr(expr) + g.expr(arg.expr) if i != args.len - 1 { g.write(', ') } diff --git a/vlib/v/gen/jsgen.v b/vlib/v/gen/jsgen.v index ec6c904fe0..23be14a5c9 100644 --- a/vlib/v/gen/jsgen.v +++ b/vlib/v/gen/jsgen.v @@ -141,8 +141,8 @@ fn (g mut JsGen) expr(node ast.Expr) { } ast.CallExpr { g.write('${it.name}(') - for i, expr in it.args { - g.expr(expr) + for i, arg in it.args { + g.expr(arg.expr) if i != it.args.len - 1 { g.write(', ') } diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index ec7e39a505..71943ce6b9 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -361,7 +361,7 @@ fn (g mut Gen) expr(node ast.Expr) { ast.StructInit {} ast.CallExpr { if it.name == 'println' || it.name == 'print' { - expr := it.args[0] + expr := it.args[0].expr g.gen_print_from_expr(expr) } /* diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 6ae198ef4e..e543a7e9c3 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -13,7 +13,7 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { name := p.check_name() fn_name := if is_c { 'C.$name' } else if mod.len > 0 { '${mod}.$name' } else { name } p.check(.lpar) - args,muts := p.call_args() + args := p.call_args() mut or_stmts := []ast.Stmt if p.tok.kind == .key_orelse { p.next() @@ -22,9 +22,7 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { node := ast.CallExpr{ name: fn_name args: args - muts: muts // tok: tok - pos: tok.position() is_c: is_c or_block: ast.OrExpr{ @@ -34,25 +32,25 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { return node } -pub fn (p mut Parser) call_args() ([]ast.Expr,[]bool) { - mut args := []ast.Expr - mut muts := []bool +pub fn (p mut Parser) call_args() []ast.CallArg { + mut args := []ast.CallArg for p.tok.kind != .rpar { + mut is_mut := false if p.tok.kind == .key_mut { p.check(.key_mut) - muts << true - } - else { - muts << false + is_mut = true } e := p.expr(0) - args << e + args << ast.CallArg{ + is_mut: is_mut + expr: e + } if p.tok.kind != .rpar { p.check(.comma) } } p.check(.rpar) - return args,muts + return args } fn (p mut Parser) fn_decl() ast.FnDecl { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d35f1ef6ef..3fea917919 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -891,7 +891,7 @@ fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr { pos := p.tok.position() if p.tok.kind == .lpar { p.next() - args,muts := p.call_args() + args := p.call_args() mut or_stmts := []ast.Stmt if p.tok.kind == .key_orelse { p.next() @@ -901,7 +901,6 @@ fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr { expr: left name: field_name args: args - muts: muts pos: pos or_block: ast.OrExpr{ stmts: or_stmts