github.com/ipld/go-ipld-prime@v0.21.0/schema/gen/go/generators.go (about)

     1  package gengo
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/ipld/go-ipld-prime/schema"
     8  )
     9  
    10  // TypeGenerator gathers all the info for generating all code related to one
    11  // type in the schema.
    12  type TypeGenerator interface {
    13  	// -- the natively-typed apis -->
    14  
    15  	EmitNativeType(io.Writer)
    16  	EmitNativeAccessors(io.Writer) // depends on the kind -- field accessors for struct, typed iterators for map, etc.
    17  	EmitNativeBuilder(io.Writer)   // typically emits some kind of struct that has a Build method.
    18  	EmitNativeMaybe(io.Writer)     // a pointer-free 'maybe' mechanism is generated for all types.
    19  
    20  	// -- the schema.TypedNode.Type method and vars -->
    21  
    22  	EmitTypeConst(io.Writer)           // these emit dummies for now
    23  	EmitTypedNodeMethodType(io.Writer) // these emit dummies for now
    24  
    25  	// -- all node methods -->
    26  	//   (and note that the nodeBuilder for this one should be the "semantic" one,
    27  	//     e.g. it *always* acts like a map for structs, even if the repr is different.)
    28  
    29  	NodeGenerator
    30  
    31  	// -- and the representation and its node and nodebuilder -->
    32  	//    (these vary!)
    33  
    34  	EmitTypedNodeMethodRepresentation(io.Writer)
    35  	GetRepresentationNodeGen() NodeGenerator // includes transitively the matched NodeBuilderGenerator
    36  }
    37  
    38  type NodeGenerator interface {
    39  	EmitNodeType(io.Writer)           // usually already covered by EmitNativeType for the primary node, but has a nonzero body for the repr node
    40  	EmitNodeTypeAssertions(io.Writer) // optional to include this content
    41  	EmitNodeMethodKind(io.Writer)
    42  	EmitNodeMethodLookupByString(io.Writer)
    43  	EmitNodeMethodLookupByNode(io.Writer)
    44  	EmitNodeMethodLookupByIndex(io.Writer)
    45  	EmitNodeMethodLookupBySegment(io.Writer)
    46  	EmitNodeMethodMapIterator(io.Writer)  // also iterator itself
    47  	EmitNodeMethodListIterator(io.Writer) // also iterator itself
    48  	EmitNodeMethodLength(io.Writer)
    49  	EmitNodeMethodIsAbsent(io.Writer)
    50  	EmitNodeMethodIsNull(io.Writer)
    51  	EmitNodeMethodAsBool(io.Writer)
    52  	EmitNodeMethodAsInt(io.Writer)
    53  	EmitNodeMethodAsFloat(io.Writer)
    54  	EmitNodeMethodAsString(io.Writer)
    55  	EmitNodeMethodAsBytes(io.Writer)
    56  	EmitNodeMethodAsLink(io.Writer)
    57  	EmitNodeMethodPrototype(io.Writer)
    58  	EmitNodePrototypeType(io.Writer)
    59  	GetNodeBuilderGenerator() NodeBuilderGenerator // assembler features also included inside
    60  }
    61  
    62  type NodeBuilderGenerator interface {
    63  	EmitNodeBuilderType(io.Writer)
    64  	EmitNodeBuilderMethods(io.Writer) // not many, so just slung them together.
    65  	EmitNodeAssemblerType(io.Writer)  // you can call this and not EmitNodeBuilderType in some situations.
    66  	EmitNodeAssemblerMethodBeginMap(io.Writer)
    67  	EmitNodeAssemblerMethodBeginList(io.Writer)
    68  	EmitNodeAssemblerMethodAssignNull(io.Writer)
    69  	EmitNodeAssemblerMethodAssignBool(io.Writer)
    70  	EmitNodeAssemblerMethodAssignInt(io.Writer)
    71  	EmitNodeAssemblerMethodAssignFloat(io.Writer)
    72  	EmitNodeAssemblerMethodAssignString(io.Writer)
    73  	EmitNodeAssemblerMethodAssignBytes(io.Writer)
    74  	EmitNodeAssemblerMethodAssignLink(io.Writer)
    75  	EmitNodeAssemblerMethodAssignNode(io.Writer)
    76  	EmitNodeAssemblerMethodPrototype(io.Writer)
    77  	EmitNodeAssemblerOtherBits(io.Writer) // key and value child assemblers are done here.
    78  }
    79  
    80  // EmitFileHeader emits a baseline package header that will
    81  // allow a file with a generated type to compile.
    82  // (Fortunately, there are no variations in this.)
    83  func EmitFileHeader(packageName string, w io.Writer) {
    84  	fmt.Fprintf(w, "package %s\n\n", packageName)
    85  	fmt.Fprintf(w, doNotEditComment+"\n\n")
    86  	fmt.Fprintf(w, "import (\n")
    87  	fmt.Fprintf(w, "\t\"github.com/ipld/go-ipld-prime/datamodel\"\n")
    88  	fmt.Fprintf(w, "\t\"github.com/ipld/go-ipld-prime/node/mixins\"\n")
    89  	fmt.Fprintf(w, "\t\"github.com/ipld/go-ipld-prime/schema\"\n")
    90  	fmt.Fprintf(w, ")\n\n")
    91  }
    92  
    93  // EmitEntireType is a helper function calls all methods of TypeGenerator
    94  // and streams all results into a single writer.
    95  // (This implies two calls to EmitNode -- one for the type-level and one for the representation-level.)
    96  func EmitEntireType(tg TypeGenerator, w io.Writer) {
    97  	tg.EmitNativeType(w)
    98  	tg.EmitNativeAccessors(w)
    99  	tg.EmitNativeBuilder(w)
   100  	tg.EmitNativeMaybe(w)
   101  	EmitNode(tg, w)
   102  	tg.EmitTypedNodeMethodType(w)
   103  	tg.EmitTypedNodeMethodRepresentation(w)
   104  
   105  	rng := tg.GetRepresentationNodeGen()
   106  	if rng == nil { // FIXME: hack to save me from stubbing tons right now, remove when done
   107  		return
   108  	}
   109  	EmitNode(rng, w)
   110  }
   111  
   112  // EmitNode is a helper function that calls all methods of NodeGenerator
   113  // and streams all results into a single writer.
   114  func EmitNode(ng NodeGenerator, w io.Writer) {
   115  	ng.EmitNodeType(w)
   116  	ng.EmitNodeTypeAssertions(w)
   117  	ng.EmitNodeMethodKind(w)
   118  	ng.EmitNodeMethodLookupByString(w)
   119  	ng.EmitNodeMethodLookupByNode(w)
   120  	ng.EmitNodeMethodLookupByIndex(w)
   121  	ng.EmitNodeMethodLookupBySegment(w)
   122  	ng.EmitNodeMethodMapIterator(w)
   123  	ng.EmitNodeMethodListIterator(w)
   124  	ng.EmitNodeMethodLength(w)
   125  	ng.EmitNodeMethodIsAbsent(w)
   126  	ng.EmitNodeMethodIsNull(w)
   127  	ng.EmitNodeMethodAsBool(w)
   128  	ng.EmitNodeMethodAsInt(w)
   129  	ng.EmitNodeMethodAsFloat(w)
   130  	ng.EmitNodeMethodAsString(w)
   131  	ng.EmitNodeMethodAsBytes(w)
   132  	ng.EmitNodeMethodAsLink(w)
   133  	ng.EmitNodeMethodPrototype(w)
   134  
   135  	ng.EmitNodePrototypeType(w)
   136  
   137  	nbg := ng.GetNodeBuilderGenerator()
   138  	if nbg == nil { // FIXME: hack to save me from stubbing tons right now, remove when done
   139  		return
   140  	}
   141  	nbg.EmitNodeBuilderType(w)
   142  	nbg.EmitNodeBuilderMethods(w)
   143  	nbg.EmitNodeAssemblerType(w)
   144  	nbg.EmitNodeAssemblerMethodBeginMap(w)
   145  	nbg.EmitNodeAssemblerMethodBeginList(w)
   146  	nbg.EmitNodeAssemblerMethodAssignNull(w)
   147  	nbg.EmitNodeAssemblerMethodAssignBool(w)
   148  	nbg.EmitNodeAssemblerMethodAssignInt(w)
   149  	nbg.EmitNodeAssemblerMethodAssignFloat(w)
   150  	nbg.EmitNodeAssemblerMethodAssignString(w)
   151  	nbg.EmitNodeAssemblerMethodAssignBytes(w)
   152  	nbg.EmitNodeAssemblerMethodAssignLink(w)
   153  	nbg.EmitNodeAssemblerMethodAssignNode(w)
   154  	nbg.EmitNodeAssemblerMethodPrototype(w)
   155  	nbg.EmitNodeAssemblerOtherBits(w)
   156  }
   157  
   158  func EmitTypeTable(pkgName string, ts schema.TypeSystem, adjCfg *AdjunctCfg, w io.Writer) {
   159  	// REVIEW: if "T__Repr" is how we want to expose this.  We could also put 'Repr' accessors on the type/prototype objects.
   160  	// FUTURE: types and prototypes are proposed to be the same.  Some of this text pretends they already are, but work is needed on this.
   161  	doTemplate(`
   162  		// Type is a struct embeding a NodePrototype/Type for every Node implementation in this package.
   163  		// One of its major uses is to start the construction of a value.
   164  		// You can use it like this:
   165  		//
   166  		// 		`+pkgName+`.Type.YourTypeName.NewBuilder().BeginMap() //...
   167  		//
   168  		// and:
   169  		//
   170  		// 		`+pkgName+`.Type.OtherTypeName.NewBuilder().AssignString("x") // ...
   171  		//
   172  		var Type typeSlab
   173  
   174  		type typeSlab struct {
   175  			{{- range . }}
   176  			{{ .Name }}       _{{ . | TypeSymbol }}__Prototype
   177  			{{ .Name }}__Repr _{{ . | TypeSymbol }}__ReprPrototype
   178  			{{- end}}
   179  		}
   180  	`, w, adjCfg, ts.GetTypes())
   181  }