Commit 7ff42bd3 authored by Eric Myhre's avatar Eric Myhre

Nicely composable NodeBuilderGenerator, +mixins.

This cleans up a lot of stuff and reduces the amount of boilerplate
content that's just generating monomorphizing error method stubs.

The nodeGenerator mixins now also use the node mixins.  I don't know
why I failed to do that from the start; I certainly meant to.
It results in shorter generated code, and the compiler turns it into
identical assembly.
parent 96d63add
......@@ -148,12 +148,36 @@ func (g stringGenerator) EmitNodeStyleType(w io.Writer) {
// --- NodeBuilder and NodeAssembler --->
func (g stringGenerator) EmitNodeBuilder(w io.Writer) {
func (g stringGenerator) GetNodeBuilderGenerator() NodeBuilderGenerator {
return stringBuilderGenerator{
g.AdjCfg,
mixins.StringAssemblerTraits{
g.PkgName,
g.TypeName,
"_" + g.AdjCfg.TypeSymbol(g.Type),
"_" + g.AdjCfg.TypeSymbol(g.Type) + "__",
},
g.PkgName,
g.Type,
}
}
type stringBuilderGenerator struct {
AdjCfg *AdjunctCfg
mixins.StringAssemblerTraits
PkgName string
Type schema.TypeString
}
func (g stringBuilderGenerator) EmitNodeBuilderType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Builder struct {
_{{ .Type | TypeSymbol }}__Assembler
}
`, w, g.AdjCfg, g)
}
func (g stringBuilderGenerator) EmitNodeBuilderMethods(w io.Writer) {
doTemplate(`
func (nb *_{{ .Type | TypeSymbol }}__Builder) Build() ipld.Node {
return nb.w
}
......@@ -163,51 +187,13 @@ func (g stringGenerator) EmitNodeBuilder(w io.Writer) {
}
`, w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNodeAssembler(w io.Writer) {
func (g stringBuilderGenerator) EmitNodeAssemblerType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Assembler struct {
w *_{{ .Type | TypeSymbol }}
}
func (_{{ .Type | TypeSymbol }}__Assembler) BeginMap(sizeHint int) (ipld.MapAssembler, error) {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.BeginMap(0)
}
func (_{{ .Type | TypeSymbol }}__Assembler) BeginList(sizeHint int) (ipld.ListAssembler, error) {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.BeginList(0)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignNull() error {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignNull()
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignBool(bool) error {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignBool(false)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignInt(int) error {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignInt(0)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignFloat(float64) error {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignFloat(0)
}
func (na *_{{ .Type | TypeSymbol }}__Assembler) AssignString(v string) error {
*na.w = _{{ .Type | TypeSymbol }}{v}
return nil
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignBytes([]byte) error {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignBytes(nil)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignLink(ipld.Link) error {
return mixins.StringAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignLink(nil)
}
func (na *_{{ .Type | TypeSymbol }}__Assembler) AssignNode(v ipld.Node) error {
if v2, err := v.AsString(); err != nil {
return err
} else {
*na.w = _{{ .Type | TypeSymbol }}{v2}
return nil
}
}
func (_{{ .Type | TypeSymbol }}__Assembler) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, g.AdjCfg, g)
}
func (g stringBuilderGenerator) EmitNodeAssemblerOtherBits(w io.Writer) {
// Nothing needed here for string kinds.
}
......@@ -29,11 +29,15 @@ type stringReprStringGenerator struct {
}
func (g stringReprStringGenerator) GetRepresentationNodeGen() NodeGenerator {
return stringReprStringReprGenerator{g.stringGenerator}
return stringReprStringReprGenerator{
g.AdjCfg,
g.Type,
}
}
type stringReprStringReprGenerator struct {
stringGenerator
AdjCfg *AdjunctCfg
Type schema.TypeString
}
func (g stringReprStringReprGenerator) EmitNodeType(w io.Writer) {
......@@ -66,5 +70,24 @@ func (stringReprStringReprGenerator) EmitNodeMethodAsBytes(io.Writer) {}
func (stringReprStringReprGenerator) EmitNodeMethodAsLink(io.Writer) {}
func (stringReprStringReprGenerator) EmitNodeMethodStyle(io.Writer) {}
func (stringReprStringReprGenerator) EmitNodeStyleType(io.Writer) {}
func (stringReprStringReprGenerator) EmitNodeBuilder(io.Writer) {}
func (stringReprStringReprGenerator) EmitNodeAssembler(io.Writer) {}
func (stringReprStringReprGenerator) GetNodeBuilderGenerator() NodeBuilderGenerator {
return stringReprStringReprBuilderGenerator{}
}
type stringReprStringReprBuilderGenerator struct{}
func (stringReprStringReprBuilderGenerator) EmitNodeBuilderType(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeBuilderMethods(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerType(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodBeginMap(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodBeginList(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignNull(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignBool(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignInt(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignFloat(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignString(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignBytes(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignLink(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerMethodStyle(io.Writer) {}
func (stringReprStringReprBuilderGenerator) EmitNodeAssemblerOtherBits(io.Writer) {}
......@@ -225,12 +225,35 @@ func (g structGenerator) EmitNodeStyleType(w io.Writer) {
// --- NodeBuilder and NodeAssembler --->
func (g structGenerator) EmitNodeBuilder(w io.Writer) {
func (g structGenerator) GetNodeBuilderGenerator() NodeBuilderGenerator {
return structBuilderGenerator{
g.AdjCfg,
mixins.MapAssemblerTraits{
g.PkgName,
g.TypeName,
"_" + g.AdjCfg.TypeSymbol(g.Type) + "__",
},
g.PkgName,
g.Type,
}
}
type structBuilderGenerator struct {
AdjCfg *AdjunctCfg
mixins.MapAssemblerTraits
PkgName string
Type schema.TypeStruct
}
func (g structBuilderGenerator) EmitNodeBuilderType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Builder struct {
_{{ .Type | TypeSymbol }}__Assembler
}
`, w, g.AdjCfg, g)
}
func (g structBuilderGenerator) EmitNodeBuilderMethods(w io.Writer) {
doTemplate(`
func (nb *_{{ .Type | TypeSymbol }}__Builder) Build() ipld.Node {
if nb.state != maState_finished {
panic("invalid state: assembler for {{ .PkgName }}.{{ .Type.Name }} must be 'finished' before Build can be called!")
......@@ -243,57 +266,38 @@ func (g structGenerator) EmitNodeBuilder(w io.Writer) {
}
`, w, g.AdjCfg, g)
}
func (g structGenerator) EmitNodeAssembler(w io.Writer) {
func (g structBuilderGenerator) EmitNodeAssemblerType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Assembler struct {
w *_{{ .Type | TypeSymbol }}
state maState
}
`, w, g.AdjCfg, g)
}
func (g structBuilderGenerator) EmitNodeAssemblerMethodBeginMap(w io.Writer) {
doTemplate(`
func (na *_{{ .Type | TypeSymbol }}__Assembler) BeginMap(sizeHint int) (ipld.MapAssembler, error) {
panic("todo structassembler beginmap")
}
func (_{{ .Type | TypeSymbol }}__Assembler) BeginList(sizeHint int) (ipld.ListAssembler, error) {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.BeginList(0)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignNull() error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignNull()
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignBool(bool) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignBool(false)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignInt(int) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignInt(0)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignFloat(float64) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignFloat(0)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignString(v string) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignString("")
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignBytes([]byte) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignBytes(nil)
}
func (_{{ .Type | TypeSymbol }}__Assembler) AssignLink(ipld.Link) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}"}.AssignLink(nil)
panic("todo structBuilderGenerator BeginMap")
}
`, w, g.AdjCfg, g)
}
func (g structBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.Writer) {
doTemplate(`
func (na *_{{ .Type | TypeSymbol }}__Assembler) AssignNode(v ipld.Node) error {
panic("todo structassembler assignNode")
}
func (_{{ .Type | TypeSymbol }}__Assembler) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
panic("todo structBuilderGenerator AssignNode")
}
`, w, g.AdjCfg, g)
}
func (g structBuilderGenerator) EmitNodeAssemblerOtherBits(w io.Writer) {
// TODO key assembler goes here. or in a small helper method for org purposes, whatever.
for _, field := range g.Type.Fields() {
g.emitFieldValueAssembler(field, w)
}
}
func (g structGenerator) emitFieldValueAssembler(f schema.StructField, w io.Writer) {
func (g structBuilderGenerator) emitFieldValueAssembler(f schema.StructField, w io.Writer) {
// TODO for Any, this should do a whole Thing;
// TODO for any specific type, we should be able to tersely create a new type that embeds its assembler and wraps the one method that's valid for finishing its kind.
doTemplate(`
// todo child assembler for field {{ .Name }}
`, w, g.AdjCfg, f)
}
......@@ -250,12 +250,35 @@ func (g structReprMapReprGenerator) EmitNodeStyleType(w io.Writer) {
// --- NodeBuilder and NodeAssembler --->
func (g structReprMapReprGenerator) EmitNodeBuilder(w io.Writer) {
func (g structReprMapReprGenerator) GetNodeBuilderGenerator() NodeBuilderGenerator {
return structReprMapReprBuilderGenerator{
g.AdjCfg,
mixins.MapAssemblerTraits{
g.PkgName,
g.TypeName,
"_" + g.AdjCfg.TypeSymbol(g.Type) + "__Repr",
},
g.PkgName,
g.Type,
}
}
type structReprMapReprBuilderGenerator struct {
AdjCfg *AdjunctCfg
mixins.MapAssemblerTraits
PkgName string
Type schema.TypeStruct
}
func (g structReprMapReprBuilderGenerator) EmitNodeBuilderType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__ReprBuilder struct {
_{{ .Type | TypeSymbol }}__ReprAssembler
}
`, w, g.AdjCfg, g)
}
func (g structReprMapReprBuilderGenerator) EmitNodeBuilderMethods(w io.Writer) {
doTemplate(`
func (nb *_{{ .Type | TypeSymbol }}__ReprBuilder) Build() ipld.Node {
if nb.state != maState_finished {
panic("invalid state: assembler for {{ .PkgName }}.{{ .Type.Name }}.Repr must be 'finished' before Build can be called!")
......@@ -268,47 +291,38 @@ func (g structReprMapReprGenerator) EmitNodeBuilder(w io.Writer) {
}
`, w, g.AdjCfg, g)
}
func (g structReprMapReprGenerator) EmitNodeAssembler(w io.Writer) {
// FIXME this is getting egregious; it's high time to break EmitNodeAssembler down into a generator with more reusable parts.
func (g structReprMapReprBuilderGenerator) EmitNodeAssemblerType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__ReprAssembler struct {
w *_{{ .Type | TypeSymbol }}
state maState
}
`, w, g.AdjCfg, g)
}
func (g structReprMapReprBuilderGenerator) EmitNodeAssemblerMethodBeginMap(w io.Writer) {
doTemplate(`
func (na *_{{ .Type | TypeSymbol }}__ReprAssembler) BeginMap(sizeHint int) (ipld.MapAssembler, error) {
panic("todo structassembler reprmap beginmap")
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) BeginList(sizeHint int) (ipld.ListAssembler, error) {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.BeginList(0)
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignNull() error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignNull()
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignBool(bool) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignBool(false)
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignInt(int) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignInt(0)
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignFloat(float64) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignFloat(0)
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignString(v string) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignString("")
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignBytes([]byte) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignBytes(nil)
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) AssignLink(ipld.Link) error {
return mixins.MapAssembler{"{{ .PkgName }}.{{ .Type.Name }}.Repr"}.AssignLink(nil)
panic("todo structReprMapReprBuilderGenerator BeginMap")
}
`, w, g.AdjCfg, g)
}
func (g structReprMapReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.Writer) {
doTemplate(`
func (na *_{{ .Type | TypeSymbol }}__ReprAssembler) AssignNode(v ipld.Node) error {
panic("todo structassembler assignNode")
}
func (_{{ .Type | TypeSymbol }}__ReprAssembler) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__ReprStyle{}
panic("todo structReprMapReprBuilderGenerator AssignNode")
}
`, w, g.AdjCfg, g)
}
func (g structReprMapReprBuilderGenerator) EmitNodeAssemblerOtherBits(w io.Writer) {
// TODO key assembler goes here. or in a small helper method for org purposes, whatever.
for _, field := range g.Type.Fields() {
g.emitFieldValueAssembler(field, w)
}
}
func (g structReprMapReprBuilderGenerator) emitFieldValueAssembler(f schema.StructField, w io.Writer) {
// TODO for Any, this should do a whole Thing;
// TODO for any specific type, we should be able to tersely create a new type that embeds its assembler and wraps the one method that's valid for finishing its kind.
doTemplate(`
// todo child assembler for field {{ .Name }}
`, w, g.AdjCfg, f)
}
......@@ -34,7 +34,7 @@ type TypeGenerator interface {
// (these vary!)
EmitTypedNodeMethodRepresentation(io.Writer)
GetRepresentationNodeGen() NodeGenerator // includes transitively the matched nodebuilderGenerator
GetRepresentationNodeGen() NodeGenerator // includes transitively the matched NodeBuilderGenerator
}
type NodeGenerator interface {
......@@ -58,8 +58,25 @@ type NodeGenerator interface {
EmitNodeMethodAsLink(io.Writer)
EmitNodeMethodStyle(io.Writer)
EmitNodeStyleType(io.Writer)
EmitNodeBuilder(io.Writer) // the whole thing
EmitNodeAssembler(io.Writer) // the whole thing
GetNodeBuilderGenerator() NodeBuilderGenerator // assembler features also included inside
}
type NodeBuilderGenerator interface {
EmitNodeBuilderType(io.Writer)
EmitNodeBuilderMethods(io.Writer) // not many, so just slung them together.
EmitNodeAssemblerType(io.Writer) // you can call this and not EmitNodeBuilderType in some situations.
EmitNodeAssemblerMethodBeginMap(io.Writer)
EmitNodeAssemblerMethodBeginList(io.Writer)
EmitNodeAssemblerMethodAssignNull(io.Writer)
EmitNodeAssemblerMethodAssignBool(io.Writer)
EmitNodeAssemblerMethodAssignInt(io.Writer)
EmitNodeAssemblerMethodAssignFloat(io.Writer)
EmitNodeAssemblerMethodAssignString(io.Writer)
EmitNodeAssemblerMethodAssignBytes(io.Writer)
EmitNodeAssemblerMethodAssignLink(io.Writer)
EmitNodeAssemblerMethodAssignNode(io.Writer)
EmitNodeAssemblerMethodStyle(io.Writer)
EmitNodeAssemblerOtherBits(io.Writer) // key and value child assemblers are done here.
}
// EmitFileHeader emits a baseline package header that will
......@@ -116,6 +133,23 @@ func EmitNode(ng NodeGenerator, w io.Writer) {
ng.EmitNodeStyleType(w)
ng.EmitNodeBuilder(w)
ng.EmitNodeAssembler(w)
nbg := ng.GetNodeBuilderGenerator()
if nbg == nil { // FIXME: hack to save me from stubbing tons right now, remove when done
return
}
nbg.EmitNodeBuilderType(w)
nbg.EmitNodeBuilderMethods(w)
nbg.EmitNodeAssemblerType(w)
nbg.EmitNodeAssemblerMethodBeginMap(w)
nbg.EmitNodeAssemblerMethodBeginList(w)
nbg.EmitNodeAssemblerMethodAssignNull(w)
nbg.EmitNodeAssemblerMethodAssignBool(w)
nbg.EmitNodeAssemblerMethodAssignInt(w)
nbg.EmitNodeAssemblerMethodAssignFloat(w)
nbg.EmitNodeAssemblerMethodAssignString(w)
nbg.EmitNodeAssemblerMethodAssignBytes(w)
nbg.EmitNodeAssemblerMethodAssignLink(w)
nbg.EmitNodeAssemblerMethodAssignNode(w)
nbg.EmitNodeAssemblerMethodStyle(w)
nbg.EmitNodeAssemblerOtherBits(w)
}
......@@ -14,6 +14,9 @@ import (
// and that is not what you want for the methods that *are* interesting for your kind.
// The kindTraitsGenerator methods will panic if called for a kind that should've overriden them.
//
// If you're implementing something that can hold "any" kind,
// probably none of these methods apply to you at all.
//
// The other types in this package embed kindTraitsGenerator with a name,
// and only forward the methods to it that don't apply for their kind;
// this means when they're used as an anonymous embed, they grant
......@@ -34,7 +37,7 @@ func (g kindTraitsGenerator) emitNodeMethodLookupString(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) LookupString(string) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "LookupString", AppropriateKind: ipld.ReprKindSet_JustMap, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.LookupString("")
}
`, w, g)
}
......@@ -45,7 +48,7 @@ func (g kindTraitsGenerator) emitNodeMethodLookup(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) Lookup(ipld.Node) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "Lookup", AppropriateKind: ipld.ReprKindSet_JustMap, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.Lookup(nil)
}
`, w, g)
}
......@@ -56,7 +59,7 @@ func (g kindTraitsGenerator) emitNodeMethodLookupIndex(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) LookupIndex(idx int) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "LookupIndex", AppropriateKind: ipld.ReprKindSet_JustList, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.LookupIndex(0)
}
`, w, g)
}
......@@ -67,7 +70,7 @@ func (g kindTraitsGenerator) emitNodeMethodLookupSegment(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) LookupSegment(seg ipld.PathSegment) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "LookupSegment", AppropriateKind: ipld.ReprKindSet_Recursive, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.LookupSegment(seg)
}
`, w, g)
}
......@@ -127,7 +130,7 @@ func (g kindTraitsGenerator) emitNodeMethodAsBool(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) AsBool() (bool, error) {
return false, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "AsBool", AppropriateKind: ipld.ReprKindSet_JustBool, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.AsBool()
}
`, w, g)
}
......@@ -138,7 +141,7 @@ func (g kindTraitsGenerator) emitNodeMethodAsInt(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) AsInt() (int, error) {
return 0, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "AsInt", AppropriateKind: ipld.ReprKindSet_JustInt, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.AsInt()
}
`, w, g)
}
......@@ -149,7 +152,7 @@ func (g kindTraitsGenerator) emitNodeMethodAsFloat(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) AsFloat() (float64, error) {
return 0, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "AsFloat", AppropriateKind: ipld.ReprKindSet_JustFloat, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.AsFloat()
}
`, w, g)
}
......@@ -160,7 +163,7 @@ func (g kindTraitsGenerator) emitNodeMethodAsString(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) AsString() (string, error) {
return "", ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "AsString", AppropriateKind: ipld.ReprKindSet_JustString, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.AsString()
}
`, w, g)
}
......@@ -171,7 +174,7 @@ func (g kindTraitsGenerator) emitNodeMethodAsBytes(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) AsBytes() ([]byte, error) {
return nil, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "AsBytes", AppropriateKind: ipld.ReprKindSet_JustBytes, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.AsBytes()
}
`, w, g)
}
......@@ -182,7 +185,135 @@ func (g kindTraitsGenerator) emitNodeMethodAsLink(w io.Writer) {
}
doTemplate(`
func ({{ .TypeSymbol }}) AsLink() (ipld.Link, error) {
return nil, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .TypeName }}", MethodName: "AsLink", AppropriateKind: ipld.ReprKindSet_JustLink, ActualKind: ipld.ReprKind_{{ .Kind }}}
return mixins.{{ .Kind }}{"{{ .PkgName }}.{{ .TypeName }}"}.AsLink()
}
`, w, g)
}
// kindAssemblerTraitsGenerator is an awfully lot like kindTraitsGenerator,
// except applying to methods for builders and assemblers.
type kindAssemblerTraitsGenerator struct {
PkgName string
TypeName string // as will be printed in messages (e.g. can be goosed up a bit, like "Thing.Repr" instead of "_Thing__Repr").
AppliedPrefix string // the prefix of what to attach methods to... this one is a little wild: should probably be either "_{{ .Type | TypeSymbol }}__" or "_{{ .Type | TypeSymbol }}__Repr", and we'll just add the words "Builder" and "Assembler".
Kind ipld.ReprKind
}
// bailed on extracting a common emitNodeBuilderType: too many variations in content and pointer placement to be worth it.
// bailed on extracting a common emitNodeBuilderMethods: same.
// bailed on extracting a common emitNodeAssemblerType: same.
//
// If you try to do these, you'll probably need:
// - an explicit understanding of if generating representations or not
// - to still be ready for boatloads of exceptions if the representation isn't directly castable to and from the type-level node.
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodBeginMap(w io.Writer) {
if ipld.ReprKindSet_JustMap.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) BeginMap(sizeHint int) (ipld.MapAssembler, error) {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.BeginMap(0)
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodBeginList(w io.Writer) {
if ipld.ReprKindSet_JustList.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) BeginList(sizeHint int) (ipld.ListAssembler, error) {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.BeginList(0)
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignNull(w io.Writer) {
if ipld.ReprKindSet_JustNull.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignNull() error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignNull()
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignBool(w io.Writer) {
if ipld.ReprKindSet_JustBool.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignBool(bool) error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignBool(false)
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignInt(w io.Writer) {
if ipld.ReprKindSet_JustInt.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignInt(int) error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignInt(0)
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignFloat(w io.Writer) {
if ipld.ReprKindSet_JustFloat.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignFloat(float64) error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignFloat(0)
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignString(w io.Writer) {
if ipld.ReprKindSet_JustString.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignString(string) error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignString("")
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignBytes(w io.Writer) {
if ipld.ReprKindSet_JustBytes.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignBytes([]byte) error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignBytes(nil)
}
`, w, g)
}
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodAssignLink(w io.Writer) {
if ipld.ReprKindSet_JustLink.Contains(g.Kind) {
panic("gen internals error: you should've overriden this")
}
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) AssignLink(ipld.Link) error {
return mixins.{{ .Kind }}Assembler{"{{ .PkgName }}.{{ .TypeName }}"}.AssignLink(nil)
}
`, w, g)
}
// bailed on extracting a common emitNodeAssemblerMethodAssignNode: way too many variations.
func (g kindAssemblerTraitsGenerator) emitNodeAssemblerMethodStyle(w io.Writer) {
doTemplate(`
func ({{ .AppliedPrefix }}Assembler) Style() ipld.NodeStyle {
return {{ .AppliedPrefix }}Style{}
}
`, w, g)
}
// bailed on extracting a common emitNodeAssemblerOtherBits: it's just self-evident there's nothing common there.
......@@ -56,3 +56,37 @@ func (g MapTraits) EmitNodeMethodAsBytes(w io.Writer) {
func (g MapTraits) EmitNodeMethodAsLink(w io.Writer) {
kindTraitsGenerator{g.PkgName, g.TypeName, g.TypeSymbol, ipld.ReprKind_Map}.emitNodeMethodAsLink(w)
}
type MapAssemblerTraits struct {
PkgName string
TypeName string // see doc in kindAssemblerTraitsGenerator
AppliedPrefix string // see doc in kindAssemblerTraitsGenerator
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodBeginList(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodBeginList(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignNull(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignNull(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignBool(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignBool(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignInt(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignInt(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignFloat(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignFloat(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignString(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignString(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignBytes(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignBytes(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodAssignLink(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodAssignLink(w)
}
func (g MapAssemblerTraits) EmitNodeAssemblerMethodStyle(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_Map}.emitNodeAssemblerMethodStyle(w)
}
......@@ -61,3 +61,60 @@ func (g StringTraits) EmitNodeMethodAsBytes(w io.Writer) {
func (g StringTraits) EmitNodeMethodAsLink(w io.Writer) {
kindTraitsGenerator{g.PkgName, g.TypeName, g.TypeSymbol, ipld.ReprKind_String}.emitNodeMethodAsLink(w)
}
type StringAssemblerTraits struct {
PkgName string
TypeName string // see doc in kindAssemblerTraitsGenerator
TypeSymbol string // the core symbol of the typed value (we assume the 'w' pointer will be a pointer to this type)
AppliedPrefix string // see doc in kindAssemblerTraitsGenerator
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodBeginMap(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodBeginMap(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodBeginList(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodBeginList(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignNull(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodAssignNull(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignBool(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodAssignBool(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignInt(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodAssignInt(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignFloat(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodAssignFloat(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignString(w io.Writer) {
// REVIEW: unresolved if this is worth the effort or not; makes this trait need to know TypeSymbol;
// others are shaping up such that things that know TypeSymbol have been over the line for reusability anyway;
// should this one really be special?
doTemplate(`
func (na *{{ .AppliedPrefix }}Assembler) AssignString(v string) error {
*na.w = {{ .TypeSymbol }}{v}
return nil
}
`, w, g)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignBytes(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodAssignBytes(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignLink(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodAssignLink(w)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodAssignNode(w io.Writer) {
doTemplate(`
func (na *{{ .AppliedPrefix }}Assembler) AssignNode(v ipld.Node) error {
if v2, err := v.AsString(); err != nil {
return err
} else {
return na.AssignString(v2)
}
}
`, w, g)
}
func (g StringAssemblerTraits) EmitNodeAssemblerMethodStyle(w io.Writer) {
kindAssemblerTraitsGenerator{g.PkgName, g.TypeName, g.AppliedPrefix, ipld.ReprKind_String}.emitNodeAssemblerMethodStyle(w)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment