parser: fix a bug with complex ref fn args

pull/2728/head
Alexander Medvednikov 2019-11-10 21:54:28 +03:00
parent 76c27c0b03
commit f30d0ce667
4 changed files with 72 additions and 12 deletions

View File

@ -270,6 +270,18 @@ fn (s mut Scanner) eat_single_newline(){
///////////////////////////////
fn (p mut Parser) mutable_arg_error(i int, arg Var, f Fn) {
mut dots_example := 'mut $p.lit'
if i > 0 {
dots_example = '.., ' + dots_example
}
if i < f.args.len - 1 {
dots_example = dots_example + ',..'
}
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: ' +
'`$f.name($dots_example)`')
}
const (
warn_match_arrow = '=> is no longer needed in match statements, use\n' +
'match foo {

View File

@ -931,8 +931,23 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
// 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 {
p.gen(',')
p.gen(', ')
}
//if f.args[0].typ.ends_with('*') {
//p.gen('&/*119*/')
//}
/*
pos := p.cgen.cur_line.index('/* ? */')
if pos > -1 {
expr := p.cgen.cur_line[pos..]
// TODO hack
// If current expression is a func call, generate the array hack
if expr.contains('(') {
p.cgen.set_placeholder(pos, '(${arg.typ[..arg.typ.len-1]}[]){')
p.gen('}[0] ')
}
}
*/
continue
}
// Reached the final vararg? Quit
@ -948,14 +963,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
// `mut numbers := [1,2,3]; reverse(mut numbers);`
if arg.is_mut {
if p.tok != .key_mut && p.tok == .name {
mut dots_example := 'mut $p.lit'
if i > 0 {
dots_example = '.., ' + dots_example
}
if i < f.args.len - 1 {
dots_example = dots_example + ',..'
}
p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name($dots_example)`')
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...)`')
@ -1105,13 +1113,26 @@ fn (p mut Parser) fn_call_args(f mut Fn) {
p.cgen.set_placeholder(ph, '& /*111*/ (array[]){')
p.gen('}[0] ')
}
else if exp_ptr && expected == got + '*' {
expr := p.cgen.cur_line[ph..]
// TODO hack
// If current expression is a func call, generate the array hack
if expr.contains('(') {
//println('fn hack expr=$expr')
p.cgen.set_placeholder(ph, '& /*113 e="$expected" g="$got"*/ ($got[]){')
p.gen('}[0] ')
} else {
p.cgen.set_placeholder(ph, '& /*114*/')
}
}
// println('\ne:"$expected" got:"$got"')
else if ! (expected == 'void*' && got == 'int') &&
! (expected == 'byte*' && got.contains(']byte')) &&
! (expected == 'byte*' && got == 'string') &&
//! (expected == 'void*' && got == 'array_int') {
! (expected == 'byte*' && got == 'byteptr') {
p.cgen.set_placeholder(ph, '& /*112 EXP:"$expected" GOT:"$got" */')
p.cgen.set_placeholder(ph, '& /*112 e="$expected" g="$got" */')
}
}
}

View File

@ -21,6 +21,8 @@ multi line comment (3)
multi line comment (2)
*/
import time
type myfn fn (int) string
type myfn2 fn (a int, b int) int
@ -119,3 +121,29 @@ fn test_fns() {
// no asserts for now, just test function declarations above
}
struct Foo {
}
fn process_foo(foo &Foo) {
}
fn get_foo() Foo {
return Foo{}
}
// This used to be broken.
fn test_ref_fn_arg() {
process_foo(get_foo())
println(3434)
assert true
/*
res := (time.random().calc_unix())
println(res)
assert true
*/
}

View File

@ -110,7 +110,6 @@ pub fn now() Time {
pub fn random() Time {
now_unix := now().uni
rand_unix := rand.next(now_unix)
return time.unix(rand_unix)
}