// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated by the codec package. DO NOT EDIT.

//lint:file-ignore SA1019 go/doc uses *ast.Object, so we must preserve it.

package godoc

import (
	"go/ast"
	"go/token"
	"golang.org/x/pkgsite/internal/godoc/codec"
)

// Fields of ast_ArrayType: Lbrack Len Elt

func encode_ast_ArrayType(e *codec.Encoder, x *ast.ArrayType) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Lbrack != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Lbrack))
	}
	if x.Len != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Len)
	}
	if x.Elt != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Elt)
	}
	e.EndStruct()
}

func decode_ast_ArrayType(d *codec.Decoder, p **ast.ArrayType) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ArrayType)
		return
	}
	var x ast.ArrayType
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Lbrack = token.Pos(d.DecodeInt())
		case 1:
			x.Len = d.DecodeAny().(ast.Expr)
		case 2:
			x.Elt = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.ArrayType", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ArrayType{},
		func(e *codec.Encoder, x any) { encode_ast_ArrayType(e, x.(*ast.ArrayType)) },
		func(d *codec.Decoder) any {
			var x *ast.ArrayType
			decode_ast_ArrayType(d, &x)
			return x
		})
}

// Fields of ast_AssignStmt: Lhs TokPos Tok Rhs

func encode_ast_AssignStmt(e *codec.Encoder, x *ast.AssignStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Lhs != nil {
		e.EncodeUint(0)
		encode_slice_ast_Expr(e, x.Lhs)
	}
	if x.TokPos != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.TokPos))
	}
	if x.Tok != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Tok))
	}
	if x.Rhs != nil {
		e.EncodeUint(3)
		encode_slice_ast_Expr(e, x.Rhs)
	}
	e.EndStruct()
}

func decode_ast_AssignStmt(d *codec.Decoder, p **ast.AssignStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.AssignStmt)
		return
	}
	var x ast.AssignStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_slice_ast_Expr(d, &x.Lhs)
		case 1:
			x.TokPos = token.Pos(d.DecodeInt())
		case 2:
			x.Tok = token.Token(d.DecodeInt())
		case 3:
			decode_slice_ast_Expr(d, &x.Rhs)
		default:
			d.UnknownField("ast.AssignStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.AssignStmt{},
		func(e *codec.Encoder, x any) { encode_ast_AssignStmt(e, x.(*ast.AssignStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.AssignStmt
			decode_ast_AssignStmt(d, &x)
			return x
		})
}

// Fields of ast_BadDecl: From To

func encode_ast_BadDecl(e *codec.Encoder, x *ast.BadDecl) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.From != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.From))
	}
	if x.To != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.To))
	}
	e.EndStruct()
}

func decode_ast_BadDecl(d *codec.Decoder, p **ast.BadDecl) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BadDecl)
		return
	}
	var x ast.BadDecl
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.From = token.Pos(d.DecodeInt())
		case 1:
			x.To = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.BadDecl", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BadDecl{},
		func(e *codec.Encoder, x any) { encode_ast_BadDecl(e, x.(*ast.BadDecl)) },
		func(d *codec.Decoder) any {
			var x *ast.BadDecl
			decode_ast_BadDecl(d, &x)
			return x
		})
}

// Fields of ast_BadExpr: From To

func encode_ast_BadExpr(e *codec.Encoder, x *ast.BadExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.From != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.From))
	}
	if x.To != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.To))
	}
	e.EndStruct()
}

func decode_ast_BadExpr(d *codec.Decoder, p **ast.BadExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BadExpr)
		return
	}
	var x ast.BadExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.From = token.Pos(d.DecodeInt())
		case 1:
			x.To = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.BadExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BadExpr{},
		func(e *codec.Encoder, x any) { encode_ast_BadExpr(e, x.(*ast.BadExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.BadExpr
			decode_ast_BadExpr(d, &x)
			return x
		})
}

// Fields of ast_BadStmt: From To

func encode_ast_BadStmt(e *codec.Encoder, x *ast.BadStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.From != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.From))
	}
	if x.To != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.To))
	}
	e.EndStruct()
}

func decode_ast_BadStmt(d *codec.Decoder, p **ast.BadStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BadStmt)
		return
	}
	var x ast.BadStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.From = token.Pos(d.DecodeInt())
		case 1:
			x.To = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.BadStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BadStmt{},
		func(e *codec.Encoder, x any) { encode_ast_BadStmt(e, x.(*ast.BadStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.BadStmt
			decode_ast_BadStmt(d, &x)
			return x
		})
}

// Fields of ast_BasicLit: ValuePos Kind Value

func encode_ast_BasicLit(e *codec.Encoder, x *ast.BasicLit) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.ValuePos != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.ValuePos))
	}
	if x.Kind != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Kind))
	}
	if x.Value != "" {
		e.EncodeUint(2)
		e.EncodeString(x.Value)
	}
	e.EndStruct()
}

func decode_ast_BasicLit(d *codec.Decoder, p **ast.BasicLit) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BasicLit)
		return
	}
	var x ast.BasicLit
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.ValuePos = token.Pos(d.DecodeInt())
		case 1:
			x.Kind = token.Token(d.DecodeInt())
		case 2:
			x.Value = d.DecodeString()
		default:
			d.UnknownField("ast.BasicLit", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BasicLit{},
		func(e *codec.Encoder, x any) { encode_ast_BasicLit(e, x.(*ast.BasicLit)) },
		func(d *codec.Decoder) any {
			var x *ast.BasicLit
			decode_ast_BasicLit(d, &x)
			return x
		})
}

// Fields of ast_BinaryExpr: X OpPos Op Y

func encode_ast_BinaryExpr(e *codec.Encoder, x *ast.BinaryExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.OpPos != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.OpPos))
	}
	if x.Op != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Op))
	}
	if x.Y != nil {
		e.EncodeUint(3)
		e.EncodeAny(x.Y)
	}
	e.EndStruct()
}

func decode_ast_BinaryExpr(d *codec.Decoder, p **ast.BinaryExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BinaryExpr)
		return
	}
	var x ast.BinaryExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			x.OpPos = token.Pos(d.DecodeInt())
		case 2:
			x.Op = token.Token(d.DecodeInt())
		case 3:
			x.Y = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.BinaryExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BinaryExpr{},
		func(e *codec.Encoder, x any) { encode_ast_BinaryExpr(e, x.(*ast.BinaryExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.BinaryExpr
			decode_ast_BinaryExpr(d, &x)
			return x
		})
}

// Fields of ast_BlockStmt: Lbrace List Rbrace

func encode_ast_BlockStmt(e *codec.Encoder, x *ast.BlockStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Lbrace != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Lbrace))
	}
	if x.List != nil {
		e.EncodeUint(1)
		encode_slice_ast_Stmt(e, x.List)
	}
	if x.Rbrace != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Rbrace))
	}
	e.EndStruct()
}

func decode_ast_BlockStmt(d *codec.Decoder, p **ast.BlockStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BlockStmt)
		return
	}
	var x ast.BlockStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Lbrace = token.Pos(d.DecodeInt())
		case 1:
			decode_slice_ast_Stmt(d, &x.List)
		case 2:
			x.Rbrace = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.BlockStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BlockStmt{},
		func(e *codec.Encoder, x any) { encode_ast_BlockStmt(e, x.(*ast.BlockStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.BlockStmt
			decode_ast_BlockStmt(d, &x)
			return x
		})
}

// Fields of ast_BranchStmt: TokPos Tok Label

func encode_ast_BranchStmt(e *codec.Encoder, x *ast.BranchStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.TokPos != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.TokPos))
	}
	if x.Tok != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Tok))
	}
	if x.Label != nil {
		e.EncodeUint(2)
		encode_ast_Ident(e, x.Label)
	}
	e.EndStruct()
}

func decode_ast_BranchStmt(d *codec.Decoder, p **ast.BranchStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.BranchStmt)
		return
	}
	var x ast.BranchStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.TokPos = token.Pos(d.DecodeInt())
		case 1:
			x.Tok = token.Token(d.DecodeInt())
		case 2:
			decode_ast_Ident(d, &x.Label)
		default:
			d.UnknownField("ast.BranchStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.BranchStmt{},
		func(e *codec.Encoder, x any) { encode_ast_BranchStmt(e, x.(*ast.BranchStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.BranchStmt
			decode_ast_BranchStmt(d, &x)
			return x
		})
}

// Fields of ast_CallExpr: Fun Lparen Args Ellipsis Rparen

func encode_ast_CallExpr(e *codec.Encoder, x *ast.CallExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Fun != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.Fun)
	}
	if x.Lparen != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Lparen))
	}
	if x.Args != nil {
		e.EncodeUint(2)
		encode_slice_ast_Expr(e, x.Args)
	}
	if x.Ellipsis != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.Ellipsis))
	}
	if x.Rparen != 0 {
		e.EncodeUint(4)
		e.EncodeInt(int64(x.Rparen))
	}
	e.EndStruct()
}

