Commit ecb4744c authored by Eric Myhre's avatar Eric Myhre

Remainder of gen for kinded union representations.

The AssignNode method is now supplied; and the previous hacky shrug
regarding switch statements with no applicable cases also had to go.
(Turns out that the no-applicable-cases thing coincidentally worked
for the "embedall" internal implementation mode; but didn't fly for
the "interface" internal style, because that would end up with
variable declarations made but not referenced.  Harrumph.)
parent fcbb4d80
...@@ -79,7 +79,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodReprKind(w io.Writer) { ...@@ -79,7 +79,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodReprKind(w io.Writer) {
return {{ $member.RepresentationBehavior | KindSymbol }} return {{ $member.RepresentationBehavior | KindSymbol }}
{{- end}} {{- end}}
{{- else if (eq (.AdjCfg.UnionMemlayout .Type) "interface") }} {{- else if (eq (.AdjCfg.UnionMemlayout .Type) "interface") }}
switch n2 := n.x.(type) { switch n.x.(type) {
{{- range $i, $member := .Type.Members }} {{- range $i, $member := .Type.Members }}
case {{ $member | TypeSymbol }}: case {{ $member | TypeSymbol }}:
return {{ $member.RepresentationBehavior | KindSymbol }} return {{ $member.RepresentationBehavior | KindSymbol }}
...@@ -92,19 +92,11 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodReprKind(w io.Writer) { ...@@ -92,19 +92,11 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodReprKind(w io.Writer) {
`, w, g.AdjCfg, g) `, w, g.AdjCfg, g)
} }
// A bunch of these methods could be improved by doing a gen-time switch for whether any of the possible members are the relevant kind at all;
// currently in the cases where there's no relevant members, we generate switch blocks that are empty except for their default...
// which works, but is arguably a little strange.
// I haven't checked if this dummy switch has any actual performance implications:
// I haven't tested if this produces unconditional assembly,
// nor if it successfully removes the access of the tag,
// though one might imagine a sufficiently clever compiler ought to do both of those things.
// Regardless, the gsloc is reducable. (Slightly. There are also bigger gains to be made elsewhere, I'm sure.)
func kindedUnionNodeMethodTemplateMunge( func kindedUnionNodeMethodTemplateMunge(
methodName string, // for error messages methodName string, // for error messages
methodSig string, // output literally methodSig string, // output literally
condClause string, // template condition for the member this should match on someSwitchClause string, // template condition for if *any* switch clause should be present
condClause string, // template condition for the member this should match on when in the range
retClause string, // clause returning the thing (how to delegate methodsig, generally) retClause string, // clause returning the thing (how to delegate methodsig, generally)
appropriateKind string, // for error messages appropriateKind string, // for error messages
nopeSentinel string, // for error return paths; generally the zero value for the first return type. nopeSentinel string, // for error return paths; generally the zero value for the first return type.
...@@ -116,12 +108,18 @@ func kindedUnionNodeMethodTemplateMunge( ...@@ -116,12 +108,18 @@ func kindedUnionNodeMethodTemplateMunge(
// //
// This error text doesn't tell us what the member kind is. This might read weirdly. // This error text doesn't tell us what the member kind is. This might read weirdly.
// It's possible we could try to cram a description of the inhabitant into the "TypeName" since it's stringy; but unclear if that's a good idea either. // It's possible we could try to cram a description of the inhabitant into the "TypeName" since it's stringy; but unclear if that's a good idea either.
// These template concatenations have evolved into a mess very quickly. This entire thing should be replaced.
// String concatenations of template clauses is an atrociously unhygenic way to compose things;
// it looked like we could limp by with it for a while, but it's gotten messier faster than expected.
errorClause := `return ` + nopeSentinel errorClause := `return ` + nopeSentinel
if !nopeSentinelOnly { if !nopeSentinelOnly {
errorClause += `, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .Type.Name }}.Repr", MethodName: "` + methodName + `", AppropriateKind: ` + appropriateKind + `, ActualKind: n.ReprKind()}` errorClause += `, ipld.ErrWrongKind{TypeName: "{{ .PkgName }}.{{ .Type.Name }}.Repr", MethodName: "` + methodName + `", AppropriateKind: ` + appropriateKind + `, ActualKind: n.ReprKind()}`
} }
return ` return `
func (n *_{{ .Type | TypeSymbol }}__Repr) ` + methodSig + ` { func (n *_{{ .Type | TypeSymbol }}__Repr) ` + methodSig + ` {
` + someSwitchClause + `
{{- if (eq (.AdjCfg.UnionMemlayout .Type) "embedAll") }} {{- if (eq (.AdjCfg.UnionMemlayout .Type) "embedAll") }}
switch n.tag { switch n.tag {
{{- range $i, $member := .Type.Members }} {{- range $i, $member := .Type.Members }}
...@@ -140,8 +138,11 @@ func kindedUnionNodeMethodTemplateMunge( ...@@ -140,8 +138,11 @@ func kindedUnionNodeMethodTemplateMunge(
{{- end}} {{- end}}
{{- end}} {{- end}}
default: default:
{{- end}}
` + errorClause + ` ` + errorClause + `
` + someSwitchClause + `
} }
{{- end}}
} }
` `
} }
...@@ -150,6 +151,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupByString(w io.Writer) ...@@ -150,6 +151,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupByString(w io.Writer)
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`LookupByString`, `LookupByString`,
`LookupByString(key string) (ipld.Node, error)`, `LookupByString(key string) (ipld.Node, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "map") }}`,
`{{- if eq $member.RepresentationBehavior.String "map" }}`, `{{- if eq $member.RepresentationBehavior.String "map" }}`,
`.LookupByString(key)`, `.LookupByString(key)`,
`ipld.ReprKindSet_JustMap`, `ipld.ReprKindSet_JustMap`,
...@@ -162,6 +164,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupByIndex(w io.Writer) { ...@@ -162,6 +164,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupByIndex(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`LookupByIndex`, `LookupByIndex`,
`LookupByIndex(idx int) (ipld.Node, error)`, `LookupByIndex(idx int) (ipld.Node, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "list") }}`,
`{{- if eq $member.RepresentationBehavior.String "list" }}`, `{{- if eq $member.RepresentationBehavior.String "list" }}`,
`.LookupByIndex(idx)`, `.LookupByIndex(idx)`,
`ipld.ReprKindSet_JustList`, `ipld.ReprKindSet_JustList`,
...@@ -174,6 +177,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupByNode(w io.Writer) { ...@@ -174,6 +177,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupByNode(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`LookupByNode`, `LookupByNode`,
`LookupByNode(key ipld.Node) (ipld.Node, error)`, `LookupByNode(key ipld.Node) (ipld.Node, error)`,
`{{- if or (.Type.RepresentationStrategy.GetMember (Kind "map")) (.Type.RepresentationStrategy.GetMember (Kind "list")) }}`,
`{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`, `{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`,
`.LookupByNode(key)`, `.LookupByNode(key)`,
`ipld.ReprKindSet_Recursive`, `ipld.ReprKindSet_Recursive`,
...@@ -186,6 +190,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupBySegment(w io.Writer) ...@@ -186,6 +190,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLookupBySegment(w io.Writer)
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`LookupBySegment`, `LookupBySegment`,
`LookupBySegment(seg ipld.PathSegment) (ipld.Node, error)`, `LookupBySegment(seg ipld.PathSegment) (ipld.Node, error)`,
`{{- if or (.Type.RepresentationStrategy.GetMember (Kind "map")) (.Type.RepresentationStrategy.GetMember (Kind "list")) }}`,
`{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`, `{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`,
`.LookupBySegment(seg)`, `.LookupBySegment(seg)`,
`ipld.ReprKindSet_Recursive`, `ipld.ReprKindSet_Recursive`,
...@@ -198,6 +203,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodMapIterator(w io.Writer) { ...@@ -198,6 +203,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodMapIterator(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`MapIterator`, `MapIterator`,
`MapIterator() ipld.MapIterator`, `MapIterator() ipld.MapIterator`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "map") }}`,
`{{- if eq $member.RepresentationBehavior.String "map" }}`, `{{- if eq $member.RepresentationBehavior.String "map" }}`,
`.MapIterator()`, `.MapIterator()`,
`ipld.ReprKindSet_JustMap`, `ipld.ReprKindSet_JustMap`,
...@@ -210,6 +216,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodListIterator(w io.Writer) { ...@@ -210,6 +216,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodListIterator(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`ListIterator`, `ListIterator`,
`ListIterator() ipld.ListIterator`, `ListIterator() ipld.ListIterator`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "list") }}`,
`{{- if eq $member.RepresentationBehavior.String "list" }}`, `{{- if eq $member.RepresentationBehavior.String "list" }}`,
`.ListIterator()`, `.ListIterator()`,
`ipld.ReprKindSet_JustList`, `ipld.ReprKindSet_JustList`,
...@@ -222,6 +229,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLength(w io.Writer) { ...@@ -222,6 +229,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodLength(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`Length`, `Length`,
`Length() int`, `Length() int`,
`{{- if or (.Type.RepresentationStrategy.GetMember (Kind "map")) (.Type.RepresentationStrategy.GetMember (Kind "list")) }}`,
`{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`, `{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`,
`.Length()`, `.Length()`,
`ipld.ReprKindSet_Recursive`, `ipld.ReprKindSet_Recursive`,
...@@ -250,6 +258,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsBool(w io.Writer) { ...@@ -250,6 +258,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsBool(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`AsBool`, `AsBool`,
`AsBool() (bool, error)`, `AsBool() (bool, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "bool") }}`,
`{{- if eq $member.RepresentationBehavior.String "bool" }}`, `{{- if eq $member.RepresentationBehavior.String "bool" }}`,
`.AsBool()`, `.AsBool()`,
`ipld.ReprKindSet_JustBool`, `ipld.ReprKindSet_JustBool`,
...@@ -262,6 +271,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsInt(w io.Writer) { ...@@ -262,6 +271,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsInt(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`AsInt`, `AsInt`,
`AsInt() (int, error)`, `AsInt() (int, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "int") }}`,
`{{- if eq $member.RepresentationBehavior.String "int" }}`, `{{- if eq $member.RepresentationBehavior.String "int" }}`,
`.AsInt()`, `.AsInt()`,
`ipld.ReprKindSet_JustInt`, `ipld.ReprKindSet_JustInt`,
...@@ -274,6 +284,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsFloat(w io.Writer) { ...@@ -274,6 +284,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsFloat(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`AsFloat`, `AsFloat`,
`AsFloat() (float64, error)`, `AsFloat() (float64, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "float") }}`,
`{{- if eq $member.RepresentationBehavior.String "float" }}`, `{{- if eq $member.RepresentationBehavior.String "float" }}`,
`.AsFloat()`, `.AsFloat()`,
`ipld.ReprKindSet_JustFloat`, `ipld.ReprKindSet_JustFloat`,
...@@ -286,6 +297,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsString(w io.Writer) { ...@@ -286,6 +297,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsString(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`AsString`, `AsString`,
`AsString() (string, error)`, `AsString() (string, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "string") }}`,
`{{- if eq $member.RepresentationBehavior.String "string" }}`, `{{- if eq $member.RepresentationBehavior.String "string" }}`,
`.AsString()`, `.AsString()`,
`ipld.ReprKindSet_JustString`, `ipld.ReprKindSet_JustString`,
...@@ -298,6 +310,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsBytes(w io.Writer) { ...@@ -298,6 +310,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsBytes(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`AsBytes`, `AsBytes`,
`AsBytes() ([]byte, error)`, `AsBytes() ([]byte, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "bytes") }}`,
`{{- if eq $member.RepresentationBehavior.String "bytes" }}`, `{{- if eq $member.RepresentationBehavior.String "bytes" }}`,
`.AsBytes()`, `.AsBytes()`,
`ipld.ReprKindSet_JustBytes`, `ipld.ReprKindSet_JustBytes`,
...@@ -310,6 +323,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsLink(w io.Writer) { ...@@ -310,6 +323,7 @@ func (g unionReprKindedReprGenerator) EmitNodeMethodAsLink(w io.Writer) {
doTemplate(kindedUnionNodeMethodTemplateMunge( doTemplate(kindedUnionNodeMethodTemplateMunge(
`AsLink`, `AsLink`,
`AsLink() (ipld.Link, error)`, `AsLink() (ipld.Link, error)`,
`{{- if .Type.RepresentationStrategy.GetMember (Kind "link") }}`,
`{{- if eq $member.RepresentationBehavior.String "link" }}`, `{{- if eq $member.RepresentationBehavior.String "link" }}`,
`.AsLink()`, `.AsLink()`,
`ipld.ReprKindSet_JustLink`, `ipld.ReprKindSet_JustLink`,
...@@ -528,12 +542,95 @@ func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerMethodAssignLink(w ...@@ -528,12 +542,95 @@ func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerMethodAssignLink(w
), w, g.AdjCfg, g) ), w, g.AdjCfg, g)
} }
func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.Writer) { func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.Writer) {
// TODO this is too wild for me at the moment, come back to it shortly // This is a very mundane AssignNode: it just calls out to the other methods on this type.
// it's basically got some of the body of kindedUnionNodeAssemblerMethodTemplateMunge, but repeated many more times. // However, even that is a little more exciting than usual: because we can't *necessarily* reject any kind of arg,
// it also needs to handle nulls gingerly. // we have the whole barrage of switch cases here. We then leave any particular rejections to those methods.
// and also handle pumping the full copy in the case of lists or maps. // Several cases could be statically replaced with errors and it would be an improvement.
//
// this is gonna have a fun ErrWrongKind value too -- we might actually have to make a non-static set of acceptable kinds :D that's a first. // Errors are problematic again, same as is noted in kindedUnionNodeAssemblerMethodTemplateMunge.
// We also end up returning errors with other method names due to how we delegate; unfortunate.
doTemplate(`
func (na *_{{ .Type | TypeSymbol }}__ReprAssembler) AssignNode(v ipld.Node) error {
if v.IsNull() {
return na.AssignNull()
}
if v2, ok := v.(*_{{ .Type | TypeSymbol }}); ok {
switch *na.m {
case schema.Maybe_Value, schema.Maybe_Null:
panic("invalid state: cannot assign into assembler that's already finished")
case midvalue:
panic("invalid state: cannot assign null into an assembler that's already begun working on recursive structures!")
}
{{- if .Type | MaybeUsesPtr }}
if na.w == nil {
na.w = v2
*na.m = schema.Maybe_Value
return nil
}
{{- end}}
*na.w = *v2
*na.m = schema.Maybe_Value
return nil
}
switch v.ReprKind() {
case ipld.ReprKind_Bool:
v2, _ := v.AsBool()
return na.AssignBool(v2)
case ipld.ReprKind_Int:
v2, _ := v.AsInt()
return na.AssignInt(v2)
case ipld.ReprKind_Float:
v2, _ := v.AsFloat()
return na.AssignFloat(v2)
case ipld.ReprKind_String:
v2, _ := v.AsString()
return na.AssignString(v2)
case ipld.ReprKind_Bytes:
v2, _ := v.AsBytes()
return na.AssignBytes(v2)
case ipld.ReprKind_Map:
na, err := na.BeginMap(v.Length())
if err != nil {
return err
}
itr := v.MapIterator()
for !itr.Done() {
k, v, err := itr.Next()
if err != nil {
return err
}
if err := na.AssembleKey().AssignNode(k); err != nil {
return err
}
if err := na.AssembleValue().AssignNode(v); err != nil {
return err
}
}
return na.Finish()
case ipld.ReprKind_List:
na, err := na.BeginList(v.Length())
if err != nil {
return err
}
itr := v.ListIterator()
for !itr.Done() {
_, v, err := itr.Next()
if err != nil {
return err
}
if err := na.AssembleValue().AssignNode(v); err != nil {
return err
}
}
return na.Finish()
case ipld.ReprKind_Link:
v2, _ := v.AsLink()
return na.AssignLink(v2)
default:
panic("unreachable")
}
}
`, w, g.AdjCfg, g)
} }
func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerMethodPrototype(w io.Writer) { func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerMethodPrototype(w io.Writer) {
doTemplate(` doTemplate(`
......
...@@ -54,6 +54,30 @@ func doTemplate(tmplstr string, w io.Writer, adjCfg *AdjunctCfg, data interface{ ...@@ -54,6 +54,30 @@ func doTemplate(tmplstr string, w io.Writer, adjCfg *AdjunctCfg, data interface{
panic("invalid enumeration value!") panic("invalid enumeration value!")
} }
}, },
"Kind": func(s string) ipld.ReprKind {
switch s {
case "map":
return ipld.ReprKind_Map
case "list":
return ipld.ReprKind_List
case "null":
return ipld.ReprKind_Null
case "bool":
return ipld.ReprKind_Bool
case "int":
return ipld.ReprKind_Int
case "float":
return ipld.ReprKind_Float
case "string":
return ipld.ReprKind_String
case "bytes":
return ipld.ReprKind_Bytes
case "link":
return ipld.ReprKind_Link
default:
panic("invalid enumeration value!")
}
},
"KindSymbol": func(k ipld.ReprKind) string { "KindSymbol": func(k ipld.ReprKind) string {
switch k { switch k {
case ipld.ReprKind_Map: case ipld.ReprKind_Map:
......
...@@ -148,6 +148,12 @@ func (r UnionRepresentation_Keyed) GetDiscriminant(t Type) string { ...@@ -148,6 +148,12 @@ func (r UnionRepresentation_Keyed) GetDiscriminant(t Type) string {
panic("that type isn't a member of this union") panic("that type isn't a member of this union")
} }
// GetMember returns type info for the member matching the kind argument,
// or may return nil if that kind is not mapped to a member of this union.
func (r UnionRepresentation_Kinded) GetMember(k ipld.ReprKind) TypeName {
return r.table[k]
}
// Fields returns a slice of descriptions of the object's fields. // Fields returns a slice of descriptions of the object's fields.
func (t TypeStruct) Fields() []StructField { func (t TypeStruct) Fields() []StructField {
a := make([]StructField, len(t.fields)) a := make([]StructField, len(t.fields))
......
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