func printOp(p io.Writer, op op) { switch op := op.(type) { case *comment: fmt.Fprintf(p, "// %s\n", op.s) 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: var args string if op.args != nil { 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)) } }
func (r *Ref) String() string { if r == nil { return "<error>" } if r.Void { return "void" } if len(r.List) == 0 { return r.T.String() } return fmt8.Join(r.List, ",") }
func (r *ref) String() string { if r == nil { return "void" } if len(r.lst) == 0 { if r.typ == nil { return "<nil>" } return r.typ.String() } return fmt8.Join(r.TypeList(), ",") }
// String returns the function signature (without the argument names). func (t *Func) String() string { // TODO: this is kind of ugly, need some refactoring 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, " ") fmt.Fprint(buf, t.Rets[0]) } if t.IsBond { fmt.Fprint(buf, " (bond)") } return buf.String() }
func buildReturnStmt(b *builder, stmt *ast.ReturnStmt) tast.Stmt { pos := stmt.Kw.Pos if stmt.Exprs == nil { if b.retType == nil || b.retNamed { return &tast.ReturnStmt{} } b.Errorf(pos, "expects return %s", fmt8.Join(b.retType, ",")) return nil } if b.retType == nil { b.Errorf(pos, "function expects no return value") return nil } src := b.buildExpr(stmt.Exprs) if src == nil { return nil } srcRef := src.R() nret := len(b.retType) nsrc := srcRef.Len() if nret != nsrc { b.Errorf(pos, "expect (%s), returning (%s)", fmt8.Join(b.retType, ","), srcRef, ) return nil } for i := 0; i < nret; i++ { t := b.retType[i] srcType := srcRef.At(i).Type() if !types.CanAssign(t, srcType) { b.Errorf(pos, "expect (%s), returning (%s)", fmt8.Join(b.retType, ","), srcRef, ) return nil } } // insert implicit type casts if srcList, ok := tast.MakeExprList(src); ok { newList := tast.NewExprList() for i, e := range srcList.Exprs { t := e.Type() if types.IsNil(t) { e = tast.NewCast(e, b.retType[i]) } else if v, ok := types.NumConst(t); ok { e = constCast(b, nil, v, e, b.retType[i]) if e == nil { panic("bug") } } newList.Append(e) } src = newList } return &tast.ReturnStmt{src} }
func buildCallExpr(b *builder, expr *ast.CallExpr) tast.Expr { f := b.buildExpr(expr.Func) if f == nil { return nil } pos := ast.ExprPos(expr.Func) fref := f.R() if !fref.IsSingle() { b.Errorf(pos, "%s is not callable", fref) return nil } if t, ok := fref.T.(*types.Type); ok { return buildCast(b, expr, t.T) } builtin, ok := fref.T.(*types.BuiltInFunc) if ok { switch builtin.Name { case "len": return buildCallLen(b, expr, f) case "make": return buildCallMake(b, expr, f) } b.Errorf(pos, "builtin %s() not implemented", builtin.Name) return nil } funcType, ok := fref.T.(*types.Func) if !ok { b.Errorf(pos, "function call on non-callable: %s", fref) return nil } args := buildExprList(b, expr.Args) if args == nil { return nil } argsRef := args.R() nargs := argsRef.Len() if nargs != len(funcType.Args) { b.Errorf(ast.ExprPos(expr), "argument expects (%s), got (%s)", fmt8.Join(funcType.Args, ","), args, ) return nil } // type check on each argument for i := 0; i < nargs; i++ { argType := argsRef.At(i).Type() 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, ) return nil } } // insert casting when it is a literal expression list. callArgs, ok := tast.MakeExprList(args) if ok { castedArgs := tast.NewExprList() for i := 0; i < nargs; i++ { argExpr := callArgs.Exprs[i] argType := argExpr.Type() expect := funcType.Args[i].T // insert auto casts for consts if types.IsNil(argType) { castedArgs.Append(tast.NewCast(argExpr, expect)) } else if _, ok := types.NumConst(argType); ok { castedArgs.Append(tast.NewCast(argExpr, expect)) } else { castedArgs.Append(argExpr) } } args = castedArgs } retRef := tast.Void for _, t := range funcType.RetTypes { retRef = tast.AppendRef(retRef, tast.NewRef(t)) } return &tast.CallExpr{f, args, retRef} }