func decode_ast_CallExpr(d *codec.Decoder, p **ast.CallExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.CallExpr)
		return
	}
	var x ast.CallExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Fun = d.DecodeAny().(ast.Expr)
		case 1:
			x.Lparen = token.Pos(d.DecodeInt())
		case 2:
			decode_slice_ast_Expr(d, &x.Args)
		case 3:
			x.Ellipsis = token.Pos(d.DecodeInt())
		case 4:
			x.Rparen = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.CallExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.CallExpr{},
		func(e *codec.Encoder, x any) { encode_ast_CallExpr(e, x.(*ast.CallExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.CallExpr
			decode_ast_CallExpr(d, &x)
			return x
		})
}

// Fields of ast_CaseClause: Case List Colon Body

func encode_ast_CaseClause(e *codec.Encoder, x *ast.CaseClause) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Case != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Case))
	}
	if x.List != nil {
		e.EncodeUint(1)
		encode_slice_ast_Expr(e, x.List)
	}
	if x.Colon != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Colon))
	}
	if x.Body != nil {
		e.EncodeUint(3)
		encode_slice_ast_Stmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_CaseClause(d *codec.Decoder, p **ast.CaseClause) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.CaseClause)
		return
	}
	var x ast.CaseClause
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Case = token.Pos(d.DecodeInt())
		case 1:
			decode_slice_ast_Expr(d, &x.List)
		case 2:
			x.Colon = token.Pos(d.DecodeInt())
		case 3:
			decode_slice_ast_Stmt(d, &x.Body)
		default:
			d.UnknownField("ast.CaseClause", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.CaseClause{},
		func(e *codec.Encoder, x any) { encode_ast_CaseClause(e, x.(*ast.CaseClause)) },
		func(d *codec.Decoder) any {
			var x *ast.CaseClause
			decode_ast_CaseClause(d, &x)
			return x
		})
}

// Fields of ast_ChanType: Begin Arrow Dir Value

func encode_ast_ChanType(e *codec.Encoder, x *ast.ChanType) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Begin != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Begin))
	}
	if x.Arrow != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Arrow))
	}
	if x.Dir != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Dir))
	}
	if x.Value != nil {
		e.EncodeUint(3)
		e.EncodeAny(x.Value)
	}
	e.EndStruct()
}

func decode_ast_ChanType(d *codec.Decoder, p **ast.ChanType) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ChanType)
		return
	}
	var x ast.ChanType
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Begin = token.Pos(d.DecodeInt())
		case 1:
			x.Arrow = token.Pos(d.DecodeInt())
		case 2:
			x.Dir = ast.ChanDir(d.DecodeInt())
		case 3:
			x.Value = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.ChanType", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ChanType{},
		func(e *codec.Encoder, x any) { encode_ast_ChanType(e, x.(*ast.ChanType)) },
		func(d *codec.Decoder) any {
			var x *ast.ChanType
			decode_ast_ChanType(d, &x)
			return x
		})
}

// Fields of ast_CommClause: Case Comm Colon Body

func encode_ast_CommClause(e *codec.Encoder, x *ast.CommClause) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Case != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Case))
	}
	if x.Comm != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Comm)
	}
	if x.Colon != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Colon))
	}
	if x.Body != nil {
		e.EncodeUint(3)
		encode_slice_ast_Stmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_CommClause(d *codec.Decoder, p **ast.CommClause) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.CommClause)
		return
	}
	var x ast.CommClause
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Case = token.Pos(d.DecodeInt())
		case 1:
			x.Comm = d.DecodeAny().(ast.Stmt)
		case 2:
			x.Colon = token.Pos(d.DecodeInt())
		case 3:
			decode_slice_ast_Stmt(d, &x.Body)
		default:
			d.UnknownField("ast.CommClause", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.CommClause{},
		func(e *codec.Encoder, x any) { encode_ast_CommClause(e, x.(*ast.CommClause)) },
		func(d *codec.Decoder) any {
			var x *ast.CommClause
			decode_ast_CommClause(d, &x)
			return x
		})
}

// Fields of ast_CommentGroup: List

func encode_ast_CommentGroup(e *codec.Encoder, x *ast.CommentGroup) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.List != nil {
		e.EncodeUint(0)
		encode_slice_ast_Comment(e, x.List)
	}
	e.EndStruct()
}

func decode_ast_CommentGroup(d *codec.Decoder, p **ast.CommentGroup) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.CommentGroup)
		return
	}
	var x ast.CommentGroup
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_slice_ast_Comment(d, &x.List)
		default:
			d.UnknownField("ast.CommentGroup", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.CommentGroup{},
		func(e *codec.Encoder, x any) { encode_ast_CommentGroup(e, x.(*ast.CommentGroup)) },
		func(d *codec.Decoder) any {
			var x *ast.CommentGroup
			decode_ast_CommentGroup(d, &x)
			return x
		})
}

// Fields of ast_Comment: Slash Text

func encode_ast_Comment(e *codec.Encoder, x *ast.Comment) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Slash != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Slash))
	}
	if x.Text != "" {
		e.EncodeUint(1)
		e.EncodeString(x.Text)
	}
	e.EndStruct()
}

func decode_ast_Comment(d *codec.Decoder, p **ast.Comment) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.Comment)
		return
	}
	var x ast.Comment
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Slash = token.Pos(d.DecodeInt())
		case 1:
			x.Text = d.DecodeString()
		default:
			d.UnknownField("ast.Comment", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.Comment{},
		func(e *codec.Encoder, x any) { encode_ast_Comment(e, x.(*ast.Comment)) },
		func(d *codec.Decoder) any {
			var x *ast.Comment
			decode_ast_Comment(d, &x)
			return x
		})
}

// Fields of ast_CompositeLit: Type Lbrace Elts Rbrace Incomplete

func encode_ast_CompositeLit(e *codec.Encoder, x *ast.CompositeLit) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Type != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.Type)
	}
	if x.Lbrace != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Lbrace))
	}
	if x.Elts != nil {
		e.EncodeUint(2)
		encode_slice_ast_Expr(e, x.Elts)
	}
	if x.Rbrace != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.Rbrace))
	}
	if x.Incomplete != false {
		e.EncodeUint(4)
		e.EncodeBool(x.Incomplete)
	}
	e.EndStruct()
}

func decode_ast_CompositeLit(d *codec.Decoder, p **ast.CompositeLit) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.CompositeLit)
		return
	}
	var x ast.CompositeLit
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Type = d.DecodeAny().(ast.Expr)
		case 1:
			x.Lbrace = token.Pos(d.DecodeInt())
		case 2:
			decode_slice_ast_Expr(d, &x.Elts)
		case 3:
			x.Rbrace = token.Pos(d.DecodeInt())
		case 4:
			x.Incomplete = d.DecodeBool()
		default:
			d.UnknownField("ast.CompositeLit", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.CompositeLit{},
		func(e *codec.Encoder, x any) { encode_ast_CompositeLit(e, x.(*ast.CompositeLit)) },
		func(d *codec.Decoder) any {
			var x *ast.CompositeLit
			decode_ast_CompositeLit(d, &x)
			return x
		})
}

// Fields of ast_DeclStmt: Decl

func encode_ast_DeclStmt(e *codec.Encoder, x *ast.DeclStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Decl != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.Decl)
	}
	e.EndStruct()
}

func decode_ast_DeclStmt(d *codec.Decoder, p **ast.DeclStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.DeclStmt)
		return
	}
	var x ast.DeclStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Decl = d.DecodeAny().(ast.Decl)
		default:
			d.UnknownField("ast.DeclStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.DeclStmt{},
		func(e *codec.Encoder, x any) { encode_ast_DeclStmt(e, x.(*ast.DeclStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.DeclStmt
			decode_ast_DeclStmt(d, &x)
			return x
		})
}

// Fields of ast_DeferStmt: Defer Call

func encode_ast_DeferStmt(e *codec.Encoder, x *ast.DeferStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Defer != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Defer))
	}
	if x.Call != nil {
		e.EncodeUint(1)
		encode_ast_CallExpr(e, x.Call)
	}
	e.EndStruct()
}

func decode_ast_DeferStmt(d *codec.Decoder, p **ast.DeferStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.DeferStmt)
		return
	}
	var x ast.DeferStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Defer = token.Pos(d.DecodeInt())
		case 1:
			decode_ast_CallExpr(d, &x.Call)
		default:
			d.UnknownField("ast.DeferStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.DeferStmt{},
		func(e *codec.Encoder, x any) { encode_ast_DeferStmt(e, x.(*ast.DeferStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.DeferStmt
			decode_ast_DeferStmt(d, &x)
			return x
		})
}

// Fields of ast_Ellipsis: Ellipsis Elt

func encode_ast_Ellipsis(e *codec.Encoder, x *ast.Ellipsis) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Ellipsis != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Ellipsis))
	}
	if x.Elt != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Elt)
	}
	e.EndStruct()
}

