Beispiel #1
0
// 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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
// 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)
	}
}
Beispiel #6
0
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 ")
	}
}
Beispiel #7
0
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
}
Beispiel #8
0
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
}
Beispiel #9
0
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)
	}
}
Beispiel #10
0
// 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
}
Beispiel #11
0
// 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
}