Esempio n. 1
0
func (p *parser) fnArgs(c *ast.CallExpr) {
	for {
		if tok := p.peek(); tok.Type == scan.Rparen {
			break
		}

		c.Args = append(c.Args, p.asgmnt())

		if tok := p.peek(); tok.Type == scan.Comma {
			p.next()
			if tok := p.peek(); tok.Type == scan.Rparen {
				p.errorf(tok.Span().Start, "trailing ',' in function call")
			}
		} else {
			break
		}
	}
	c.Rparen = p.expect(scan.Rparen)
}
Esempio n. 2
0
// call type checks a call expression.
func (c *checker) call(x *operand, e *ast.CallExpr) exprType {
	// if there is no forward declaration of the function
	// it is assumed to be variadic and returns an int
	ident, ok := e.Fun.(*ast.Ident)
	if ok {
		var y operand
		c.ident(&y, ident, true)
		if y.mode == invalid {
			pos := e.Span().Start
			result := NewVar(pos, 0, ident.Name, Typ[Int], nil)
			sig := NewSignature(nil, result, true)
			fun := NewFunc(pos, GlobalStatic, ident.Name, sig)
			fwrd := NewFwrd(ident.Name, fun)
			c.declare(Fwd, c.scope, ident, fwrd, scan.NoPos)
		}
	}
	c.expr(x, e.Fun)

	invalidArgs := false
	var y operand
	for _, arg := range e.Args {
		c.expr(&y, arg)
		if isRecord(y.typ) {
			c.errorf(arg.Span().Start, "struct/union passing by value is not supported")
			invalidArgs = true
		}
	}
	if invalidArgs {
		goto Error
	}

	switch x.mode {
	case invalid:
		x.expr = e
		return statement

	default:
		sig, _ := x.typ.Underlying().(*Signature)
		if sig == nil {
			c.errorf(e.Span().Start, "cannot call a non-function %v", x)
			goto Error
		}

		params := sig.Params()
		numParams := 0
		if params != nil {
			numParams = params.Len()
		}
		if !sig.Variadic() && len(e.Args) != numParams {
			c.errorf(e.Lparen.Span().Start, "expected %d arguments, but function call passed %d arguments", numParams, len(e.Args))
			goto Error
		}

		if sig.Variadic() && numParams != 0 && len(e.Args) < numParams {
			c.errorf(e.Lparen.Span().Start, "expected at least %d arguments for variadic function, but function call passed %d arguments", numParams, len(e.Args))
		}

		// don't need to check the individual arguments, because we don't support passing records, so everything else
		// is a pointer or integer and pointers can be passed to integer and vice versa

		x.typ = sig.Result().Type().Underlying()
		if x.typ == Typ[Void] {
			x.mode = novalue
		}

		return statement
	}

Error:
	x.mode = invalid
	x.expr = e
	return statement
}