func decode_ast_Ellipsis(d *codec.Decoder, p **ast.Ellipsis) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.Ellipsis)
		return
	}
	var x ast.Ellipsis
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Ellipsis = token.Pos(d.DecodeInt())
		case 1:
			x.Elt = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.Ellipsis", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.Ellipsis{},
		func(e *codec.Encoder, x any) { encode_ast_Ellipsis(e, x.(*ast.Ellipsis)) },
		func(d *codec.Decoder) any {
			var x *ast.Ellipsis
			decode_ast_Ellipsis(d, &x)
			return x
		})
}

// Fields of ast_EmptyStmt: Semicolon Implicit

func encode_ast_EmptyStmt(e *codec.Encoder, x *ast.EmptyStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Semicolon != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Semicolon))
	}
	if x.Implicit != false {
		e.EncodeUint(1)
		e.EncodeBool(x.Implicit)
	}
	e.EndStruct()
}

func decode_ast_EmptyStmt(d *codec.Decoder, p **ast.EmptyStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.EmptyStmt)
		return
	}
	var x ast.EmptyStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Semicolon = token.Pos(d.DecodeInt())
		case 1:
			x.Implicit = d.DecodeBool()
		default:
			d.UnknownField("ast.EmptyStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.EmptyStmt{},
		func(e *codec.Encoder, x any) { encode_ast_EmptyStmt(e, x.(*ast.EmptyStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.EmptyStmt
			decode_ast_EmptyStmt(d, &x)
			return x
		})
}

// Fields of ast_ExprStmt: X

func encode_ast_ExprStmt(e *codec.Encoder, x *ast.ExprStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	e.EndStruct()
}

func decode_ast_ExprStmt(d *codec.Decoder, p **ast.ExprStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ExprStmt)
		return
	}
	var x ast.ExprStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.ExprStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ExprStmt{},
		func(e *codec.Encoder, x any) { encode_ast_ExprStmt(e, x.(*ast.ExprStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.ExprStmt
			decode_ast_ExprStmt(d, &x)
			return x
		})
}

// Fields of ast_FieldList: Opening List Closing

func encode_ast_FieldList(e *codec.Encoder, x *ast.FieldList) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Opening != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Opening))
	}
	if x.List != nil {
		e.EncodeUint(1)
		encode_slice_ast_Field(e, x.List)
	}
	if x.Closing != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Closing))
	}
	e.EndStruct()
}

func decode_ast_FieldList(d *codec.Decoder, p **ast.FieldList) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.FieldList)
		return
	}
	var x ast.FieldList
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Opening = token.Pos(d.DecodeInt())
		case 1:
			decode_slice_ast_Field(d, &x.List)
		case 2:
			x.Closing = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.FieldList", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.FieldList{},
		func(e *codec.Encoder, x any) { encode_ast_FieldList(e, x.(*ast.FieldList)) },
		func(d *codec.Decoder) any {
			var x *ast.FieldList
			decode_ast_FieldList(d, &x)
			return x
		})
}

// Fields of ast_Field: Doc Names Type Tag Comment

func encode_ast_Field(e *codec.Encoder, x *ast.Field) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.Names != nil {
		e.EncodeUint(1)
		encode_slice_ast_Ident(e, x.Names)
	}
	if x.Type != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Type)
	}
	if x.Tag != nil {
		e.EncodeUint(3)
		encode_ast_BasicLit(e, x.Tag)
	}
	if x.Comment != nil {
		e.EncodeUint(4)
		encode_ast_CommentGroup(e, x.Comment)
	}
	e.EndStruct()
}

func decode_ast_Field(d *codec.Decoder, p **ast.Field) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.Field)
		return
	}
	var x ast.Field
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			decode_slice_ast_Ident(d, &x.Names)
		case 2:
			x.Type = d.DecodeAny().(ast.Expr)
		case 3:
			decode_ast_BasicLit(d, &x.Tag)
		case 4:
			decode_ast_CommentGroup(d, &x.Comment)
		default:
			d.UnknownField("ast.Field", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.Field{},
		func(e *codec.Encoder, x any) { encode_ast_Field(e, x.(*ast.Field)) },
		func(d *codec.Decoder) any {
			var x *ast.Field
			decode_ast_Field(d, &x)
			return x
		})
}

// Fields of ast_ForStmt: For Init Cond Post Body

func encode_ast_ForStmt(e *codec.Encoder, x *ast.ForStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.For != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.For))
	}
	if x.Init != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Init)
	}
	if x.Cond != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Cond)
	}
	if x.Post != nil {
		e.EncodeUint(3)
		e.EncodeAny(x.Post)
	}
	if x.Body != nil {
		e.EncodeUint(4)
		encode_ast_BlockStmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_ForStmt(d *codec.Decoder, p **ast.ForStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ForStmt)
		return
	}
	var x ast.ForStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.For = token.Pos(d.DecodeInt())
		case 1:
			x.Init = d.DecodeAny().(ast.Stmt)
		case 2:
			x.Cond = d.DecodeAny().(ast.Expr)
		case 3:
			x.Post = d.DecodeAny().(ast.Stmt)
		case 4:
			decode_ast_BlockStmt(d, &x.Body)
		default:
			d.UnknownField("ast.ForStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ForStmt{},
		func(e *codec.Encoder, x any) { encode_ast_ForStmt(e, x.(*ast.ForStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.ForStmt
			decode_ast_ForStmt(d, &x)
			return x
		})
}

// Fields of ast_FuncDecl: Doc Recv Name Type Body

func encode_ast_FuncDecl(e *codec.Encoder, x *ast.FuncDecl) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.Recv != nil {
		e.EncodeUint(1)
		encode_ast_FieldList(e, x.Recv)
	}
	if x.Name != nil {
		e.EncodeUint(2)
		encode_ast_Ident(e, x.Name)
	}
	if x.Type != nil {
		e.EncodeUint(3)
		encode_ast_FuncType(e, x.Type)
	}
	if x.Body != nil {
		e.EncodeUint(4)
		encode_ast_BlockStmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_FuncDecl(d *codec.Decoder, p **ast.FuncDecl) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.FuncDecl)
		return
	}
	var x ast.FuncDecl
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			decode_ast_FieldList(d, &x.Recv)
		case 2:
			decode_ast_Ident(d, &x.Name)
		case 3:
			decode_ast_FuncType(d, &x.Type)
		case 4:
			decode_ast_BlockStmt(d, &x.Body)
		default:
			d.UnknownField("ast.FuncDecl", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.FuncDecl{},
		func(e *codec.Encoder, x any) { encode_ast_FuncDecl(e, x.(*ast.FuncDecl)) },
		func(d *codec.Decoder) any {
			var x *ast.FuncDecl
			decode_ast_FuncDecl(d, &x)
			return x
		})
}

// Fields of ast_FuncLit: Type Body

func encode_ast_FuncLit(e *codec.Encoder, x *ast.FuncLit) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Type != nil {
		e.EncodeUint(0)
		encode_ast_FuncType(e, x.Type)
	}
	if x.Body != nil {
		e.EncodeUint(1)
		encode_ast_BlockStmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_FuncLit(d *codec.Decoder, p **ast.FuncLit) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.FuncLit)
		return
	}
	var x ast.FuncLit
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_FuncType(d, &x.Type)
		case 1:
			decode_ast_BlockStmt(d, &x.Body)
		default:
			d.UnknownField("ast.FuncLit", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.FuncLit{},
		func(e *codec.Encoder, x any) { encode_ast_FuncLit(e, x.(*ast.FuncLit)) },
		func(d *codec.Decoder) any {
			var x *ast.FuncLit
			decode_ast_FuncLit(d, &x)
			return x
		})
}

// Fields of ast_FuncType: Func Params Results TypeParams

func encode_ast_FuncType(e *codec.Encoder, x *ast.FuncType) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Func != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Func))
	}
	if x.Params != nil {
		e.EncodeUint(1)
		encode_ast_FieldList(e, x.Params)
	}
	if x.Results != nil {
		e.EncodeUint(2)
		encode_ast_FieldList(e, x.Results)
	}
	if x.TypeParams != nil {
		e.EncodeUint(3)
		encode_ast_FieldList(e, x.TypeParams)
	}
	e.EndStruct()
}

func decode_ast_FuncType(d *codec.Decoder, p **ast.FuncType) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.FuncType)
		return
	}
	var x ast.FuncType
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Func = token.Pos(d.DecodeInt())
		case 1:
			decode_ast_FieldList(d, &x.Params)
		case 2:
			decode_ast_FieldList(d, &x.Results)
		case 3:
			decode_ast_FieldList(d, &x.TypeParams)
		default:
			d.UnknownField("ast.FuncType", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.FuncType{},
		func(e *codec.Encoder, x any) { encode_ast_FuncType(e, x.(*ast.FuncType)) },
		func(d *codec.Decoder) any {
			var x *ast.FuncType
			decode_ast_FuncType(d, &x)
			return x
		})
}

