Commit 7754ce08 authored by Eric Myhre's avatar Eric Myhre

More extraction and DRY'ing.

Int is now basically all common stuff.  Now I'm really gonna quit.

Interestingly, the total line count isn't going down very fast.
108 insertions, 165 deletions, according to the git diff stat.
Evidentally the overhead of things opting into this is darn near
the amount of lines saved in many cases.
parent 7cdaa71e
......@@ -50,6 +50,78 @@ func emitNativeMaybe(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
`, w, adjCfg, data)
}
func emitNativeType_scalar(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
// Using a struct with a single member is the same size in memory as a typedef,
// while also having the advantage of meaning we can block direct casting,
// which is desirable because the compiler then ensures our validate methods can't be evaded.
doTemplate(`
type _{{ .Type | TypeSymbol }} struct{ x {{ .ReprKind | KindPrim }} }
type {{ .Type | TypeSymbol }} = *_{{ .Type | TypeSymbol }}
`, w, adjCfg, data)
}
func emitNativeAccessors_scalar(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
// The node interface's `AsFoo` method is almost sufficient... but
// this method unboxes without needing to return an error that's statically impossible,
// which makes it easier to use in chaining.
doTemplate(`
func (n {{ .Type | TypeSymbol }}) {{ .ReprKind.String | title }}() {{ .ReprKind | KindPrim }} {
return n.x
}
`, w, adjCfg, data)
}
func emitNativeBuilder_scalar(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
// Generate a single-step construction function -- this is easy to do for a scalar,
// and all representations of scalar kind can be expected to have a method like this.
// The function is attached to the nodestyle for convenient namespacing;
// it needs no new memory, so it would be inappropriate to attach to the builder or assembler.
// FUTURE: should engage validation flow.
doTemplate(`
func (_{{ .Type | TypeSymbol }}__Style) From{{ .ReprKind.String | title }}(v {{ .ReprKind | KindPrim }}) ({{ .Type | TypeSymbol }}, error) {
n := _{{ .Type | TypeSymbol }}{v}
return &n, nil
}
`, w, adjCfg, data)
}
func emitNodeTypeAssertions_typical(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
doTemplate(`
var _ ipld.Node = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
var _ schema.TypedNode = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
`, w, adjCfg, data)
}
func emitNodeMethodAsKind_scalar(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
doTemplate(`
func (n {{ .Type | TypeSymbol }}) As{{ .ReprKind.String | title }}() ({{ .ReprKind | KindPrim }}, error) {
return n.x, nil
}
`, w, adjCfg, data)
}
func emitNodeMethodStyle_typical(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
doTemplate(`
func ({{ .Type | TypeSymbol }}) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, adjCfg, data)
}
// nodeStyle doesn't really vary textually at all between types and kinds
// because it's just builders and standard resets.
func emitNodeStyleType_typical(w io.Writer, adjCfg *AdjunctCfg, data interface{}) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Style struct{}
func (_{{ .Type | TypeSymbol }}__Style) NewBuilder() ipld.NodeBuilder {
var nb _{{ .Type | TypeSymbol }}__Builder
nb.Reset()
return &nb
}
`, w, adjCfg, data)
}
// emitTypicalTypedNodeMethodRepresentation does... what it says on the tin.
//
// For most types, the way to get the representation node pointer doesn't
......@@ -153,7 +225,7 @@ func emitNodeAssemblerMethodAssignKind_scalar(w io.Writer, adjCfg *AdjunctCfg, d
// This allocation only happens if the 'w' ptr is nil, which means we're being used on a Maybe;
// otherwise, the 'w' ptr should already be set, and we fill that memory location without allocating, as usual.
doTemplate(`
func (na *_{{ .Type | TypeSymbol }}__Assembler) Assign{{ .ReprKind.String | title }}(v {{ .ReprKind | KindPrim}}) error {
func (na *_{{ .Type | TypeSymbol }}__Assembler) Assign{{ .ReprKind.String | title }}(v {{ .ReprKind | KindPrim }}) error {
switch *na.m {
case schema.Maybe_Value, schema.Maybe_Null:
panic("invalid state: cannot assign into assembler that's already finished")
......
......@@ -17,38 +17,13 @@ type intGenerator struct {
// --- native content and specializations --->
func (g intGenerator) EmitNativeType(w io.Writer) {
// Using a struct with a single member is the same size in memory as a typedef,
// while also having the advantage of meaning we can block direct casting,
// which is desirable because the compiler then ensures our validate methods can't be evaded.
doTemplate(`
type _{{ .Type | TypeSymbol }} struct{ x int }
type {{ .Type | TypeSymbol }} = *_{{ .Type | TypeSymbol }}
`, w, g.AdjCfg, g)
emitNativeType_scalar(w, g.AdjCfg, g)
}
func (g intGenerator) EmitNativeAccessors(w io.Writer) {
// The node interface's `AsInt` method is almost sufficient... but
// this method unboxes without needing to return an error that's statically impossible,
// which makes it easier to use in chaining.
doTemplate(`
func (n {{ .Type | TypeSymbol }}) Int() int {
return n.x
}
`, w, g.AdjCfg, g)
emitNativeAccessors_scalar(w, g.AdjCfg, g)
}
func (g intGenerator) EmitNativeBuilder(w io.Writer) {
// Generate a single-step construction function -- this is easy to do for a scalar,
// and all representations of scalar kind can be expected to have a method like this.
// The function is attached to the nodestyle for convenient namespacing;
// it needs no new memory, so it would be inappropriate to attach to the builder or assembler.
// FUTURE: should engage validation flow.
doTemplate(`
func (_{{ .Type | TypeSymbol }}__Style) FromInt(v int) ({{ .Type | TypeSymbol }}, error) {
n := _{{ .Type | TypeSymbol }}{v}
return &n, nil
}
`, w, g.AdjCfg, g)
emitNativeBuilder_scalar(w, g.AdjCfg, g)
}
func (g intGenerator) EmitNativeMaybe(w io.Writer) {
......@@ -82,40 +57,17 @@ func (g intGenerator) EmitTypedNodeMethodRepresentation(w io.Writer) {
func (g intGenerator) EmitNodeType(w io.Writer) {
// No additional types needed. Methods all attach to the native type.
}
func (g intGenerator) EmitNodeTypeAssertions(w io.Writer) {
doTemplate(`
var _ ipld.Node = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
var _ schema.TypedNode = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
`, w, g.AdjCfg, g)
emitNodeTypeAssertions_typical(w, g.AdjCfg, g)
}
func (g intGenerator) EmitNodeMethodAsInt(w io.Writer) {
doTemplate(`
func (n {{ .Type | TypeSymbol }}) AsInt() (int, error) {
return n.x, nil
}
`, w, g.AdjCfg, g)
emitNodeMethodAsKind_scalar(w, g.AdjCfg, g)
}
func (g intGenerator) EmitNodeMethodStyle(w io.Writer) {
doTemplate(`
func ({{ .Type | TypeSymbol }}) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, g.AdjCfg, g)
emitNodeMethodStyle_typical(w, g.AdjCfg, g)
}
func (g intGenerator) EmitNodeStyleType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Style struct{}
func (_{{ .Type | TypeSymbol }}__Style) NewBuilder() ipld.NodeBuilder {
var nb _{{ .Type | TypeSymbol }}__Builder
nb.Reset()
return &nb
}
`, w, g.AdjCfg, g)
emitNodeStyleType_typical(w, g.AdjCfg, g)
}
// --- NodeBuilder and NodeAssembler --->
......
......@@ -67,10 +67,7 @@ func (g listGenerator) EmitNodeType(w io.Writer) {
}
func (g listGenerator) EmitNodeTypeAssertions(w io.Writer) {
doTemplate(`
var _ ipld.Node = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
var _ schema.TypedNode = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
`, w, g.AdjCfg, g)
emitNodeTypeAssertions_typical(w, g.AdjCfg, g)
}
func (g listGenerator) EmitNodeMethodLookupIndex(w io.Writer) {
......@@ -152,25 +149,11 @@ func (g listGenerator) EmitNodeMethodLength(w io.Writer) {
}
func (g listGenerator) EmitNodeMethodStyle(w io.Writer) {
// REVIEW: this appears to be standard even across kinds; can we extract it?
doTemplate(`
func ({{ .Type | TypeSymbol }}) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, g.AdjCfg, g)
emitNodeMethodStyle_typical(w, g.AdjCfg, g)
}
func (g listGenerator) EmitNodeStyleType(w io.Writer) {
// REVIEW: this appears to be standard even across kinds; can we extract it?
doTemplate(`
type _{{ .Type | TypeSymbol }}__Style struct{}
func (_{{ .Type | TypeSymbol }}__Style) NewBuilder() ipld.NodeBuilder {
var nb _{{ .Type | TypeSymbol }}__Builder
nb.Reset()
return &nb
}
`, w, g.AdjCfg, g)
emitNodeStyleType_typical(w, g.AdjCfg, g)
}
// --- NodeBuilder and NodeAssembler --->
......
......@@ -111,10 +111,7 @@ func (g mapGenerator) EmitNodeType(w io.Writer) {
}
func (g mapGenerator) EmitNodeTypeAssertions(w io.Writer) {
doTemplate(`
var _ ipld.Node = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
var _ schema.TypedNode = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
`, w, g.AdjCfg, g)
emitNodeTypeAssertions_typical(w, g.AdjCfg, g)
}
func (g mapGenerator) EmitNodeMethodLookupString(w io.Writer) {
......@@ -225,25 +222,11 @@ func (g mapGenerator) EmitNodeMethodLength(w io.Writer) {
}
func (g mapGenerator) EmitNodeMethodStyle(w io.Writer) {
// REVIEW: this appears to be standard even across kinds; can we extract it?
doTemplate(`
func ({{ .Type | TypeSymbol }}) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, g.AdjCfg, g)
emitNodeMethodStyle_typical(w, g.AdjCfg, g)
}
func (g mapGenerator) EmitNodeStyleType(w io.Writer) {
// REVIEW: this appears to be standard even across kinds; can we extract it?
doTemplate(`
type _{{ .Type | TypeSymbol }}__Style struct{}
func (_{{ .Type | TypeSymbol }}__Style) NewBuilder() ipld.NodeBuilder {
var nb _{{ .Type | TypeSymbol }}__Builder
nb.Reset()
return &nb
}
`, w, g.AdjCfg, g)
emitNodeStyleType_typical(w, g.AdjCfg, g)
}
// --- NodeBuilder and NodeAssembler --->
......
......@@ -17,26 +17,11 @@ type stringGenerator struct {
// --- native content and specializations --->
func (g stringGenerator) EmitNativeType(w io.Writer) {
// Using a struct with a single member is the same size in memory as a typedef,
// while also having the advantage of meaning we can block direct casting,
// which is desirable because the compiler then ensures our validate methods can't be evaded.
doTemplate(`
type _{{ .Type | TypeSymbol }} struct{ x string }
type {{ .Type | TypeSymbol }} = *_{{ .Type | TypeSymbol }}
`, w, g.AdjCfg, g)
emitNativeType_scalar(w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNativeAccessors(w io.Writer) {
// The node interface's `AsString` method is almost sufficient... but
// this method unboxes without needing to return an error that's statically impossible,
// which makes it easier to use in chaining.
doTemplate(`
func (n {{ .Type | TypeSymbol }}) String() string {
return n.x
}
`, w, g.AdjCfg, g)
emitNativeAccessors_scalar(w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNativeBuilder(w io.Writer) {
// Generate a single-step construction function -- this is easy to do for a scalar,
// and all representations of scalar kind can be expected to have a method like this.
......@@ -53,12 +38,7 @@ func (g stringGenerator) EmitNativeBuilder(w io.Writer) {
`, w, g.AdjCfg, g)
// And generate a publicly exported version of that single-step constructor, too.
// (Just don't expose the details about allocation, because you can't meaningfully use that from outside the package.)
doTemplate(`
func (_{{ .Type | TypeSymbol }}__Style) FromString(v string) ({{ .Type | TypeSymbol }}, error) {
n := _{{ .Type | TypeSymbol }}{v}
return &n, nil
}
`, w, g.AdjCfg, g)
emitNativeBuilder_scalar(w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNativeMaybe(w io.Writer) {
......@@ -94,38 +74,16 @@ func (g stringGenerator) EmitNodeType(w io.Writer) {
}
func (g stringGenerator) EmitNodeTypeAssertions(w io.Writer) {
doTemplate(`
var _ ipld.Node = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
var _ schema.TypedNode = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
`, w, g.AdjCfg, g)
emitNodeTypeAssertions_typical(w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNodeMethodAsString(w io.Writer) {
doTemplate(`
func (n {{ .Type | TypeSymbol }}) AsString() (string, error) {
return n.x, nil
}
`, w, g.AdjCfg, g)
emitNodeMethodAsKind_scalar(w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNodeMethodStyle(w io.Writer) {
doTemplate(`
func ({{ .Type | TypeSymbol }}) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, g.AdjCfg, g)
emitNodeMethodStyle_typical(w, g.AdjCfg, g)
}
func (g stringGenerator) EmitNodeStyleType(w io.Writer) {
doTemplate(`
type _{{ .Type | TypeSymbol }}__Style struct{}
func (_{{ .Type | TypeSymbol }}__Style) NewBuilder() ipld.NodeBuilder {
var nb _{{ .Type | TypeSymbol }}__Builder
nb.Reset()
return &nb
}
`, w, g.AdjCfg, g)
emitNodeStyleType_typical(w, g.AdjCfg, g)
}
// --- NodeBuilder and NodeAssembler --->
......
......@@ -85,10 +85,7 @@ func (g structGenerator) EmitNodeType(w io.Writer) {
}
func (g structGenerator) EmitNodeTypeAssertions(w io.Writer) {
doTemplate(`
var _ ipld.Node = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
var _ schema.TypedNode = ({{ .Type | TypeSymbol }})(&_{{ .Type | TypeSymbol }}{})
`, w, g.AdjCfg, g)
emitNodeTypeAssertions_typical(w, g.AdjCfg, g)
}
func (g structGenerator) EmitNodeMethodLookupString(w io.Writer) {
......@@ -194,25 +191,11 @@ func (g structGenerator) EmitNodeMethodLength(w io.Writer) {
}
func (g structGenerator) EmitNodeMethodStyle(w io.Writer) {
// REVIEW: this appears to be standard even across kinds; can we extract it?
doTemplate(`
func ({{ .Type | TypeSymbol }}) Style() ipld.NodeStyle {
return _{{ .Type | TypeSymbol }}__Style{}
}
`, w, g.AdjCfg, g)
emitNodeMethodStyle_typical(w, g.AdjCfg, g)
}
func (g structGenerator) EmitNodeStyleType(w io.Writer) {
// REVIEW: this appears to be standard even across kinds; can we extract it?
doTemplate(`
type _{{ .Type | TypeSymbol }}__Style struct{}
func (_{{ .Type | TypeSymbol }}__Style) NewBuilder() ipld.NodeBuilder {
var nb _{{ .Type | TypeSymbol }}__Builder
nb.Reset()
return &nb
}
`, w, g.AdjCfg, g)
emitNodeStyleType_typical(w, g.AdjCfg, g)
}
// --- NodeBuilder and NodeAssembler --->
......
......@@ -12,6 +12,9 @@ type IntTraits struct {
TypeSymbol string // see doc in kindTraitsGenerator
}
func (IntTraits) ReprKind() ipld.ReprKind {
return ipld.ReprKind_Int
}
func (g IntTraits) EmitNodeMethodReprKind(w io.Writer) {
doTemplate(`
func ({{ .TypeSymbol }}) ReprKind() ipld.ReprKind {
......
......@@ -12,6 +12,9 @@ type ListTraits struct {
TypeSymbol string // see doc in kindTraitsGenerator
}
func (ListTraits) ReprKind() ipld.ReprKind {
return ipld.ReprKind_List
}
func (g ListTraits) EmitNodeMethodReprKind(w io.Writer) {
doTemplate(`
func ({{ .TypeSymbol }}) ReprKind() ipld.ReprKind {
......
......@@ -12,6 +12,9 @@ type MapTraits struct {
TypeSymbol string // see doc in kindTraitsGenerator
}
func (MapTraits) ReprKind() ipld.ReprKind {
return ipld.ReprKind_Map
}
func (g MapTraits) EmitNodeMethodReprKind(w io.Writer) {
doTemplate(`
func ({{ .TypeSymbol }}) ReprKind() ipld.ReprKind {
......
......@@ -12,6 +12,9 @@ type StringTraits struct {
TypeSymbol string // see doc in kindTraitsGenerator
}
func (StringTraits) ReprKind() ipld.ReprKind {
return ipld.ReprKind_String
}
func (g StringTraits) EmitNodeMethodReprKind(w io.Writer) {
doTemplate(`
func ({{ .TypeSymbol }}) ReprKind() ipld.ReprKind {
......
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