// storeParams handles parameters // // If the parameters include an ellipsis we need to copy parameters into // an interface{} array as follows. // // params := []interface{}{} // params[0] = p1 // params[1] = p2 // for i, p := range ellipsisParam { // params[2+i] = p // } // // If not it is better to add the params to the call directly for performance // reasons func storeParams(params *ast.FieldList) ([]ast.Stmt, bool, error) { // Is there an ellipsis parameter? listlen := len(params.List) if listlen > 0 { last := params.List[len(params.List)-1] if _, ok := last.Type.(*ast.Ellipsis); ok { code := fmt.Sprintf("\tut__params := make([]interface{}, %d + len(%s))\n", params.NumFields()-1, last.Names[0].Name) i := 0 for _, f := range params.List { for _, n := range f.Names { if _, ok := f.Type.(*ast.Ellipsis); ok { // Ellipsis expression code += fmt.Sprintf(` for j, p := range %s { ut__params[%d+j] = p } `, n.Name, i) } else { code += fmt.Sprintf("\tut__params[%d] = %s\n", i, n.Name) } i++ } } stmts, err := parseCodeBlock(code) return stmts, true, err } } return nil, false, nil }
func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Pos, bool) { n := fields.NumFields() ts := make([]Type, n) ns := make([]*ast.Ident, n) ps := make([]token.Pos, n) bad := false if fields != nil { i := 0 for _, f := range fields.List { t := a.compileType(f.Type, allowRec) if t == nil { bad = true } if f.Names == nil { ns[i] = nil ts[i] = t ps[i] = f.Type.Pos() i++ continue } for _, n := range f.Names { ns[i] = n ts[i] = t ps[i] = n.Pos() i++ } } } return ts, ns, ps, bad }
func (f *File) validParams(params *ast.FieldList) *Error { if params == nil { panic("ERROR: params fieldlist should never be nil") } if params.List == nil { return nil } for i := 0; i < params.NumFields(); i++ { field := params.List[i] if field == nil { return &Error{errors.New(fmt.Sprint("ERROR nil field, anonymous fields not allowed!!")), params.Pos()} } if len(field.Names) != 1 { panic("ERROR len(field.Names) != 1!!") } name := field.Names[0] if name == nil { panic("ERROR name == nil, this shouldn't occur") } typ := f.Info.TypeOf(field.Type) if e := f.validParamType(typ); e != nil { e.Pos = field.Pos() return e } } return nil }
func (f *File) validResults(results *ast.FieldList) *Error { if results == nil || results.List == nil { return nil } if results.NumFields() != 1 { err := fmt.Sprint("ERROR: can only return at most one result, not:", results.NumFields()) return &Error{errors.New(err), results.Pos()} } result := results.List[0] if result == nil { return nil } if result.Names != nil { return &Error{errors.New(fmt.Sprint("ERROR: can only return nonnamed result, not:", result.Names)), result.Pos()} } typ := f.Info.TypeOf(result.Type) if err := f.validResultType(typ); err != nil { err.Pos = result.Pos() if f.validVarDeclType(typ) == nil { err.Err = errors.New(fmt.Sprint(err.Err) + ", type only valid as a var decl, or param") } else if f.validParamType(typ) == nil { err.Err = errors.New(fmt.Sprint(err.Err) + ", type only valid as func param type") } return err } return nil }
// Sets multiLine to true if the signature spans multiple lines. func (p *printer) signature(params, result *ast.FieldList, multiLine *bool) { p.parameters(params, multiLine) n := result.NumFields() if n > 0 { p.print(blank) if n == 1 && result.List[0].Names == nil { // single anonymous result; no ()'s p.expr(result.List[0].Type, multiLine) return } p.parameters(result, multiLine) } }
func (p *printer) funcreturn(result *ast.FieldList) { n := result.NumFields() if n > 0 { p.print(blank) if n == 1 && result.List[0].Names == nil { // single anonymous result; no ()'s p.expr(result.List[0].Type) return } p.parameters(result) } else { p.print("void ") } }
func (fs *FileSet) parseFieldList(fl *ast.FieldList) []gen.StructField { if fl == nil || fl.NumFields() == 0 { return nil } out := make([]gen.StructField, 0, fl.NumFields()) for i, field := range fl.List { fds := fs.getField(field) if len(fds) > 0 { out = append(out, fds...) } else { warnf(" \u26a0 ignored struct field %d\n", i) } } return out }
func (fs *FileSet) parseFieldList(fl *ast.FieldList) []gen.StructField { if fl == nil || fl.NumFields() == 0 { return nil } out := make([]gen.StructField, 0, fl.NumFields()) for _, field := range fl.List { pushstate(fieldName(field)) fds := fs.getField(field) if len(fds) > 0 { out = append(out, fds...) } else { warnln("ignored.") } popstate() } return out }
func (p *printer) signature(params, result *ast.FieldList) { if params != nil { p.parameters(params) } else { p.print(token.LPAREN, token.RPAREN) } n := result.NumFields() if n > 0 { // result != nil p.print(blank) if n == 1 && result.List[0].Names == nil { // single anonymous result; no ()'s p.expr(stripParensAlways(result.List[0].Type)) return } p.parameters(result) } }
// belongsToReceiver checks if a function with these return types belongs to // a receiver. If it belongs to a receiver, the name of that receiver will be // returned with ok set to true. Otherwise ok will be false. // Behavior should be similar to how go doc decides when a function belongs to // a receiver (gosrc/pkg/go/doc/reader.go). func (p *tagParser) belongsToReceiver(types *ast.FieldList) (name string, ok bool) { if types == nil || types.NumFields() == 0 { return "", false } // If the first return type has more than 1 result associated with // it, it should not belong to that receiver. // Similar behavior as go doc (go source/. if len(types.List[0].Names) > 1 { return "", false } // get name of the first return type t := getType(types.List[0].Type, false) // check if it exists in the current list of known types for _, knownType := range p.types { if t == knownType { return knownType, true } } return "", false }
// declReturnValues builds the return part of the call // func declReturnValues(results *ast.FieldList) ([]ast.Stmt, error) { if results.NumFields() == 0 { return nil, nil } stmts := []ast.Stmt{} for i, f := range results.List { // var r_X type stmts = append(stmts, &ast.DeclStmt{ Decl: &ast.GenDecl{ Tok: token.VAR, Specs: []ast.Spec{ &ast.ValueSpec{ Names: []*ast.Ident{ ast.NewIdent(fmt.Sprintf("r_%d", i)), }, Type: f.Type, }, }, }, }) // if r[X] != nil { // r_X = r[X].(type) // } stmts = append(stmts, &ast.IfStmt{ Cond: &ast.BinaryExpr{ X: &ast.IndexExpr{ X: ast.NewIdent("r"), Index: &ast.BasicLit{ Kind: token.INT, Value: fmt.Sprintf("%d", i), }, }, Op: token.NEQ, Y: ast.NewIdent("nil"), }, Body: &ast.BlockStmt{ List: []ast.Stmt{ &ast.AssignStmt{ Lhs: []ast.Expr{ ast.NewIdent(fmt.Sprintf("r_%d", i)), }, Tok: token.ASSIGN, Rhs: []ast.Expr{ &ast.TypeAssertExpr{ X: &ast.IndexExpr{ X: ast.NewIdent("r"), Index: &ast.BasicLit{ Kind: token.INT, Value: fmt.Sprintf("%d", i), }, }, Type: f.Type, }, }, }, }, }, }) } return stmts, nil }