// Fields of ast_GenDecl: Doc TokPos Tok Lparen Specs Rparen

func encode_ast_GenDecl(e *codec.Encoder, x *ast.GenDecl) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.TokPos != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.TokPos))
	}
	if x.Tok != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Tok))
	}
	if x.Lparen != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.Lparen))
	}
	if x.Specs != nil {
		e.EncodeUint(4)
		encode_slice_ast_Spec(e, x.Specs)
	}
	if x.Rparen != 0 {
		e.EncodeUint(5)
		e.EncodeInt(int64(x.Rparen))
	}
	e.EndStruct()
}

func decode_ast_GenDecl(d *codec.Decoder, p **ast.GenDecl) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.GenDecl)
		return
	}
	var x ast.GenDecl
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			x.TokPos = token.Pos(d.DecodeInt())
		case 2:
			x.Tok = token.Token(d.DecodeInt())
		case 3:
			x.Lparen = token.Pos(d.DecodeInt())
		case 4:
			decode_slice_ast_Spec(d, &x.Specs)
		case 5:
			x.Rparen = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.GenDecl", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.GenDecl{},
		func(e *codec.Encoder, x any) { encode_ast_GenDecl(e, x.(*ast.GenDecl)) },
		func(d *codec.Decoder) any {
			var x *ast.GenDecl
			decode_ast_GenDecl(d, &x)
			return x
		})
}

// Fields of ast_GoStmt: Go Call

func encode_ast_GoStmt(e *codec.Encoder, x *ast.GoStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Go != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Go))
	}
	if x.Call != nil {
		e.EncodeUint(1)
		encode_ast_CallExpr(e, x.Call)
	}
	e.EndStruct()
}

func decode_ast_GoStmt(d *codec.Decoder, p **ast.GoStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.GoStmt)
		return
	}
	var x ast.GoStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Go = token.Pos(d.DecodeInt())
		case 1:
			decode_ast_CallExpr(d, &x.Call)
		default:
			d.UnknownField("ast.GoStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.GoStmt{},
		func(e *codec.Encoder, x any) { encode_ast_GoStmt(e, x.(*ast.GoStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.GoStmt
			decode_ast_GoStmt(d, &x)
			return x
		})
}

// Fields of ast_Ident: NamePos Name Obj

func encode_ast_Ident(e *codec.Encoder, x *ast.Ident) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.NamePos != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.NamePos))
	}
	if x.Name != "" {
		e.EncodeUint(1)
		e.EncodeString(x.Name)
	}
	if x.Obj != nil {
		e.EncodeUint(2)
		encode_ast_Object(e, x.Obj)
	}
	e.EndStruct()
}

func decode_ast_Ident(d *codec.Decoder, p **ast.Ident) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.Ident)
		return
	}
	var x ast.Ident
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.NamePos = token.Pos(d.DecodeInt())
		case 1:
			x.Name = d.DecodeString()
		case 2:
			decode_ast_Object(d, &x.Obj)
		default:
			d.UnknownField("ast.Ident", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.Ident{},
		func(e *codec.Encoder, x any) { encode_ast_Ident(e, x.(*ast.Ident)) },
		func(d *codec.Decoder) any {
			var x *ast.Ident
			decode_ast_Ident(d, &x)
			return x
		})
}

// Fields of ast_IfStmt: If Init Cond Body Else

func encode_ast_IfStmt(e *codec.Encoder, x *ast.IfStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.If != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.If))
	}
	if x.Init != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Init)
	}
	if x.Cond != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Cond)
	}
	if x.Body != nil {
		e.EncodeUint(3)
		encode_ast_BlockStmt(e, x.Body)
	}
	if x.Else != nil {
		e.EncodeUint(4)
		e.EncodeAny(x.Else)
	}
	e.EndStruct()
}

func decode_ast_IfStmt(d *codec.Decoder, p **ast.IfStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.IfStmt)
		return
	}
	var x ast.IfStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.If = token.Pos(d.DecodeInt())
		case 1:
			x.Init = d.DecodeAny().(ast.Stmt)
		case 2:
			x.Cond = d.DecodeAny().(ast.Expr)
		case 3:
			decode_ast_BlockStmt(d, &x.Body)
		case 4:
			x.Else = d.DecodeAny().(ast.Stmt)
		default:
			d.UnknownField("ast.IfStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.IfStmt{},
		func(e *codec.Encoder, x any) { encode_ast_IfStmt(e, x.(*ast.IfStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.IfStmt
			decode_ast_IfStmt(d, &x)
			return x
		})
}

// Fields of ast_ImportSpec: Doc Name Path Comment EndPos

func encode_ast_ImportSpec(e *codec.Encoder, x *ast.ImportSpec) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.Name != nil {
		e.EncodeUint(1)
		encode_ast_Ident(e, x.Name)
	}
	if x.Path != nil {
		e.EncodeUint(2)
		encode_ast_BasicLit(e, x.Path)
	}
	if x.Comment != nil {
		e.EncodeUint(3)
		encode_ast_CommentGroup(e, x.Comment)
	}
	if x.EndPos != 0 {
		e.EncodeUint(4)
		e.EncodeInt(int64(x.EndPos))
	}
	e.EndStruct()
}

func decode_ast_ImportSpec(d *codec.Decoder, p **ast.ImportSpec) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ImportSpec)
		return
	}
	var x ast.ImportSpec
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			decode_ast_Ident(d, &x.Name)
		case 2:
			decode_ast_BasicLit(d, &x.Path)
		case 3:
			decode_ast_CommentGroup(d, &x.Comment)
		case 4:
			x.EndPos = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.ImportSpec", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ImportSpec{},
		func(e *codec.Encoder, x any) { encode_ast_ImportSpec(e, x.(*ast.ImportSpec)) },
		func(d *codec.Decoder) any {
			var x *ast.ImportSpec
			decode_ast_ImportSpec(d, &x)
			return x
		})
}

// Fields of ast_IncDecStmt: X TokPos Tok

func encode_ast_IncDecStmt(e *codec.Encoder, x *ast.IncDecStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.TokPos != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.TokPos))
	}
	if x.Tok != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Tok))
	}
	e.EndStruct()
}

func decode_ast_IncDecStmt(d *codec.Decoder, p **ast.IncDecStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.IncDecStmt)
		return
	}
	var x ast.IncDecStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			x.TokPos = token.Pos(d.DecodeInt())
		case 2:
			x.Tok = token.Token(d.DecodeInt())
		default:
			d.UnknownField("ast.IncDecStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.IncDecStmt{},
		func(e *codec.Encoder, x any) { encode_ast_IncDecStmt(e, x.(*ast.IncDecStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.IncDecStmt
			decode_ast_IncDecStmt(d, &x)
			return x
		})
}

// Fields of ast_IndexExpr: X Lbrack Index Rbrack

func encode_ast_IndexExpr(e *codec.Encoder, x *ast.IndexExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.Lbrack != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Lbrack))
	}
	if x.Index != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Index)
	}
	if x.Rbrack != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.Rbrack))
	}
	e.EndStruct()
}

func decode_ast_IndexExpr(d *codec.Decoder, p **ast.IndexExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.IndexExpr)
		return
	}
	var x ast.IndexExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			x.Lbrack = token.Pos(d.DecodeInt())
		case 2:
			x.Index = d.DecodeAny().(ast.Expr)
		case 3:
			x.Rbrack = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.IndexExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.IndexExpr{},
		func(e *codec.Encoder, x any) { encode_ast_IndexExpr(e, x.(*ast.IndexExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.IndexExpr
			decode_ast_IndexExpr(d, &x)
			return x
		})
}

// Fields of ast_IndexListExpr: X Lbrack Indices Rbrack

func encode_ast_IndexListExpr(e *codec.Encoder, x *ast.IndexListExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.Lbrack != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Lbrack))
	}
	if x.Indices != nil {
		e.EncodeUint(2)
		encode_slice_ast_Expr(e, x.Indices)
	}
	if x.Rbrack != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.Rbrack))
	}
	e.EndStruct()
}

func decode_ast_IndexListExpr(d *codec.Decoder, p **ast.IndexListExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.IndexListExpr)
		return
	}
	var x ast.IndexListExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			x.Lbrack = token.Pos(d.DecodeInt())
		case 2:
			decode_slice_ast_Expr(d, &x.Indices)
		case 3:
			x.Rbrack = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.IndexListExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.IndexListExpr{},
		func(e *codec.Encoder, x any) { encode_ast_IndexListExpr(e, x.(*ast.IndexListExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.IndexListExpr
			decode_ast_IndexListExpr(d, &x)
			return x
		})
}

// Fields of ast_InterfaceType: Interface Methods Incomplete

func encode_ast_InterfaceType(e *codec.Encoder, x *ast.InterfaceType) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Interface != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Interface))
	}
	if x.Methods != nil {
		e.EncodeUint(1)
		encode_ast_FieldList(e, x.Methods)
	}
	if x.Incomplete != false {
		e.EncodeUint(2)
		e.EncodeBool(x.Incomplete)
	}
	e.EndStruct()
}

