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

     1  hacking gengo
     2  =============
     3  
     4  What the heck?
     5  --------------
     6  
     7  We're doing code generation.
     8  
     9  The name of the game is "keep it simple".
    10  Most of this is implemented as string templating.
    11  No, we didn't use the Go AST system.  We could have; we didn't.
    12  Implementing this as string templating seemed easier to mentally model,
    13  and the additional value provided by use of AST libraries seems minimal
    14  since we feed the outputs into a compiler for verification immediately anyway.
    15  
    16  Some things seem significantly redundant.
    17  That's probably because they are.
    18  In general, if there's a choice between apparent redundancy in the generator itself
    19  versus almost any other tradeoff which affects the outputs, we prioritize the outputs.
    20  (This may be especially noticable when it comes to error messages: we emit a lot
    21  of them... while making sure they contain very specific references.  This leads
    22  to some seemingly redundant code, but good error messages are worth it.)
    23  
    24  See [README_behaviors](README_behaviors.md) for notes about the behaviors of the code output by the generator;
    25  this document is about the generator code itself and the design thereof.
    26  
    27  
    28  Entrypoints
    29  -----------
    30  
    31  The most important intefaces are all in [`generators.go`](generators.go).
    32  
    33  The function you're most likely looking for that "does the thing" is the
    34  `Generate(outputPath string, pkgName string, schema.TypeSystem, *AdjunctCfg)` method,
    35  which can be found in the [`generate.go`](generate.go) file.
    36  You can take any of the functions inside of that and use them as well,
    37  if you want more granular control over what content ends up in which files.
    38  
    39  The eventual plan is be able to drive this whole apparatus around via a CLI
    40  which consumes IPLD Schema files.
    41  Implementing this can come after more of the core is done.
    42  (Seealso the `schema/tmpBuilders.go` file a couple directories up for why
    43  this is currently filed as nontrivial/do-later.)
    44  
    45  
    46  Organization
    47  ------------
    48  
    49  ### How many things are generated, anyway?
    50  
    51  There are roughly *seven* categories of API to generate per type:
    52  
    53  - 1: the readonly thing a native caller uses
    54  - 2: the builder thing a native caller uses
    55  - 3: the readonly typed node
    56  - 4: the builder/assembler for typed node
    57  - 5: the readonly representation node
    58  - 6: the builder/assembler via representation
    59  - 7: and a maybe wrapper
    60  
    61  (And these are just the ones nominally visible in the exported API surface!
    62  There are several more concrete types than this implied by some parts of that list,
    63  such as iterators for the nodes, internal parts of builders, and so forth.)
    64  
    65  These numbers will be used to describe some further organization.
    66  
    67  ### How are the generator components grouped?
    68  
    69  There are three noteworthy types of generator internals:
    70  
    71  - `TypeGenerator`
    72  - `NodeGenerator`
    73  - `NodebuilderGenerator`
    74  
    75  The first one is where you start; the latter two do double duty for each type.
    76  
    77  Exported types for purpose 1, 2, 3, and 7 are emitted from `TypeGenerator` (3 from the embedded `NodeGenerator`).
    78  
    79  The exported type for purpose 5 is emitted from another `NodeGenerator` instance.
    80  
    81  The exported types for purposes 4 and 6 are emitted from two distinct `NodebuilderGenerator` instances.
    82  
    83  For every variation in type kind and representation strategy for that type kind,
    84  one type implementing `TypeGenerator` is composed, and it has functions which
    85  yield all the other interfaces for addressing the various purposes.
    86  
    87  ### How are files and their contents grouped?
    88  
    89  Most of the files in this package are following a pattern:
    90  
    91  - for each kind:
    92  	- `gen{Kind}.go` -- has emitters for the native type parts (1, 2, 7) and type-level node behaviors (3, 4).
    93  	- for each representation that kind can have:
    94  		- `gen{Kind}Repr{ReprStrat}.go` -- has emitters for (5, 6).
    95  
    96  A `mixins` sub-package contains some code which is used and embedded in the generators in this package.
    97  These features are mostly per-kind -- representation kind, not type-level kind.
    98  For example, you'll see "map" behaviors from the mixins package added to "struct" generators.
    99  
   100  ### What are all these abbreviations?
   101  
   102  See [HACKME_abbrevs.md](HACKME_abbrevs.md).
   103  
   104  ### Code architecture
   105  
   106  See [HACKME_tradeoffs.md](HACKME_tradeoffs.md) for an overview of tradeoffs,
   107  and which priorities we selected in this package.
   108  (There are *many* tradeoffs.)
   109  
   110  See [HACKME_memorylayout.md](HACKME_memorylayout.md) for a (large) amount of
   111  exposition on how this code is designed in order to be allocation-avoidant
   112  and fast in general.
   113  
   114  See [HACKME_templates.md](HACKME_templates.md) for some overview on how we've
   115  used templates, and what forms of reuse and abstraction there are.
   116  
   117  See [HACKME_scalars.md](HACKME_scalars.md) for some discussion of scalars
   118  and (why we generate more of them than you might expect).
   119  
   120  See [HACKME_maybe.md](HACKME_maybe.md) for notes how how the 'maybe' feature
   121  (how we describe `nullable` and `optional` schema features in generated golang code)
   122  has evolved.
   123  
   124  
   125  Testing
   126  -------
   127  
   128  See [HACKME_testing.md](HACKME_testing.md) for some details about how this works.
   129  
   130  In general, try to copy some of the existing tests and get things to suit.
   131  
   132  Be advised that we use the golang plugin feature, and that has some additional
   133  requirements of your development environment than is usual in golang.
   134  (Namely, you have to be on linux and you have to have a c compiler!)
   135