-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Codegen output rearrange #105
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,133 @@ | ||
package gengo | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"path/filepath" | ||
"sort" | ||
|
||
"github.com/ipld/go-ipld-prime/schema" | ||
) | ||
|
||
// Generate takes a typesystem and the adjunct config for codegen, | ||
// and emits generated code in the given path with the given package name. | ||
// | ||
// All of the files produced will match the pattern "ipldsch.*.gen.go". | ||
func Generate(pth string, pkgName string, ts schema.TypeSystem, adjCfg *AdjunctCfg) { | ||
// Emit fixed bits. | ||
withFile(filepath.Join(pth, "ipldsch_minima.go"), func(f io.Writer) { | ||
EmitInternalEnums(pkgName, f) | ||
}) | ||
|
||
// Local helper function for applying generation logic to each type. | ||
// We will end up doing this more than once because in this layout, more than one file contains part of the story for each type. | ||
applyToEachType := func(fn func(tg TypeGenerator, w io.Writer), f io.Writer) { | ||
// Sort the type names so we have a determinisic order; this affects output consistency. | ||
// Any stable order would do, but we don't presently have one, so a sort is necessary. | ||
types := ts.GetTypes() | ||
keys := make(sortableTypeNames, 0, len(types)) | ||
for tn := range types { | ||
keys = append(keys, tn) | ||
} | ||
sort.Sort(keys) | ||
for _, tn := range keys { | ||
switch t2 := types[tn].(type) { | ||
case *schema.TypeBool: | ||
fn(NewBoolReprBoolGenerator(pkgName, t2, adjCfg), f) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this code feels repetitive to me; it seems like you could do:
|
||
case *schema.TypeInt: | ||
fn(NewIntReprIntGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeFloat: | ||
fn(NewFloatReprFloatGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeString: | ||
fn(NewStringReprStringGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeBytes: | ||
fn(NewBytesReprBytesGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeLink: | ||
fn(NewLinkReprLinkGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeStruct: | ||
switch t2.RepresentationStrategy().(type) { | ||
case schema.StructRepresentation_Map: | ||
fn(NewStructReprMapGenerator(pkgName, t2, adjCfg), f) | ||
case schema.StructRepresentation_Tuple: | ||
fn(NewStructReprTupleGenerator(pkgName, t2, adjCfg), f) | ||
case schema.StructRepresentation_Stringjoin: | ||
fn(NewStructReprStringjoinGenerator(pkgName, t2, adjCfg), f) | ||
default: | ||
panic("unrecognized struct representation strategy") | ||
} | ||
case *schema.TypeMap: | ||
fn(NewMapReprMapGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeList: | ||
fn(NewListReprListGenerator(pkgName, t2, adjCfg), f) | ||
case *schema.TypeUnion: | ||
switch t2.RepresentationStrategy().(type) { | ||
case schema.UnionRepresentation_Keyed: | ||
fn(NewUnionReprKeyedGenerator(pkgName, t2, adjCfg), f) | ||
case schema.UnionRepresentation_Kinded: | ||
fn(NewUnionReprKindedGenerator(pkgName, t2, adjCfg), f) | ||
default: | ||
panic("unrecognized union representation strategy") | ||
} | ||
default: | ||
panic("add more type switches here :)") | ||
} | ||
} | ||
} | ||
|
||
// Emit a file with the type table, and the golang type defns for each type. | ||
withFile(filepath.Join(pth, "ipldsch_types.go"), func(f io.Writer) { | ||
// Emit headers, import statements, etc. | ||
fmt.Fprintf(f, "package %s\n\n", pkgName) | ||
fmt.Fprintf(f, doNotEditComment+"\n\n") | ||
|
||
// Emit the type table. | ||
EmitTypeTable(pkgName, ts, adjCfg, f) | ||
|
||
// Emit the type defns matching the schema types. | ||
fmt.Fprintf(f, "\n// --- type definitions follow ---\n\n") | ||
applyToEachType(func(tg TypeGenerator, w io.Writer) { | ||
tg.EmitNativeType(w) | ||
fmt.Fprintf(f, "\n") | ||
}, f) | ||
|
||
}) | ||
|
||
// Emit a file with all the Node/NodeBuilder/NodeAssembler boilerplate. | ||
// Also includes typedefs for representation-level data. | ||
// Also includes the MaybeT boilerplate. | ||
withFile(filepath.Join(pth, "ipldsch_satisfaction.go"), func(f io.Writer) { | ||
// Emit headers, import statements, etc. | ||
fmt.Fprintf(f, "package %s\n\n", pkgName) | ||
fmt.Fprintf(f, doNotEditComment+"\n\n") | ||
fmt.Fprintf(f, "import (\n") | ||
fmt.Fprintf(f, "\tipld \"github.com/ipld/go-ipld-prime\"\n") // referenced everywhere. | ||
fmt.Fprintf(f, "\t\"github.com/ipld/go-ipld-prime/node/mixins\"\n") // referenced by node implementation guts. | ||
fmt.Fprintf(f, "\t\"github.com/ipld/go-ipld-prime/schema\"\n") // referenced by maybes (and surprisingly little else). | ||
fmt.Fprintf(f, ")\n\n") | ||
|
||
// For each type, we'll emit... everything except the native type, really. | ||
applyToEachType(func(tg TypeGenerator, w io.Writer) { | ||
tg.EmitNativeAccessors(w) | ||
tg.EmitNativeBuilder(w) | ||
tg.EmitNativeMaybe(w) | ||
EmitNode(tg, w) | ||
tg.EmitTypedNodeMethodType(w) | ||
tg.EmitTypedNodeMethodRepresentation(w) | ||
|
||
nrg := tg.GetRepresentationNodeGen() | ||
EmitNode(nrg, w) | ||
|
||
fmt.Fprintf(f, "\n") | ||
}, f) | ||
}) | ||
} | ||
|
||
// GenerateSplayed is like Generate, but emits a differnet pattern of files. | ||
// GenerateSplayed emits many more individual files than Generate. | ||
// | ||
// This function should be considered deprecated and may be removed in the future. | ||
func GenerateSplayed(pth string, pkgName string, ts schema.TypeSystem, adjCfg *AdjunctCfg) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd personally remove it directly. The old code will always be in the git history if we wish to reuse it. |
||
// Emit fixed bits. | ||
withFile(filepath.Join(pth, "minima.go"), func(f io.Writer) { | ||
EmitInternalEnums(pkgName, f) | ||
|
@@ -63,6 +182,8 @@ func Generate(pth string, pkgName string, ts schema.TypeSystem, adjCfg *AdjunctC | |
|
||
// Emit the unified type table. | ||
withFile(filepath.Join(pth, "typeTable.go"), func(f io.Writer) { | ||
fmt.Fprintf(f, "package %s\n\n", pkgName) | ||
fmt.Fprintf(f, doNotEditComment+"\n\n") | ||
EmitTypeTable(pkgName, ts, adjCfg, f) | ||
}) | ||
} | ||
|
@@ -75,3 +196,9 @@ func withFile(filename string, fn func(io.Writer)) { | |
defer f.Close() | ||
fn(f) | ||
} | ||
|
||
type sortableTypeNames []schema.TypeName | ||
|
||
func (a sortableTypeNames) Len() int { return len(a) } | ||
func (a sortableTypeNames) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | ||
func (a sortableTypeNames) Less(i, j int) bool { return a[i] < a[j] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this? It's trivial to remove comments from Go source code by just using
go/parser
with the comment flag disabled, and re-printing the program. Or, if the code is simple enough, a bit of sed.