func decode_ast_InterfaceType(d *codec.Decoder, p **ast.InterfaceType) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.InterfaceType)
		return
	}
	var x ast.InterfaceType
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Interface = token.Pos(d.DecodeInt())
		case 1:
			decode_ast_FieldList(d, &x.Methods)
		case 2:
			x.Incomplete = d.DecodeBool()
		default:
			d.UnknownField("ast.InterfaceType", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.InterfaceType{},
		func(e *codec.Encoder, x any) { encode_ast_InterfaceType(e, x.(*ast.InterfaceType)) },
		func(d *codec.Decoder) any {
			var x *ast.InterfaceType
			decode_ast_InterfaceType(d, &x)
			return x
		})
}

// Fields of ast_KeyValueExpr: Key Colon Value

func encode_ast_KeyValueExpr(e *codec.Encoder, x *ast.KeyValueExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Key != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.Key)
	}
	if x.Colon != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Colon))
	}
	if x.Value != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Value)
	}
	e.EndStruct()
}

func decode_ast_KeyValueExpr(d *codec.Decoder, p **ast.KeyValueExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.KeyValueExpr)
		return
	}
	var x ast.KeyValueExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Key = d.DecodeAny().(ast.Expr)
		case 1:
			x.Colon = token.Pos(d.DecodeInt())
		case 2:
			x.Value = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.KeyValueExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.KeyValueExpr{},
		func(e *codec.Encoder, x any) { encode_ast_KeyValueExpr(e, x.(*ast.KeyValueExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.KeyValueExpr
			decode_ast_KeyValueExpr(d, &x)
			return x
		})
}

// Fields of ast_LabeledStmt: Label Colon Stmt

func encode_ast_LabeledStmt(e *codec.Encoder, x *ast.LabeledStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Label != nil {
		e.EncodeUint(0)
		encode_ast_Ident(e, x.Label)
	}
	if x.Colon != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Colon))
	}
	if x.Stmt != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Stmt)
	}
	e.EndStruct()
}

func decode_ast_LabeledStmt(d *codec.Decoder, p **ast.LabeledStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.LabeledStmt)
		return
	}
	var x ast.LabeledStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_Ident(d, &x.Label)
		case 1:
			x.Colon = token.Pos(d.DecodeInt())
		case 2:
			x.Stmt = d.DecodeAny().(ast.Stmt)
		default:
			d.UnknownField("ast.LabeledStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.LabeledStmt{},
		func(e *codec.Encoder, x any) { encode_ast_LabeledStmt(e, x.(*ast.LabeledStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.LabeledStmt
			decode_ast_LabeledStmt(d, &x)
			return x
		})
}

// Fields of ast_MapType: Map Key Value

func encode_ast_MapType(e *codec.Encoder, x *ast.MapType) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Map != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Map))
	}
	if x.Key != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Key)
	}
	if x.Value != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Value)
	}
	e.EndStruct()
}

func decode_ast_MapType(d *codec.Decoder, p **ast.MapType) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.MapType)
		return
	}
	var x ast.MapType
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Map = token.Pos(d.DecodeInt())
		case 1:
			x.Key = d.DecodeAny().(ast.Expr)
		case 2:
			x.Value = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.MapType", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.MapType{},
		func(e *codec.Encoder, x any) { encode_ast_MapType(e, x.(*ast.MapType)) },
		func(d *codec.Decoder) any {
			var x *ast.MapType
			decode_ast_MapType(d, &x)
			return x
		})
}

// Fields of ast_ParenExpr: Lparen X Rparen

func encode_ast_ParenExpr(e *codec.Encoder, x *ast.ParenExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Lparen != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Lparen))
	}
	if x.X != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.X)
	}
	if x.Rparen != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Rparen))
	}
	e.EndStruct()
}

func decode_ast_ParenExpr(d *codec.Decoder, p **ast.ParenExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ParenExpr)
		return
	}
	var x ast.ParenExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Lparen = token.Pos(d.DecodeInt())
		case 1:
			x.X = d.DecodeAny().(ast.Expr)
		case 2:
			x.Rparen = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.ParenExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ParenExpr{},
		func(e *codec.Encoder, x any) { encode_ast_ParenExpr(e, x.(*ast.ParenExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.ParenExpr
			decode_ast_ParenExpr(d, &x)
			return x
		})
}

// Fields of ast_RangeStmt: For Key Value TokPos Tok X Body Range

func encode_ast_RangeStmt(e *codec.Encoder, x *ast.RangeStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.For != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.For))
	}
	if x.Key != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Key)
	}
	if x.Value != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Value)
	}
	if x.TokPos != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.TokPos))
	}
	if x.Tok != 0 {
		e.EncodeUint(4)
		e.EncodeInt(int64(x.Tok))
	}
	if x.X != nil {
		e.EncodeUint(5)
		e.EncodeAny(x.X)
	}
	if x.Body != nil {
		e.EncodeUint(6)
		encode_ast_BlockStmt(e, x.Body)
	}
	if x.Range != 0 {
		e.EncodeUint(7)
		e.EncodeInt(int64(x.Range))
	}
	e.EndStruct()
}

func decode_ast_RangeStmt(d *codec.Decoder, p **ast.RangeStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.RangeStmt)
		return
	}
	var x ast.RangeStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.For = token.Pos(d.DecodeInt())
		case 1:
			x.Key = d.DecodeAny().(ast.Expr)
		case 2:
			x.Value = d.DecodeAny().(ast.Expr)
		case 3:
			x.TokPos = token.Pos(d.DecodeInt())
		case 4:
			x.Tok = token.Token(d.DecodeInt())
		case 5:
			x.X = d.DecodeAny().(ast.Expr)
		case 6:
			decode_ast_BlockStmt(d, &x.Body)
		case 7:
			x.Range = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.RangeStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.RangeStmt{},
		func(e *codec.Encoder, x any) { encode_ast_RangeStmt(e, x.(*ast.RangeStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.RangeStmt
			decode_ast_RangeStmt(d, &x)
			return x
		})
}

// Fields of ast_ReturnStmt: Return Results

func encode_ast_ReturnStmt(e *codec.Encoder, x *ast.ReturnStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Return != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Return))
	}
	if x.Results != nil {
		e.EncodeUint(1)
		encode_slice_ast_Expr(e, x.Results)
	}
	e.EndStruct()
}

func decode_ast_ReturnStmt(d *codec.Decoder, p **ast.ReturnStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ReturnStmt)
		return
	}
	var x ast.ReturnStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Return = token.Pos(d.DecodeInt())
		case 1:
			decode_slice_ast_Expr(d, &x.Results)
		default:
			d.UnknownField("ast.ReturnStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ReturnStmt{},
		func(e *codec.Encoder, x any) { encode_ast_ReturnStmt(e, x.(*ast.ReturnStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.ReturnStmt
			decode_ast_ReturnStmt(d, &x)
			return x
		})
}

// Fields of ast_Scope: Outer Objects

func encode_ast_Scope(e *codec.Encoder, x *ast.Scope) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Outer != nil {
		e.EncodeUint(0)
		encode_ast_Scope(e, x.Outer)
	}
	if x.Objects != nil {
		e.EncodeUint(1)
		encode_map_string_ast_Object(e, x.Objects)
	}
	e.EndStruct()
}

func decode_ast_Scope(d *codec.Decoder, p **ast.Scope) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.Scope)
		return
	}
	var x ast.Scope
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_Scope(d, &x.Outer)
		case 1:
			decode_map_string_ast_Object(d, &x.Objects)
		default:
			d.UnknownField("ast.Scope", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.Scope{},
		func(e *codec.Encoder, x any) { encode_ast_Scope(e, x.(*ast.Scope)) },
		func(d *codec.Decoder) any {
			var x *ast.Scope
			decode_ast_Scope(d, &x)
			return x
		})
}

// Fields of ast_SelectStmt: Select Body

func encode_ast_SelectStmt(e *codec.Encoder, x *ast.SelectStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Select != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Select))
	}
	if x.Body != nil {
		e.EncodeUint(1)
		encode_ast_BlockStmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_SelectStmt(d *codec.Decoder, p **ast.SelectStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.SelectStmt)
		return
	}
	var x ast.SelectStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Select = token.Pos(d.DecodeInt())
		case 1:
			decode_ast_BlockStmt(d, &x.Body)
		default:
			d.UnknownField("ast.SelectStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.SelectStmt{},
		func(e *codec.Encoder, x any) { encode_ast_SelectStmt(e, x.(*ast.SelectStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.SelectStmt
			decode_ast_SelectStmt(d, &x)
			return x
		})
}

// Fields of ast_SelectorExpr: X Sel

func encode_ast_SelectorExpr(e *codec.Encoder, x *ast.SelectorExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.Sel != nil {
		e.EncodeUint(1)
		encode_ast_Ident(e, x.Sel)
	}
	e.EndStruct()
}

func decode_ast_SelectorExpr(d *codec.Decoder, p **ast.SelectorExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.SelectorExpr)
		return
	}
	var x ast.SelectorExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			decode_ast_Ident(d, &x.Sel)
		default:
			d.UnknownField("ast.SelectorExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.SelectorExpr{},
		func(e *codec.Encoder, x any) { encode_ast_SelectorExpr(e, x.(*ast.SelectorExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.SelectorExpr
			decode_ast_SelectorExpr(d, &x)
			return x
		})
}

// Fields of ast_SendStmt: Chan Arrow Value

func encode_ast_SendStmt(e *codec.Encoder, x *ast.SendStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Chan != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.Chan)
	}
	if x.Arrow != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Arrow))
	}
	if x.Value != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Value)
	}
	e.EndStruct()
}

