parser/checker/gen: update call args to use ast.CallArg

pull/4024/head
Joe Conigliaro 2020-03-14 21:11:43 +11:00
parent 6752fed9f2
commit cc338df77f
8 changed files with 53 additions and 62 deletions

View File

@ -162,9 +162,7 @@ pub:
mut: mut:
// func Expr // func Expr
name string name string
args []Expr args []CallArg
arg_types []table.Type
expr_types []table.Type
is_c bool is_c bool
muts []bool muts []bool
or_block OrExpr or_block OrExpr
@ -177,15 +175,21 @@ pub:
pos token.Position pos token.Position
expr Expr // `user` in `user.register()` expr Expr // `user` in `user.register()`
name string name string
args []Expr args []CallArg
muts []bool
or_block OrExpr or_block OrExpr
mut: mut:
expr_type table.Type // type of `user` expr_type table.Type // type of `user`
receiver_type table.Type // User receiver_type table.Type // User
return_type table.Type 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 { pub struct Return {

View File

@ -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 call_expr.return_type = f.return_type
if f.is_c || call_expr.is_c { if f.is_c || call_expr.is_c {
for expr in call_expr.args { for arg in call_expr.args {
c.expr(expr) c.expr(arg.expr)
} }
return f.return_type 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 // println can print anything
if fn_name == 'println' { 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 return f.return_type
} }
mut arg_types := []table.Type for i, call_arg in call_expr.args {
mut expr_types := []table.Type
for i, arg_expr in call_expr.args {
arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] } 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 c.expected_type = arg.typ
typ := c.expr(arg_expr) typ := c.expr(call_arg.expr)
expr_types << typ call_expr.args[i].typ = typ
// arg_types << typ // arg.typ call_expr.args[i].expected_type = arg.typ
arg_types << arg.typ
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
arg_typ_sym := c.table.get_type_symbol(arg.typ) arg_typ_sym := c.table.get_type_symbol(arg.typ)
if !c.table.check(typ, 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) 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 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 method_call_expr.expr_type = typ
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
name := method_call_expr.name 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') // println('method call $name $method_call_expr.pos.line_nr')
if typ_sym.kind == .array && name in ['filter', 'clone', 'repeat'] { if typ_sym.kind == .array && name in ['filter', 'clone', 'repeat'] {
if name == 'filter' { 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' { 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` // need to return `array_xxx` instead of `array`
method_call_expr.return_type = typ 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' { // if name == 'clone' {
// println('CLONE nr args=$method.args.len') // 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 c.expected_type = method.args[i + 1].typ
arg_types << c.expected_type method_call_expr.args[i].expected_type = c.expected_type
expr_types << c.expr(arg_expr) method_call_expr.args[i].typ = c.expr(arg.expr)
} }
method_call_expr.receiver_type = method.args[0].typ method_call_expr.receiver_type = method.args[0].typ
method_call_expr.return_type = method.return_type 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 return method.return_type
} }
c.error('type `$typ_sym.name` has no method `$name`', method_call_expr.pos) c.error('type `$typ_sym.name` has no method `$name`', method_call_expr.pos)

View File

@ -364,7 +364,7 @@ fn (f mut Fmt) expr(node ast.Expr) {
} }
ast.CallExpr { ast.CallExpr {
f.write('${it.name}(') f.write('${it.name}(')
f.call_args(it.args, it.muts) f.call_args(it.args)
f.write(')') f.write(')')
f.or_expr(it.or_block) f.or_expr(it.or_block)
} }
@ -490,7 +490,7 @@ fn (f mut Fmt) expr(node ast.Expr) {
ast.MethodCallExpr { ast.MethodCallExpr {
f.expr(it.expr) f.expr(it.expr)
f.write('.' + it.name + '(') f.write('.' + it.name + '(')
f.call_args(it.args, it.muts) f.call_args(it.args)
f.write(')') f.write(')')
f.or_expr(it.or_block) 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 { for i, arg in args {
if muts[i] { if arg.is_mut {
f.write('mut ') f.write('mut ')
} }
if i > 0 { if i > 0 {
f.wrap_long_line() f.wrap_long_line()
} }
f.expr(arg) f.expr(arg.expr)
if i < args.len - 1 { if i < args.len - 1 {
f.write(', ') f.write(', ')
} }

View File

@ -548,15 +548,15 @@ fn (g mut Gen) expr(node ast.Expr) {
name = name[3..] name = name[3..]
} }
g.write('${name}(') 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))` // `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.write('${sym.name}_str(')
g.expr(it.args[0]) g.expr(it.args[0].expr)
g.write('))') g.write('))')
} }
else { else {
g.call_args(it.args, it.muts, it.arg_types, it.expr_types) g.call_args(it.args)
g.write(')') g.write(')')
} }
g.is_c_call = false 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(')') g.write(')')
} }
ast.None { 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) { fn (g mut Gen) call_args(args []ast.CallArg) {
for i, expr in args { for i, arg in args {
if arg_types.len > 0 { if arg.expected_type != 0 {
// typ := arg_types[i] arg_is_ptr := table.type_is_ptr(arg.expected_type) || arg.expected_type == table.voidptr_type_idx
arg_is_ptr := table.type_is_ptr(arg_types[i]) || arg_types[i] == table.voidptr_type_idx expr_is_ptr := table.type_is_ptr(arg.typ)
expr_is_ptr := i < expr_types.len && table.type_is_ptr(expr_types[i]) if arg.is_mut && !arg_is_ptr {
if muts[i] && !arg_is_ptr {
g.write('&/*mut*/') g.write('&/*mut*/')
} }
else if arg_is_ptr && !expr_is_ptr { 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.write('*/*d*/')
} }
} }
g.expr(expr) g.expr(arg.expr)
if i != args.len - 1 { if i != args.len - 1 {
g.write(', ') g.write(', ')
} }

View File

@ -141,8 +141,8 @@ fn (g mut JsGen) expr(node ast.Expr) {
} }
ast.CallExpr { ast.CallExpr {
g.write('${it.name}(') g.write('${it.name}(')
for i, expr in it.args { for i, arg in it.args {
g.expr(expr) g.expr(arg.expr)
if i != it.args.len - 1 { if i != it.args.len - 1 {
g.write(', ') g.write(', ')
} }

View File

@ -361,7 +361,7 @@ fn (g mut Gen) expr(node ast.Expr) {
ast.StructInit {} ast.StructInit {}
ast.CallExpr { ast.CallExpr {
if it.name == 'println' || it.name == 'print' { if it.name == 'println' || it.name == 'print' {
expr := it.args[0] expr := it.args[0].expr
g.gen_print_from_expr(expr) g.gen_print_from_expr(expr)
} }
/* /*

View File

@ -13,7 +13,7 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
name := p.check_name() name := p.check_name()
fn_name := if is_c { 'C.$name' } else if mod.len > 0 { '${mod}.$name' } else { name } fn_name := if is_c { 'C.$name' } else if mod.len > 0 { '${mod}.$name' } else { name }
p.check(.lpar) p.check(.lpar)
args,muts := p.call_args() args := p.call_args()
mut or_stmts := []ast.Stmt mut or_stmts := []ast.Stmt
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
p.next() p.next()
@ -22,9 +22,7 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
node := ast.CallExpr{ node := ast.CallExpr{
name: fn_name name: fn_name
args: args args: args
muts: muts
// tok: tok // tok: tok
pos: tok.position() pos: tok.position()
is_c: is_c is_c: is_c
or_block: ast.OrExpr{ or_block: ast.OrExpr{
@ -34,25 +32,25 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
return node return node
} }
pub fn (p mut Parser) call_args() ([]ast.Expr,[]bool) { pub fn (p mut Parser) call_args() []ast.CallArg {
mut args := []ast.Expr mut args := []ast.CallArg
mut muts := []bool
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
mut is_mut := false
if p.tok.kind == .key_mut { if p.tok.kind == .key_mut {
p.check(.key_mut) p.check(.key_mut)
muts << true is_mut = true
}
else {
muts << false
} }
e := p.expr(0) e := p.expr(0)
args << e args << ast.CallArg{
is_mut: is_mut
expr: e
}
if p.tok.kind != .rpar { if p.tok.kind != .rpar {
p.check(.comma) p.check(.comma)
} }
} }
p.check(.rpar) p.check(.rpar)
return args,muts return args
} }
fn (p mut Parser) fn_decl() ast.FnDecl { fn (p mut Parser) fn_decl() ast.FnDecl {

View File

@ -891,7 +891,7 @@ fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr {
pos := p.tok.position() pos := p.tok.position()
if p.tok.kind == .lpar { if p.tok.kind == .lpar {
p.next() p.next()
args,muts := p.call_args() args := p.call_args()
mut or_stmts := []ast.Stmt mut or_stmts := []ast.Stmt
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
p.next() p.next()
@ -901,7 +901,6 @@ fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr {
expr: left expr: left
name: field_name name: field_name
args: args args: args
muts: muts
pos: pos pos: pos
or_block: ast.OrExpr{ or_block: ast.OrExpr{
stmts: or_stmts stmts: or_stmts