Beispiel #1
0
func buildCallExpr(b *builder, expr *ast.CallExpr) *ref {
	f := b.buildExpr(expr.Func)
	if f == nil {
		return nil
	}

	pos := ast.ExprPos(expr.Func)

	if !f.IsSingle() {
		b.Errorf(pos, "expression list is not callable")
		return nil
	}

	funcType, ok := f.Type().(*types.Func) // the func sig in the builder
	if !ok {
		// not a function
		b.Errorf(pos, "function call on non-callable")
		return nil
	}

	args := buildExprList(b, expr.Args)
	if args == nil {
		return nil
	}

	if args.Len() != len(funcType.Args) {
		b.Errorf(ast.ExprPos(expr), "argument expects (%s), got (%s)",
			fmt8.Join(funcType.Args, ","), fmt8.Join(args.typ, ","),
		)
		return nil
	}

	// type check on parameters
	for i, argType := range args.typ {
		expect := funcType.Args[i].T
		if !types.CanAssign(expect, argType) {
			pos := ast.ExprPos(expr.Args.Exprs[i])
			b.Errorf(pos, "argument %d expects %s, got %s",
				i+1, expect, argType,
			)
		}
	}

	ret := new(ref)
	ret.typ = funcType.RetTypes
	for _, t := range funcType.RetTypes {
		ret.ir = append(ret.ir, b.f.NewTemp(t.Size(), types.IsByte(t)))
	}

	// call the func in IR
	b.b.Call(ret.ir, f.IR(), funcType.Sig, args.ir...)

	return ret
}
Beispiel #2
0
func (b *builder) newLocal(t types.T, name string) ir.Ref {
	return b.f.NewLocal(t.Size(), name, types.IsByte(t))
}
Beispiel #3
0
func (b *builder) newTemp(t types.T) *ref {
	return newRef(t, b.f.NewTemp(t.Size(), types.IsByte(t)))
}