func decode_ast_SendStmt(d *codec.Decoder, p **ast.SendStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.SendStmt)
		return
	}
	var x ast.SendStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Chan = d.DecodeAny().(ast.Expr)
		case 1:
			x.Arrow = token.Pos(d.DecodeInt())
		case 2:
			x.Value = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.SendStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.SendStmt{},
		func(e *codec.Encoder, x any) { encode_ast_SendStmt(e, x.(*ast.SendStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.SendStmt
			decode_ast_SendStmt(d, &x)
			return x
		})
}

// Fields of ast_SliceExpr: X Lbrack Low High Max Slice3 Rbrack

func encode_ast_SliceExpr(e *codec.Encoder, x *ast.SliceExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.Lbrack != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Lbrack))
	}
	if x.Low != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Low)
	}
	if x.High != nil {
		e.EncodeUint(3)
		e.EncodeAny(x.High)
	}
	if x.Max != nil {
		e.EncodeUint(4)
		e.EncodeAny(x.Max)
	}
	if x.Slice3 != false {
		e.EncodeUint(5)
		e.EncodeBool(x.Slice3)
	}
	if x.Rbrack != 0 {
		e.EncodeUint(6)
		e.EncodeInt(int64(x.Rbrack))
	}
	e.EndStruct()
}

func decode_ast_SliceExpr(d *codec.Decoder, p **ast.SliceExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.SliceExpr)
		return
	}
	var x ast.SliceExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			x.Lbrack = token.Pos(d.DecodeInt())
		case 2:
			x.Low = d.DecodeAny().(ast.Expr)
		case 3:
			x.High = d.DecodeAny().(ast.Expr)
		case 4:
			x.Max = d.DecodeAny().(ast.Expr)
		case 5:
			x.Slice3 = d.DecodeBool()
		case 6:
			x.Rbrack = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.SliceExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.SliceExpr{},
		func(e *codec.Encoder, x any) { encode_ast_SliceExpr(e, x.(*ast.SliceExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.SliceExpr
			decode_ast_SliceExpr(d, &x)
			return x
		})
}

// Fields of ast_StarExpr: Star X

func encode_ast_StarExpr(e *codec.Encoder, x *ast.StarExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Star != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Star))
	}
	if x.X != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.X)
	}
	e.EndStruct()
}

func decode_ast_StarExpr(d *codec.Decoder, p **ast.StarExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.StarExpr)
		return
	}
	var x ast.StarExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Star = token.Pos(d.DecodeInt())
		case 1:
			x.X = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.StarExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.StarExpr{},
		func(e *codec.Encoder, x any) { encode_ast_StarExpr(e, x.(*ast.StarExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.StarExpr
			decode_ast_StarExpr(d, &x)
			return x
		})
}

// Fields of ast_StructType: Struct Fields Incomplete

func encode_ast_StructType(e *codec.Encoder, x *ast.StructType) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Struct != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Struct))
	}
	if x.Fields != nil {
		e.EncodeUint(1)
		encode_ast_FieldList(e, x.Fields)
	}
	if x.Incomplete != false {
		e.EncodeUint(2)
		e.EncodeBool(x.Incomplete)
	}
	e.EndStruct()
}

func decode_ast_StructType(d *codec.Decoder, p **ast.StructType) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.StructType)
		return
	}
	var x ast.StructType
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Struct = token.Pos(d.DecodeInt())
		case 1:
			decode_ast_FieldList(d, &x.Fields)
		case 2:
			x.Incomplete = d.DecodeBool()
		default:
			d.UnknownField("ast.StructType", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.StructType{},
		func(e *codec.Encoder, x any) { encode_ast_StructType(e, x.(*ast.StructType)) },
		func(d *codec.Decoder) any {
			var x *ast.StructType
			decode_ast_StructType(d, &x)
			return x
		})
}

// Fields of ast_SwitchStmt: Switch Init Tag Body

func encode_ast_SwitchStmt(e *codec.Encoder, x *ast.SwitchStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Switch != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Switch))
	}
	if x.Init != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Init)
	}
	if x.Tag != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Tag)
	}
	if x.Body != nil {
		e.EncodeUint(3)
		encode_ast_BlockStmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_SwitchStmt(d *codec.Decoder, p **ast.SwitchStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.SwitchStmt)
		return
	}
	var x ast.SwitchStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Switch = token.Pos(d.DecodeInt())
		case 1:
			x.Init = d.DecodeAny().(ast.Stmt)
		case 2:
			x.Tag = d.DecodeAny().(ast.Expr)
		case 3:
			decode_ast_BlockStmt(d, &x.Body)
		default:
			d.UnknownField("ast.SwitchStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.SwitchStmt{},
		func(e *codec.Encoder, x any) { encode_ast_SwitchStmt(e, x.(*ast.SwitchStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.SwitchStmt
			decode_ast_SwitchStmt(d, &x)
			return x
		})
}

// Fields of ast_TypeAssertExpr: X Lparen Type Rparen

func encode_ast_TypeAssertExpr(e *codec.Encoder, x *ast.TypeAssertExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.X != nil {
		e.EncodeUint(0)
		e.EncodeAny(x.X)
	}
	if x.Lparen != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Lparen))
	}
	if x.Type != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Type)
	}
	if x.Rparen != 0 {
		e.EncodeUint(3)
		e.EncodeInt(int64(x.Rparen))
	}
	e.EndStruct()
}

func decode_ast_TypeAssertExpr(d *codec.Decoder, p **ast.TypeAssertExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.TypeAssertExpr)
		return
	}
	var x ast.TypeAssertExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.X = d.DecodeAny().(ast.Expr)
		case 1:
			x.Lparen = token.Pos(d.DecodeInt())
		case 2:
			x.Type = d.DecodeAny().(ast.Expr)
		case 3:
			x.Rparen = token.Pos(d.DecodeInt())
		default:
			d.UnknownField("ast.TypeAssertExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.TypeAssertExpr{},
		func(e *codec.Encoder, x any) { encode_ast_TypeAssertExpr(e, x.(*ast.TypeAssertExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.TypeAssertExpr
			decode_ast_TypeAssertExpr(d, &x)
			return x
		})
}

// Fields of ast_TypeSpec: Doc Name Assign Type Comment TypeParams

func encode_ast_TypeSpec(e *codec.Encoder, x *ast.TypeSpec) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.Name != nil {
		e.EncodeUint(1)
		encode_ast_Ident(e, x.Name)
	}
	if x.Assign != 0 {
		e.EncodeUint(2)
		e.EncodeInt(int64(x.Assign))
	}
	if x.Type != nil {
		e.EncodeUint(3)
		e.EncodeAny(x.Type)
	}
	if x.Comment != nil {
		e.EncodeUint(4)
		encode_ast_CommentGroup(e, x.Comment)
	}
	if x.TypeParams != nil {
		e.EncodeUint(5)
		encode_ast_FieldList(e, x.TypeParams)
	}
	e.EndStruct()
}

func decode_ast_TypeSpec(d *codec.Decoder, p **ast.TypeSpec) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.TypeSpec)
		return
	}
	var x ast.TypeSpec
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			decode_ast_Ident(d, &x.Name)
		case 2:
			x.Assign = token.Pos(d.DecodeInt())
		case 3:
			x.Type = d.DecodeAny().(ast.Expr)
		case 4:
			decode_ast_CommentGroup(d, &x.Comment)
		case 5:
			decode_ast_FieldList(d, &x.TypeParams)
		default:
			d.UnknownField("ast.TypeSpec", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.TypeSpec{},
		func(e *codec.Encoder, x any) { encode_ast_TypeSpec(e, x.(*ast.TypeSpec)) },
		func(d *codec.Decoder) any {
			var x *ast.TypeSpec
			decode_ast_TypeSpec(d, &x)
			return x
		})
}

// Fields of ast_TypeSwitchStmt: Switch Init Assign Body

