Commit ecad4261 authored by Eric Myhre's avatar Eric Myhre

Finish ErrWrongKind; add typed.Node.Representation

typed.Node.Representation(), which returns another Node, should address
most of the infelicies we've found so far in trying to plan nice code
that works over the schema layer.

Also added in this comment: ipld.ReprKindSet, primarily for use in the
ErrWrongKind error.  It comes up often enough we might as well formalize
the thing.
parent 1a53233c
......@@ -15,20 +15,15 @@ type ErrWrongKind struct {
// "AsString".
MethodName string
// ApprorpriateKind is used to describe the Kind which the erroring method
// would make sense for.
// ApprorpriateKind describes which ReprKinds the erroring method would
// make sense for.
AppropriateKind ReprKindSet
// ActualKind describes the ReprKind of the node the method was called on.
//
// In the case of typed nodes, this will typically refer to the 'natural'
// data-model kind for such a type (e.g., structs will say 'map' here).
AppropriateKind ReprKind
ActualKind ReprKind // FIXME okay just no, this really needs to say what it knows.
// REVIEW this is almost certainly wrong. Maybe you need some short enums
// for things like "the kinds you can traverse by name" e.g. map+struct.
// And I'm really sparse for reasons not to put schema-level Kind in the root package.
// All the counter-arguments are similar to the ones about Path, and they
// just flat out lose when up against "errors matter".
ActualKind ReprKind
}
func (e ErrWrongKind) Error() string {
......
......@@ -24,9 +24,28 @@ import (
// components which are from different versions of a schema. Smooth migrations
// and zero-copy type-safe data sharing between them: We can accommodate that!
type Node interface {
// typed.Node acts just like a regular Node for almost all purposes;
// which ReprKind it acts as is determined by the TypeKind.
// (Note that the representation strategy of the type does *not* affect
// the ReprKind of typed.Node -- rather, the representation strategy
// affects the `.Representation().ReprKind()`.)
//
// For example: if the `.Type().Kind()` of this node is "struct",
// it will act like ReprKind() == "map"
// (even if Type().(Struct).ReprStrategy() is "tuple").
ipld.Node
// Type returns a reference to the reified schema.Type value.
Type() schema.Type
// Representation returns an ipld.Node which sees the data in this node
// in its representation form.
//
// For example: if the `.Type().Kind()` of this node is "struct",
// `.Representation().Kind()` may vary based on its representation strategy:
// if the representation strategy is "map", then it will be ReprKind=="map";
// if the streatgy is "tuple", then it will be ReprKind=="list".
Representation() ipld.Node
}
// unboxing is... ugh, we probably should codegen an unbox method per concrete type.
......
......@@ -48,3 +48,31 @@ func (k ReprKind) String() string {
panic("invalid enumeration value!")
}
}
// ReprKindSet is a type with a few enumerated consts that are commonly used
// (mostly, in error messages).
type ReprKindSet []ReprKind
var (
ReprKindSet_Recursive = ReprKindSet{ReprKind_Map, ReprKind_List}
ReprKindSet_Scalar = ReprKindSet{ReprKind_Null, ReprKind_Bool, ReprKind_Int, ReprKind_Float, ReprKind_String, ReprKind_Bytes, ReprKind_Link}
ReprKindSet_JustMap = ReprKindSet{ReprKind_Map}
ReprKindSet_JustList = ReprKindSet{ReprKind_List}
ReprKindSet_JustNull = ReprKindSet{ReprKind_Null}
ReprKindSet_JustBool = ReprKindSet{ReprKind_Bool}
ReprKindSet_JustInt = ReprKindSet{ReprKind_Int}
ReprKindSet_JustFloat = ReprKindSet{ReprKind_Float}
ReprKindSet_JustString = ReprKindSet{ReprKind_String}
ReprKindSet_JustBytes = ReprKindSet{ReprKind_Bytes}
ReprKindSet_JustLink = ReprKindSet{ReprKind_Link}
)
func (x ReprKindSet) String() string {
s := ""
for i := 0; i < len(x)-1; i++ {
s += x[i].String() + " or "
}
s += x[len(x)-1].String()
return s
}
......@@ -13,10 +13,12 @@ type generateKindString struct {
// FUTURE: perhaps both a global one (e.g. output package name) and a per-type one.
}
// FUTURE: quite a few of these "nope" methods can be reused widely.
func (gk generateKindString) EmitNodeMethodTraverseField(w io.Writer) {
doTemplate(`
func ({{ .Name }}) TraverseField(key string) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
return nil, ipld.ErrWrongKind{MethodName: "TraverseField", AppropriateKind: ipld.ReprKindSet_JustMap, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......@@ -24,7 +26,7 @@ func (gk generateKindString) EmitNodeMethodTraverseField(w io.Writer) {
func (gk generateKindString) EmitNodeMethodTraverseIndex(w io.Writer) {
doTemplate(`
func ({{ .Name }}) TraverseIndex(idx int) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
return nil, ipld.ErrWrongKind{MethodName: "TraverseIndex", AppropriateKind: ipld.ReprKindSet_JustList, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......@@ -32,7 +34,7 @@ func (gk generateKindString) EmitNodeMethodTraverseIndex(w io.Writer) {
func (gk generateKindString) EmitNodeMethodMapIterator(w io.Writer) {
doTemplate(`
func ({{ .Name }}) MapIterator() ipld.MapIterator {
return mapIteratorReject{ipld.ErrWrongKind{ /* todo more content */ }}
return mapIteratorReject{ipld.ErrWrongKind{MethodName: "MapIterator", AppropriateKind: ipld.ReprKindSet_JustMap, ActualKind: ipld.ReprKind_String}}
}
`, w, gk)
}
......@@ -40,7 +42,7 @@ func (gk generateKindString) EmitNodeMethodMapIterator(w io.Writer) {
func (gk generateKindString) EmitNodeMethodListIterator(w io.Writer) {
doTemplate(`
func ({{ .Name }}) ListIterator() ipld.ListIterator {
return listIteratorReject{ipld.ErrWrongKind{ /* todo more content */ }}
return listIteratorReject{ipld.ErrWrongKind{MethodName: "ListIterator", AppropriateKind: ipld.ReprKindSet_JustList, ActualKind: ipld.ReprKind_String}}
}
`, w, gk) // REVIEW: maybe that rejection thunk should be in main package? don't really want to flash it at folks though. very impl detail.
}
......@@ -64,7 +66,7 @@ func (gk generateKindString) EmitNodeMethodIsNull(w io.Writer) {
func (gk generateKindString) EmitNodeMethodAsBool(w io.Writer) {
doTemplate(`
func ({{ .Name }}) AsBool() (bool, error) {
return false, ipld.ErrWrongKind{ /* todo more content */ }
return false, ipld.ErrWrongKind{MethodName: "AsBool", AppropriateKind: ipld.ReprKindSet_JustBool, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......@@ -72,7 +74,7 @@ func (gk generateKindString) EmitNodeMethodAsBool(w io.Writer) {
func (gk generateKindString) EmitNodeMethodAsInt(w io.Writer) {
doTemplate(`
func ({{ .Name }}) AsInt() (int, error) {
return 0, ipld.ErrWrongKind{ /* todo more content */ }
return 0, ipld.ErrWrongKind{MethodName: "AsInt", AppropriateKind: ipld.ReprKindSet_JustInt, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......@@ -80,7 +82,7 @@ func (gk generateKindString) EmitNodeMethodAsInt(w io.Writer) {
func (gk generateKindString) EmitNodeMethodAsFloat(w io.Writer) {
doTemplate(`
func ({{ .Name }}) AsFloat() (float64, error) {
return 0, ipld.ErrWrongKind{ /* todo more content */ }
return 0, ipld.ErrWrongKind{MethodName: "AsFloat", AppropriateKind: ipld.ReprKindSet_JustFloat, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......@@ -96,7 +98,7 @@ func (gk generateKindString) EmitNodeMethodAsString(w io.Writer) {
func (gk generateKindString) EmitNodeMethodAsBytes(w io.Writer) {
doTemplate(`
func ({{ .Name }}) AsBytes() ([]byte, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
return nil, ipld.ErrWrongKind{MethodName: "AsBytes", AppropriateKind: ipld.ReprKindSet_JustBytes, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......@@ -104,7 +106,7 @@ func (gk generateKindString) EmitNodeMethodAsBytes(w io.Writer) {
func (gk generateKindString) EmitNodeMethodAsLink(w io.Writer) {
doTemplate(`
func ({{ .Name }}) AsLink() (ipld.Link, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
return nil, ipld.ErrWrongKind{MethodName: "AsLink", AppropriateKind: ipld.ReprKindSet_JustLink, ActualKind: ipld.ReprKind_String}
}
`, w, gk)
}
......
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