From 122c533854c7fe1a9ceff1d144ec15cf51100135 Mon Sep 17 00:00:00 2001 From: Eric Myhre Date: Tue, 25 Jun 2019 23:03:47 +0200 Subject: [PATCH] Refactor of type/schema code. - `typed.Node` -> now lives in the `impl/typed` package, more like other nodes. - Most of the other essential parts of reasoning about types moved to `schema` package. ("typed.Type" seemed like a nasty stutter.) - `typed.Universe` renamed to `schema.TypeSystem`. - Current `Validate` method moved to `schema` package, but see new comments about potential future homes of that code, and its aspirational relationship to `typed.Node`. Conspicuously *not* yet refactored or moved in this comment: - The `typed/declaration` package -- though it will shortly be scrapped and later reappear as `schema/ast`. The dream is that it would be neatest of all if we could generate it by codegen; but we'll see. (This would seem to imply we'll have to make sufficient exported methods for creating the `schema.Type` values... while we also want to make those immutable. We'll... see.) - The `typed/gen` package is also untouched in this commit, but should similarly move shortly. The codegen really ought to be built against the `schema.Type` reified interfaces. Overall, this drops the sheer nesting depths of packages a fair bit, which seems likely to be a good smell. --- typed/node.go => impl/typed/typedNode.go | 14 +++++++++++--- typed/system/types.go => schema/type.go | 9 ++++----- {typed/system => schema}/typeMethods.go | 8 ++++---- typed/system/universe.go => schema/typesystem.go | 4 ++-- {typed/system => schema}/validate.go | 15 ++++++++++++--- {typed/system => schema}/validate_test.go | 4 ++-- 6 files changed, 35 insertions(+), 19 deletions(-) rename typed/node.go => impl/typed/typedNode.go (52%) rename typed/system/types.go => schema/type.go (95%) rename {typed/system => schema}/typeMethods.go (96%) rename typed/system/universe.go => schema/typesystem.go (91%) rename {typed/system => schema}/validate.go (81%) rename {typed/system => schema}/validate_test.go (86%) diff --git a/typed/node.go b/impl/typed/typedNode.go similarity index 52% rename from typed/node.go rename to impl/typed/typedNode.go index 97bbd34..bb0a10b 100644 --- a/typed/node.go +++ b/impl/typed/typedNode.go @@ -2,12 +2,12 @@ package typed import ( "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/typed/system" + "github.com/ipld/go-ipld-prime/schema" ) // typed.Node is a superset of the ipld.Node interface, and has additional behaviors. // -// A typed.Node can be inspected for its typesystem.Type and typesystem.Kind, +// A typed.Node can be inspected for its schema.Type and schema.Kind, // which conveys much more and richer information than the Data Model layer // ipld.ReprKind. // @@ -26,5 +26,13 @@ import ( type Node interface { ipld.Node - Type() typesystem.Type + Type() schema.Type } + +// unboxing is... ugh, we probably should codegen an unbox method per concrete type. +// (or, attach them to the non-pointer type, which would namespace in an alloc-free way, but i don't know if that's anything but confusing.) +// there are notes about this from way back at 2019.01; reread to see if any remain relevant and valid. +// main important point is: it's not gonna be casting. +// if casting was sufficient to unbox, it'd mean every method on the Node interface would be difficult to use as a field name on a struct type. undesirable. +// okay, or, alternative, we flip this to `superapi.Footype{}.Fields().FrobFieldName()`. that strikes me as unlikely to be pleasing, though. +// istm we can safely expect direct use of field names much, much more often that flipping back and forth to hypergeneric node; so we should optimize syntax for that accordingly. diff --git a/typed/system/types.go b/schema/type.go similarity index 95% rename from typed/system/types.go rename to schema/type.go index 8d1e8cf..853dfb0 100644 --- a/typed/system/types.go +++ b/schema/type.go @@ -1,11 +1,10 @@ -package typesystem +package schema import ( ipld "github.com/ipld/go-ipld-prime" - typedeclaration "github.com/ipld/go-ipld-prime/typed/declaration" ) -type TypeName = typedeclaration.TypeName +type TypeName string // = ast.TypeName // typesystem.Type is an union interface; each of the `Type*` concrete types // in this package are one of its members. @@ -45,7 +44,7 @@ type Type interface { _Type() // Returns a pointer to the typesystem.Universe this type is a member of. - Universe() *Universe + TypeSystem() *TypeSystem // Returns the string name of the Type. This name is unique within the // universe this type is a member of, *unless* this type is Anonymous, @@ -79,7 +78,7 @@ var ( type anyType struct { name TypeName - universe *Universe + universe *TypeSystem } type TypeBool struct { diff --git a/typed/system/typeMethods.go b/schema/typeMethods.go similarity index 96% rename from typed/system/typeMethods.go rename to schema/typeMethods.go index 8de6dd8..801c31b 100644 --- a/typed/system/typeMethods.go +++ b/schema/typeMethods.go @@ -1,4 +1,4 @@ -package typesystem +package schema import ( "github.com/ipld/go-ipld-prime" @@ -6,9 +6,9 @@ import ( /* cookie-cutter standard interface stuff */ -func (anyType) _Type() {} -func (t anyType) Universe() *Universe { return t.universe } -func (t anyType) Name() TypeName { return t.name } +func (anyType) _Type() {} +func (t anyType) TypeSystem() *TypeSystem { return t.universe } +func (t anyType) Name() TypeName { return t.name } func (TypeBool) ReprKind() ipld.ReprKind { return ipld.ReprKind_Bool diff --git a/typed/system/universe.go b/schema/typesystem.go similarity index 91% rename from typed/system/universe.go rename to schema/typesystem.go index 5334966..8e1420c 100644 --- a/typed/system/universe.go +++ b/schema/typesystem.go @@ -1,6 +1,6 @@ -package typesystem +package schema -type Universe struct { +type TypeSystem struct { // namedTypes is the set of all named types in this universe. // The map's key is the value's Name() property and must be unique. // diff --git a/typed/system/validate.go b/schema/validate.go similarity index 81% rename from typed/system/validate.go rename to schema/validate.go index a817464..4f92326 100644 --- a/typed/system/validate.go +++ b/schema/validate.go @@ -1,4 +1,4 @@ -package typesystem +package schema import ( "fmt" @@ -7,12 +7,21 @@ import ( "github.com/ipld/go-ipld-prime" ) -func Validate(ts Universe, t Type, node ipld.Node) []error { +// FUTURE: we also want something *almost* identical to this Validate method, +// but returning a `typed.Node` in the case of no error. +// (Such a method would go in the same package as `typed.Node`, presumably.) +// How do we avoid writing this method twice? +// Maybe both a Validate and Reify method belong in `typed` package, +// and Validate just returns less? +// No... Reify should probably short-circuit sooner? +// Unclear. Guess first step is that we need to decide the intended UX! + +func Validate(ts TypeSystem, t Type, node ipld.Node) []error { return validate(ts, t, node, "/") } // review: 'ts' param might not actually be necessary; everything relevant can be reached from t so far. -func validate(ts Universe, t Type, node ipld.Node, pth string) []error { +func validate(ts TypeSystem, t Type, node ipld.Node, pth string) []error { switch t2 := t.(type) { case TypeBool: if node.ReprKind() != ipld.ReprKind_Bool { diff --git a/typed/system/validate_test.go b/schema/validate_test.go similarity index 86% rename from typed/system/validate_test.go rename to schema/validate_test.go index c7572fb..654669e 100644 --- a/typed/system/validate_test.go +++ b/schema/validate_test.go @@ -1,4 +1,4 @@ -package typesystem +package schema import ( "testing" @@ -15,7 +15,7 @@ func TestSimpleTypes(t *testing.T) { anyType{name: "Foo"}, } Wish(t, - Validate(Universe{}, t1, n1), + Validate(TypeSystem{}, t1, n1), ShouldEqual, []error(nil)) }) } -- GitLab