func encode_ast_TypeSwitchStmt(e *codec.Encoder, x *ast.TypeSwitchStmt) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Switch != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Switch))
	}
	if x.Init != nil {
		e.EncodeUint(1)
		e.EncodeAny(x.Init)
	}
	if x.Assign != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Assign)
	}
	if x.Body != nil {
		e.EncodeUint(3)
		encode_ast_BlockStmt(e, x.Body)
	}
	e.EndStruct()
}

func decode_ast_TypeSwitchStmt(d *codec.Decoder, p **ast.TypeSwitchStmt) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.TypeSwitchStmt)
		return
	}
	var x ast.TypeSwitchStmt
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Switch = token.Pos(d.DecodeInt())
		case 1:
			x.Init = d.DecodeAny().(ast.Stmt)
		case 2:
			x.Assign = d.DecodeAny().(ast.Stmt)
		case 3:
			decode_ast_BlockStmt(d, &x.Body)
		default:
			d.UnknownField("ast.TypeSwitchStmt", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.TypeSwitchStmt{},
		func(e *codec.Encoder, x any) { encode_ast_TypeSwitchStmt(e, x.(*ast.TypeSwitchStmt)) },
		func(d *codec.Decoder) any {
			var x *ast.TypeSwitchStmt
			decode_ast_TypeSwitchStmt(d, &x)
			return x
		})
}

// Fields of ast_UnaryExpr: OpPos Op X

func encode_ast_UnaryExpr(e *codec.Encoder, x *ast.UnaryExpr) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.OpPos != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.OpPos))
	}
	if x.Op != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Op))
	}
	if x.X != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.X)
	}
	e.EndStruct()
}

func decode_ast_UnaryExpr(d *codec.Decoder, p **ast.UnaryExpr) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.UnaryExpr)
		return
	}
	var x ast.UnaryExpr
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.OpPos = token.Pos(d.DecodeInt())
		case 1:
			x.Op = token.Token(d.DecodeInt())
		case 2:
			x.X = d.DecodeAny().(ast.Expr)
		default:
			d.UnknownField("ast.UnaryExpr", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.UnaryExpr{},
		func(e *codec.Encoder, x any) { encode_ast_UnaryExpr(e, x.(*ast.UnaryExpr)) },
		func(d *codec.Decoder) any {
			var x *ast.UnaryExpr
			decode_ast_UnaryExpr(d, &x)
			return x
		})
}

// Fields of ast_ValueSpec: Doc Names Type Values Comment

func encode_ast_ValueSpec(e *codec.Encoder, x *ast.ValueSpec) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.Names != nil {
		e.EncodeUint(1)
		encode_slice_ast_Ident(e, x.Names)
	}
	if x.Type != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Type)
	}
	if x.Values != nil {
		e.EncodeUint(3)
		encode_slice_ast_Expr(e, x.Values)
	}
	if x.Comment != nil {
		e.EncodeUint(4)
		encode_ast_CommentGroup(e, x.Comment)
	}
	e.EndStruct()
}

func decode_ast_ValueSpec(d *codec.Decoder, p **ast.ValueSpec) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.ValueSpec)
		return
	}
	var x ast.ValueSpec
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			decode_slice_ast_Ident(d, &x.Names)
		case 2:
			x.Type = d.DecodeAny().(ast.Expr)
		case 3:
			decode_slice_ast_Expr(d, &x.Values)
		case 4:
			decode_ast_CommentGroup(d, &x.Comment)
		default:
			d.UnknownField("ast.ValueSpec", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.ValueSpec{},
		func(e *codec.Encoder, x any) { encode_ast_ValueSpec(e, x.(*ast.ValueSpec)) },
		func(d *codec.Decoder) any {
			var x *ast.ValueSpec
			decode_ast_ValueSpec(d, &x)
			return x
		})
}

// Fields of encPackage: GOOS GOARCH Files ModulePackagePaths

func encode_encPackage(e *codec.Encoder, x *encPackage) {
	if !e.StartStruct(x == nil, x) {
		return
	}

	if x.Files != nil {
		e.EncodeUint(2)
		encode_slice_File(e, x.Files)
	}
	if x.ModulePackagePaths != nil {
		e.EncodeUint(3)
		encode_map_string_bool(e, x.ModulePackagePaths)
	}
	e.EndStruct()
}

func decode_encPackage(d *codec.Decoder, p **encPackage) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*encPackage)
		return
	}
	var x encPackage
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 2:
			decode_slice_File(d, &x.Files)
		case 3:
			decode_map_string_bool(d, &x.ModulePackagePaths)
		default:
			d.UnknownField("encPackage", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&encPackage{},
		func(e *codec.Encoder, x any) { encode_encPackage(e, x.(*encPackage)) },
		func(d *codec.Decoder) any {
			var x *encPackage
			decode_encPackage(d, &x)
			return x
		})
}

func encode_slice_ast_Expr(e *codec.Encoder, s []ast.Expr) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		e.EncodeAny(x)
	}
}

func decode_slice_ast_Expr(d *codec.Decoder, p *[]ast.Expr) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]ast.Expr, n)
	for i := 0; i < n; i++ {
		s[i] = d.DecodeAny().(ast.Expr)
	}
	*p = s
}

func init() {
	codec.Register([]ast.Expr(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Expr(e, x.([]ast.Expr)) },
		func(d *codec.Decoder) any { var x []ast.Expr; decode_slice_ast_Expr(d, &x); return x })
}

func encode_slice_ast_Stmt(e *codec.Encoder, s []ast.Stmt) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		e.EncodeAny(x)
	}
}

func decode_slice_ast_Stmt(d *codec.Decoder, p *[]ast.Stmt) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]ast.Stmt, n)
	for i := 0; i < n; i++ {
		s[i] = d.DecodeAny().(ast.Stmt)
	}
	*p = s
}

func init() {
	codec.Register([]ast.Stmt(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Stmt(e, x.([]ast.Stmt)) },
		func(d *codec.Decoder) any { var x []ast.Stmt; decode_slice_ast_Stmt(d, &x); return x })
}

func encode_slice_ast_Comment(e *codec.Encoder, s []*ast.Comment) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		encode_ast_Comment(e, x)
	}
}

func decode_slice_ast_Comment(d *codec.Decoder, p *[]*ast.Comment) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]*ast.Comment, n)
	for i := 0; i < n; i++ {
		decode_ast_Comment(d, &s[i])
	}
	*p = s
}

func init() {
	codec.Register([]*ast.Comment(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Comment(e, x.([]*ast.Comment)) },
		func(d *codec.Decoder) any { var x []*ast.Comment; decode_slice_ast_Comment(d, &x); return x })
}

func encode_slice_ast_Field(e *codec.Encoder, s []*ast.Field) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		encode_ast_Field(e, x)
	}
}

func decode_slice_ast_Field(d *codec.Decoder, p *[]*ast.Field) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]*ast.Field, n)
	for i := 0; i < n; i++ {
		decode_ast_Field(d, &s[i])
	}
	*p = s
}

func init() {
	codec.Register([]*ast.Field(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Field(e, x.([]*ast.Field)) },
		func(d *codec.Decoder) any { var x []*ast.Field; decode_slice_ast_Field(d, &x); return x })
}

func encode_slice_ast_Ident(e *codec.Encoder, s []*ast.Ident) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		encode_ast_Ident(e, x)
	}
}

func decode_slice_ast_Ident(d *codec.Decoder, p *[]*ast.Ident) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]*ast.Ident, n)
	for i := 0; i < n; i++ {
		decode_ast_Ident(d, &s[i])
	}
	*p = s
}

func init() {
	codec.Register([]*ast.Ident(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Ident(e, x.([]*ast.Ident)) },
		func(d *codec.Decoder) any { var x []*ast.Ident; decode_slice_ast_Ident(d, &x); return x })
}

func encode_slice_ast_Spec(e *codec.Encoder, s []ast.Spec) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		e.EncodeAny(x)
	}
}

func decode_slice_ast_Spec(d *codec.Decoder, p *[]ast.Spec) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]ast.Spec, n)
	for i := 0; i < n; i++ {
		s[i] = d.DecodeAny().(ast.Spec)
	}
	*p = s
}

func init() {
	codec.Register([]ast.Spec(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Spec(e, x.([]ast.Spec)) },
		func(d *codec.Decoder) any { var x []ast.Spec; decode_slice_ast_Spec(d, &x); return x })
}

// Fields of ast_Object: Kind Name Decl Data Type

func encode_ast_Object(e *codec.Encoder, x *ast.Object) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Kind != 0 {
		e.EncodeUint(0)
		e.EncodeInt(int64(x.Kind))
	}
	if x.Name != "" {
		e.EncodeUint(1)
		e.EncodeString(x.Name)
	}
	if x.Decl != nil {
		e.EncodeUint(2)
		e.EncodeAny(x.Decl)
	}
	if x.Data != nil {
		e.EncodeUint(3)
		e.EncodeAny(x.Data)
	}
	if x.Type != nil {
		e.EncodeUint(4)
		e.EncodeAny(x.Type)
	}
	e.EndStruct()
}

