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 }
func (r *ref) String() string { if r == nil { return "void" } if len(r.typ) == 0 { return "<nil>" } return fmt8.Join(r.typ, ",") }
func printVarDecl(p *fmt8.Printer, d *VarDecl) { ss := make([]string, len(d.Idents.Idents)) for i, id := range d.Idents.Idents { ss[i] = id.Lit } fmt.Fprint(p, fmt8.Join(ss, ",")) if d.Type != nil { fmt.Fprint(p, " ") printExpr(p, d.Type) } if d.Eq != nil { fmt.Fprint(p, " = ") printExpr(p, d.Exprs) } }
// String returns the function signature (without the argument names). func (t *Func) String() string { // TODO: this is kind of ugly, need some refactor buf := new(bytes.Buffer) fmt.Fprintf(buf, "func (%s) ", fmt8.Join(t.Args, ",")) if len(t.Rets) > 1 { fmt.Fprintf(buf, "(") for i, ret := range t.Rets { if i > 0 { fmt.Fprint(buf, ",") } fmt.Fprint(buf, ret) } fmt.Fprint(buf, ")") } else if len(t.Rets) == 1 { fmt.Fprint(buf, t.Rets[0]) } return buf.String() }
func printOp(p *fmt8.Printer, op op) { switch op := op.(type) { case *arithOp: if op.a == nil { if op.op == "" { fmt.Fprintf(p, "%s = %s\n", op.dest, op.b) } else if op.op == "0" { fmt.Fprintf(p, "%s = 0\n", op.dest) } else { fmt.Fprintf(p, "%s = %s %s\n", op.dest, op.op, op.b) } } else { fmt.Fprintf(p, "%s = %s %s %s\n", op.dest, op.a, op.op, op.b, ) } case *callOp: args := fmt8.Join(op.args, ",") fmt.Fprintf(p, "%s = %s(%s)\n", op.dest, op.f, args) default: panic(fmt.Errorf("invalid or unknown IR op: %T", op)) } }