Commit f2d59579 authored by Eric Myhre's avatar Eric Myhre

Merge branch 'schema-work'

parents 4169feeb 52033884
......@@ -4,6 +4,19 @@ import (
ipld "github.com/ipld/go-ipld-prime"
)
// Interesting jibblybit: docs actually shouldn't be part of the schema.
// Do the affect the cardinality of any of the members? Change any behavior? No.
// Therefore I shouldn't want them to change the CID of the schema as a whole.
//
// Now, obviously this is in dispute with what I want for the AST.
// What shall we do about this?
//
// It's exercise for two schemas applying to the same data, I guess.
// Hopefully we can get it to do something sane when it comes to codegen:
// having double the code for this would be undesirable.
// (I think this is probably a gimme, though. We'll just use a generic
// typed.Node wrapper (with limited view) around the even-more-typed codegen types.)
type TypeName string
// typedeclaration.Type is a union interface; each of the `Type*` concrete types
......
package typegen
import (
"fmt"
"io"
)
// you'll find a file in this package per kind
// (schema level kind, not data model level reprkind)...
// sparse cross-product with their representation strategy (more or less)
// (it's more... idunnoyet. hopefully we have implstrats and reprstrats,
// and those combine over an interface so it's not a triple cross product...
// and hopefully that interface is nodebuilder,
// because I dunno why it wouldn't be unless we goof on perf somehow).
// typeGenerator declares a standard names for a bunch of methods for generating
// code for our schema types. There's still numerous places where other casts
// to more specific interfaces will be required (so, technically, it's not a
// very powerful interface; it's not so much that the abstractions leak as that
// the floodgates are outright open), but this at least forces consistency onto
// the parts where we can.
//
// All Emit{foo} methods should emit one trailing and one leading linebreak, or,
// nothing (e.g. string kinds don't need to produce a dummy map iterator, so
// such a method can just emit nothing, and the extra spacing between sections
// shouldn't accumulate).
//
// None of these methods return error values because we panic in this package.
//
type typeGenerator interface {
// wip note: hopefully imports are a constant. if not, we'll have to curry something with the writer.
// -- the typed.Node.Type method and vars -->
// TODO
// (and last -- needs whole `typed/system` package)
// -- all node methods -->
EmitNodeType(io.Writer)
EmitNodeMethodReprKind(io.Writer)
EmitNodeMethodTraverseField(io.Writer)
EmitNodeMethodTraverseIndex(io.Writer)
EmitNodeMethodMapIterator(io.Writer)
EmitNodeMethodListIterator(io.Writer)
EmitNodeMethodLength(io.Writer)
EmitNodeMethodIsNull(io.Writer)
EmitNodeMethodAsBool(io.Writer)
EmitNodeMethodAsInt(io.Writer)
EmitNodeMethodAsFloat(io.Writer)
EmitNodeMethodAsString(io.Writer)
EmitNodeMethodAsBytes(io.Writer)
EmitNodeMethodAsLink(io.Writer)
EmitNodeMethodNodeBuilder(io.Writer)
// TODO also iterators (return blanks for non-{map,list,struct,enum})
// -- all nodebuilder methods -->
// TODO
}
func emitFileHeader(w io.Writer) {
fmt.Fprintf(w, "package whee\n\n")
fmt.Fprintf(w, "import (\n")
fmt.Fprintf(w, "\tipld \"github.com/ipld/go-ipld-prime\"\n")
fmt.Fprintf(w, ")\n")
}
// enums will have special methods
// maps will have special methods (namely, well typed getters
package typegen
import (
"io"
"text/template"
declaration "github.com/ipld/go-ipld-prime/typed/declaration"
wish "github.com/warpfork/go-wish"
)
type generateKindString struct {
Name declaration.TypeName
Type declaration.Type
}
func (gk generateKindString) EmitNodeMethodTraverseField(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) TraverseField(key string) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodTraverseIndex(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) TraverseIndex(idx int) (ipld.Node, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodMapIterator(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) MapIterator() ipld.MapIterator {
return mapIteratorReject{ipld.ErrWrongKind{ /* todo more content */ }}
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodListIterator(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) ListIterator() ipld.ListIterator {
return listIteratorReject{ipld.ErrWrongKind{ /* todo more content */ }}
}
`))).Execute(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.
}
func (gk generateKindString) EmitNodeMethodLength(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) Length() int {
return -1
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodIsNull(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) IsNull() bool {
return false
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodAsBool(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) AsBool() (bool, error) {
return false, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodAsInt(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) AsInt() (int, error) {
return 0, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodAsFloat(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) AsFloat() (float64, error) {
return 0, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodAsString(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func (x {{ .Name }}) AsString() (string, error) {
return x.x, nil
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodAsBytes(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) AsBytes() ([]byte, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodAsLink(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) AsLink() (ipld.Link, error) {
return nil, ipld.ErrWrongKind{ /* todo more content */ }
}
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodNodeBuilder(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) NodeBuilder() ipld.NodeBuilder {
return {{ .Name }}__NodeBuilder{}
}
`))).Execute(w, gk)
}
package typegen
import (
"io"
"text/template"
wish "github.com/warpfork/go-wish"
)
func (gk generateKindString) EmitNodeType(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
var _ ipld.Node = {{ .Name }}{}
type {{ .Name }} struct { x string }
`))).Execute(w, gk)
}
func (gk generateKindString) EmitNodeMethodReprKind(w io.Writer) {
template.Must(template.New("").Parse("\n"+wish.Dedent(`
func ({{ .Name }}) ReprKind() ipld.ReprKind {
return ipld.ReprKind_String
}
`))).Execute(w, gk)
}
package typegen
import (
"io"
"os"
"testing"
declaration "github.com/ipld/go-ipld-prime/typed/declaration"
)
func TestNuevo(t *testing.T) {
os.Mkdir("test", 0755)
openOrPanic := func(filename string) *os.File {
y, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
return y
}
f := openOrPanic("test/neu.go")
emitFileHeader(f)
emitType := func(tg typeGenerator, w io.Writer) {
tg.EmitNodeType(w)
tg.EmitNodeMethodReprKind(w)
tg.EmitNodeMethodTraverseField(w)
tg.EmitNodeMethodTraverseIndex(w)
tg.EmitNodeMethodMapIterator(w)
tg.EmitNodeMethodListIterator(w)
tg.EmitNodeMethodLength(w)
tg.EmitNodeMethodIsNull(w)
tg.EmitNodeMethodAsBool(w)
tg.EmitNodeMethodAsInt(w)
tg.EmitNodeMethodAsFloat(w)
tg.EmitNodeMethodAsString(w)
tg.EmitNodeMethodAsBytes(w)
tg.EmitNodeMethodAsLink(w)
tg.EmitNodeMethodNodeBuilder(w)
}
emitType(generateKindString{"Strang", declaration.TypeString{}}, f)
}
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