func decode_ast_Object(d *codec.Decoder, p **ast.Object) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.Object)
		return
	}
	var x ast.Object
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Kind = ast.ObjKind(d.DecodeInt())
		case 1:
			x.Name = d.DecodeString()
		case 2:
			x.Decl = d.DecodeAny()
		case 3:
			x.Data = d.DecodeAny()
		case 4:
			x.Type = d.DecodeAny()
		default:
			d.UnknownField("ast.Object", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.Object{},
		func(e *codec.Encoder, x any) { encode_ast_Object(e, x.(*ast.Object)) },
		func(d *codec.Decoder) any {
			var x *ast.Object
			decode_ast_Object(d, &x)
			return x
		})
}

func encode_map_string_ast_Object(e *codec.Encoder, m map[string]*ast.Object) {
	if m == nil {
		e.EncodeNil()
		return
	}
	e.StartList(2 * len(m))
	for k, v := range m {
		e.EncodeString(k)
		encode_ast_Object(e, v)
	}
}

func decode_map_string_ast_Object(d *codec.Decoder, p *map[string]*ast.Object) {
	n2 := d.StartList()
	if n2 < 0 {
		return
	}
	n := n2 / 2
	m := make(map[string]*ast.Object, n)
	var k string
	var v *ast.Object
	for i := 0; i < n; i++ {
		k = d.DecodeString()
		decode_ast_Object(d, &v)
		m[k] = v
	}
	*p = m
}

func init() {
	codec.Register(map[string]*ast.Object(nil),
		func(e *codec.Encoder, x any) { encode_map_string_ast_Object(e, x.(map[string]*ast.Object)) },
		func(d *codec.Decoder) any {
			var x map[string]*ast.Object
			decode_map_string_ast_Object(d, &x)
			return x
		})
}

func encode_slice_File(e *codec.Encoder, s []*File) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		encode_File(e, x)
	}
}

func decode_slice_File(d *codec.Decoder, p *[]*File) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]*File, n)
	for i := 0; i < n; i++ {
		decode_File(d, &s[i])
	}
	*p = s
}

func init() {
	codec.Register([]*File(nil),
		func(e *codec.Encoder, x any) { encode_slice_File(e, x.([]*File)) },
		func(d *codec.Decoder) any { var x []*File; decode_slice_File(d, &x); return x })
}

func encode_map_string_bool(e *codec.Encoder, m map[string]bool) {
	if m == nil {
		e.EncodeNil()
		return
	}
	e.StartList(2 * len(m))
	for k, v := range m {
		e.EncodeString(k)
		e.EncodeBool(v)
	}
}

func decode_map_string_bool(d *codec.Decoder, p *map[string]bool) {
	n2 := d.StartList()
	if n2 < 0 {
		return
	}
	n := n2 / 2
	m := make(map[string]bool, n)
	var k string
	var v bool
	for i := 0; i < n; i++ {
		k = d.DecodeString()
		v = d.DecodeBool()
		m[k] = v
	}
	*p = m
}

func init() {
	codec.Register(map[string]bool(nil),
		func(e *codec.Encoder, x any) { encode_map_string_bool(e, x.(map[string]bool)) },
		func(d *codec.Decoder) any { var x map[string]bool; decode_map_string_bool(d, &x); return x })
}

// Fields of File: Name AST

func encode_File(e *codec.Encoder, x *File) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Name != "" {
		e.EncodeUint(0)
		e.EncodeString(x.Name)
	}
	if x.AST != nil {
		e.EncodeUint(1)
		encode_ast_File(e, x.AST)
	}
	e.EndStruct()
}

func decode_File(d *codec.Decoder, p **File) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*File)
		return
	}
	var x File
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			x.Name = d.DecodeString()
		case 1:
			decode_ast_File(d, &x.AST)
		default:
			d.UnknownField("File", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&File{},
		func(e *codec.Encoder, x any) { encode_File(e, x.(*File)) },
		func(d *codec.Decoder) any {
			var x *File
			decode_File(d, &x)
			return x
		})
}

// Fields of ast_File: Doc Package Name Decls Scope Imports Unresolved Comments FileStart FileEnd GoVersion

func encode_ast_File(e *codec.Encoder, x *ast.File) {
	if !e.StartStruct(x == nil, x) {
		return
	}
	if x.Doc != nil {
		e.EncodeUint(0)
		encode_ast_CommentGroup(e, x.Doc)
	}
	if x.Package != 0 {
		e.EncodeUint(1)
		e.EncodeInt(int64(x.Package))
	}
	if x.Name != nil {
		e.EncodeUint(2)
		encode_ast_Ident(e, x.Name)
	}
	if x.Decls != nil {
		e.EncodeUint(3)
		encode_slice_ast_Decl(e, x.Decls)
	}
	if x.Scope != nil {
		e.EncodeUint(4)
		encode_ast_Scope(e, x.Scope)
	}
	if x.Imports != nil {
		e.EncodeUint(5)
		encode_slice_ast_ImportSpec(e, x.Imports)
	}
	if x.Unresolved != nil {
		e.EncodeUint(6)
		encode_slice_ast_Ident(e, x.Unresolved)
	}
	if x.Comments != nil {
		e.EncodeUint(7)
		encode_slice_ast_CommentGroup(e, x.Comments)
	}
	if x.FileStart != 0 {
		e.EncodeUint(8)
		e.EncodeInt(int64(x.FileStart))
	}
	if x.FileEnd != 0 {
		e.EncodeUint(9)
		e.EncodeInt(int64(x.FileEnd))
	}
	if x.GoVersion != "" {
		e.EncodeUint(10)
		e.EncodeString(x.GoVersion)
	}
	e.EndStruct()
}

func decode_ast_File(d *codec.Decoder, p **ast.File) {
	proceed, ref := d.StartStruct()
	if !proceed {
		return
	}
	if ref != nil {
		*p = ref.(*ast.File)
		return
	}
	var x ast.File
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 {
			break
		}
		switch n {
		case 0:
			decode_ast_CommentGroup(d, &x.Doc)
		case 1:
			x.Package = token.Pos(d.DecodeInt())
		case 2:
			decode_ast_Ident(d, &x.Name)
		case 3:
			decode_slice_ast_Decl(d, &x.Decls)
		case 4:
			decode_ast_Scope(d, &x.Scope)
		case 5:
			decode_slice_ast_ImportSpec(d, &x.Imports)
		case 6:
			decode_slice_ast_Ident(d, &x.Unresolved)
		case 7:
			decode_slice_ast_CommentGroup(d, &x.Comments)
		case 8:
			x.FileStart = token.Pos(d.DecodeInt())
		case 9:
			x.FileEnd = token.Pos(d.DecodeInt())
		case 10:
			x.GoVersion = d.DecodeString()
		default:
			d.UnknownField("ast.File", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&ast.File{},
		func(e *codec.Encoder, x any) { encode_ast_File(e, x.(*ast.File)) },
		func(d *codec.Decoder) any {
			var x *ast.File
			decode_ast_File(d, &x)
			return x
		})
}

func encode_slice_ast_Decl(e *codec.Encoder, s []ast.Decl) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		e.EncodeAny(x)
	}
}

func decode_slice_ast_Decl(d *codec.Decoder, p *[]ast.Decl) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]ast.Decl, n)
	for i := 0; i < n; i++ {
		s[i] = d.DecodeAny().(ast.Decl)
	}
	*p = s
}

func init() {
	codec.Register([]ast.Decl(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_Decl(e, x.([]ast.Decl)) },
		func(d *codec.Decoder) any { var x []ast.Decl; decode_slice_ast_Decl(d, &x); return x })
}

func encode_slice_ast_ImportSpec(e *codec.Encoder, s []*ast.ImportSpec) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		encode_ast_ImportSpec(e, x)
	}
}

func decode_slice_ast_ImportSpec(d *codec.Decoder, p *[]*ast.ImportSpec) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]*ast.ImportSpec, n)
	for i := 0; i < n; i++ {
		decode_ast_ImportSpec(d, &s[i])
	}
	*p = s
}

func init() {
	codec.Register([]*ast.ImportSpec(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_ImportSpec(e, x.([]*ast.ImportSpec)) },
		func(d *codec.Decoder) any { var x []*ast.ImportSpec; decode_slice_ast_ImportSpec(d, &x); return x })
}

func encode_slice_ast_CommentGroup(e *codec.Encoder, s []*ast.CommentGroup) {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		encode_ast_CommentGroup(e, x)
	}
}

func decode_slice_ast_CommentGroup(d *codec.Decoder, p *[]*ast.CommentGroup) {
	n := d.StartList()
	if n < 0 {
		return
	}
	s := make([]*ast.CommentGroup, n)
	for i := 0; i < n; i++ {
		decode_ast_CommentGroup(d, &s[i])
	}
	*p = s
}

func init() {
	codec.Register([]*ast.CommentGroup(nil),
		func(e *codec.Encoder, x any) { encode_slice_ast_CommentGroup(e, x.([]*ast.CommentGroup)) },
		func(d *codec.Decoder) any { var x []*ast.CommentGroup; decode_slice_ast_CommentGroup(d, &x); return x })
}
