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 }