Add types.TypeRef

We want to explore encoding type information about Noms data in
the Noms database. So, we need some way to describe types. This
takes the shortest path to making a Noms type called "TypeRef" that
is a peer of Set, Map et al and can describe all the types we currently
use.
This commit is contained in:
Chris Masone
2015-09-01 12:08:37 -07:00
parent aa474edbf3
commit 63c956a5c5
33 changed files with 1684 additions and 464 deletions

View File

@@ -7,18 +7,31 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __mainPackageInFile_types_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"Pitch": __typeRefOfPitch(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// ListOfMapOfStringToValue
type ListOfMapOfStringToValue struct {
l types.List
}
type ListOfMapOfStringToValueDef []MapOfStringToValueDef
func NewListOfMapOfStringToValue() ListOfMapOfStringToValue {
return ListOfMapOfStringToValue{types.NewList()}
}
type ListOfMapOfStringToValueDef []MapOfStringToValueDef
func (def ListOfMapOfStringToValueDef) New() ListOfMapOfStringToValue {
l := make([]types.Value, len(def))
for i, d := range def {
@@ -27,11 +40,6 @@ func (def ListOfMapOfStringToValueDef) New() ListOfMapOfStringToValue {
return ListOfMapOfStringToValue{types.NewList(l...)}
}
func ListOfMapOfStringToValueFromVal(val types.Value) ListOfMapOfStringToValue {
// TODO: Validate here
return ListOfMapOfStringToValue{val.(types.List)}
}
func (self ListOfMapOfStringToValue) Def() ListOfMapOfStringToValueDef {
l := make([]MapOfStringToValueDef, self.Len())
for i := uint64(0); i < self.Len(); i++ {
@@ -40,6 +48,11 @@ func (self ListOfMapOfStringToValue) Def() ListOfMapOfStringToValueDef {
return l
}
func ListOfMapOfStringToValueFromVal(val types.Value) ListOfMapOfStringToValue {
// TODO: Validate here
return ListOfMapOfStringToValue{val.(types.List)}
}
func (self ListOfMapOfStringToValue) NomsValue() types.Value {
return self.l
}
@@ -130,12 +143,12 @@ type MapOfStringToValue struct {
m types.Map
}
type MapOfStringToValueDef map[string]types.Value
func NewMapOfStringToValue() MapOfStringToValue {
return MapOfStringToValue{types.NewMap()}
}
type MapOfStringToValueDef map[string]types.Value
func (def MapOfStringToValueDef) New() MapOfStringToValue {
kv := make([]types.Value, 0, len(def)*2)
for k, v := range def {
@@ -230,12 +243,12 @@ type MapOfStringToListOfPitch struct {
m types.Map
}
type MapOfStringToListOfPitchDef map[string]ListOfPitchDef
func NewMapOfStringToListOfPitch() MapOfStringToListOfPitch {
return MapOfStringToListOfPitch{types.NewMap()}
}
type MapOfStringToListOfPitchDef map[string]ListOfPitchDef
func (def MapOfStringToListOfPitchDef) New() MapOfStringToListOfPitch {
kv := make([]types.Value, 0, len(def)*2)
for k, v := range def {
@@ -330,12 +343,12 @@ type ListOfPitch struct {
l types.List
}
type ListOfPitchDef []PitchDef
func NewListOfPitch() ListOfPitch {
return ListOfPitch{types.NewList()}
}
type ListOfPitchDef []PitchDef
func (def ListOfPitchDef) New() ListOfPitch {
l := make([]types.Value, len(def))
for i, d := range def {
@@ -344,11 +357,6 @@ func (def ListOfPitchDef) New() ListOfPitch {
return ListOfPitch{types.NewList(l...)}
}
func ListOfPitchFromVal(val types.Value) ListOfPitch {
// TODO: Validate here
return ListOfPitch{val.(types.List)}
}
func (self ListOfPitch) Def() ListOfPitchDef {
l := make([]PitchDef, self.Len())
for i := uint64(0); i < self.Len(); i++ {
@@ -357,6 +365,11 @@ func (self ListOfPitch) Def() ListOfPitchDef {
return l
}
func ListOfPitchFromVal(val types.Value) ListOfPitch {
// TODO: Validate here
return ListOfPitch{val.(types.List)}
}
func (self ListOfPitch) NomsValue() types.Value {
return self.l
}
@@ -443,11 +456,6 @@ func (l ListOfPitch) Filter(cb ListOfPitchFilterCallback) ListOfPitch {
// Pitch
type PitchDef struct {
X float64
Z float64
}
type Pitch struct {
m types.Map
}
@@ -455,15 +463,22 @@ type Pitch struct {
func NewPitch() Pitch {
return Pitch{types.NewMap(
types.NewString("$name"), types.NewString("Pitch"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("Pitch"), __mainPackageInFile_types_Ref()),
types.NewString("X"), types.Float64(0),
types.NewString("Z"), types.Float64(0),
)}
}
type PitchDef struct {
X float64
Z float64
}
func (def PitchDef) New() Pitch {
return Pitch{
types.NewMap(
types.NewString("$name"), types.NewString("Pitch"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("Pitch"), __mainPackageInFile_types_Ref()),
types.NewString("X"), types.Float64(def.X),
types.NewString("Z"), types.Float64(def.Z),
)}
@@ -476,6 +491,17 @@ func (self Pitch) Def() PitchDef {
}
}
// Creates and returns a Noms Value that describes Pitch.
func __typeRefOfPitch() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("Pitch"),
types.NewList(
types.NewString("X"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("Z"), types.MakePrimitiveTypeRef(types.Float64Kind),
),
nil)
}
func PitchFromVal(val types.Value) Pitch {
// TODO: Validate here
return Pitch{val.(types.Map)}
@@ -493,6 +519,10 @@ func (self Pitch) Ref() ref.Ref {
return self.m.Ref()
}
func (self Pitch) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self Pitch) X() float64 {
return float64(self.m.Get(types.NewString("X")).(types.Float64))
}
@@ -515,12 +545,12 @@ type MapOfStringToString struct {
m types.Map
}
type MapOfStringToStringDef map[string]string
func NewMapOfStringToString() MapOfStringToString {
return MapOfStringToString{types.NewMap()}
}
type MapOfStringToStringDef map[string]string
func (def MapOfStringToStringDef) New() MapOfStringToString {
kv := make([]types.Value, 0, len(def)*2)
for k, v := range def {

View File

@@ -93,6 +93,10 @@ func jsonDecodeTaggedValue(m map[string]interface{}) interface{} {
if v, ok := v.([]interface{}); ok {
return jsonDecodeSet(v)
}
case "type":
if v, ok := v.(map[string]interface{}); ok {
return jsonDecodeTypeRef(v)
}
}
break
}
@@ -168,3 +172,22 @@ func jsonDecodeMap(input []interface{}) Map {
func jsonDecodeSet(input []interface{}) Set {
return jsonDecodeList(input)
}
func jsonDecodeTypeRef(input map[string]interface{}) TypeRef {
var ok bool
name, ok := input["name"].(string)
d.Exp.True(ok, "Name field of type must be string, not %+v", input["name"])
kind, ok := jsonDecodeValue(input["kind"]).(uint8)
d.Exp.True(ok, "Kind field of type must be uint8, not %+v", input["kind"])
pkgRef := ref.Ref{}
if input["pkgRef"] != nil {
pkgRef, ok = jsonDecodeValue(input["pkgRef"]).(ref.Ref)
d.Exp.True(ok, "If present, pkgRef field of type must be ref.Ref, not %+v", input["pkgRef"])
}
var desc interface{}
if input["desc"] != nil {
desc = jsonDecodeValue(input["desc"])
}
return TypeRef{PkgRef: pkgRef, Name: name, Kind: kind, Desc: desc}
}

View File

@@ -1,6 +1,7 @@
package enc
import (
"fmt"
"strings"
"testing"
@@ -77,6 +78,16 @@ func TestJSONDecode(t *testing.T) {
testDecode(`j {"set":[false,{"int32":42},"hotdog",{"ref":"sha1-58bdf8e374b39f9b1e8a64784cf5c09601f4b7ea"},{"ref":"sha1-dca2a4be23d4455487bb588c6a0ab1b9ee07757e"}]}
`, SetFromItems(false, int32(42), "hotdog", emptyListRef, emptyMapRef))
// TypeRefs
testDecode(`j {"type":{"kind":{"uint8":0},"name":""}}
`, TypeRef{Kind: 0})
ref1 := ref.New(ref.Sha1Digest{0xde, 0xad, 0xbe, 0xef})
ref2 := ref.New(ref.Sha1Digest{0xbe, 0xef, 0xca, 0xfe})
testDecode(fmt.Sprintf(`j {"type":{"desc":{"list":[{"ref":"%s"},{"ref":"%s"}]},"kind":{"uint8":15},"name":""}}
`, ref1, ref2), TypeRef{ref.Ref{}, "", 15, []interface{}{ref1, ref2}})
testDecode(`j {"type":{"desc":{"list":["f","g"]},"kind":{"uint8":18},"name":"enum"}}
`, TypeRef{ref.Ref{}, "enum", 18, []interface{}{"f", "g"}})
// Blob (compound)
// echo -n 'b Hello' | sha1sum
blr := ref.Parse("sha1-c35018551e725bd2ab45166b69d15fda00b161c1")

View File

@@ -41,6 +41,13 @@ type Map []interface{}
type Set []interface{}
type TypeRef struct {
PkgRef ref.Ref
Name string
Kind uint8
Desc interface{}
}
func jsonEncode(dst io.Writer, v interface{}) {
var j interface{}
j = getJSON(v)
@@ -117,6 +124,8 @@ func getJSONPrimitive(v interface{}) interface{} {
return map[string]interface{}{
"uint64": uint64(v),
}
case TypeRef:
return getJSONTypeRef(v)
default:
d.Exp.Fail(fmt.Sprintf("Unexpected type: %T, %+v", v, v))
}
@@ -165,6 +174,20 @@ func getJSONSet(s Set) interface{} {
return getJSONIterable("set", s)
}
func getJSONTypeRef(t TypeRef) interface{} {
body := map[string]interface{}{
"name": getJSONPrimitive(t.Name),
"kind": getJSONPrimitive(t.Kind),
}
if t.PkgRef != (ref.Ref{}) {
body["pkgRef"] = getJSON(t.PkgRef)
}
if t.Desc != nil {
body["desc"] = getJSON(t.Desc)
}
return map[string]interface{}{"type": body}
}
func getJSONIterable(tag string, items []interface{}) interface{} {
j := make([]interface{}, len(items))
for i, item := range items {

View File

@@ -79,6 +79,17 @@ func TestJsonEncode(t *testing.T) {
`, ref2, ref1)
testEncode(expected, SetFromItems("foo", true, uint16(42), ref2, ref1))
// TypeRefs
expected = `j {"type":{"kind":{"uint8":0},"name":""}}
`
testEncode(expected, TypeRef{ref.Ref{}, "", 0, nil})
expected = fmt.Sprintf(`j {"type":{"desc":{"list":[{"ref":"%s"},{"ref":"%s"}]},"kind":{"uint8":15},"name":""}}
`, ref1, ref2)
testEncode(expected, TypeRef{ref.Ref{}, "", 15, []interface{}{ref1, ref2}})
expected = `j {"type":{"desc":{"list":["f","g"]},"kind":{"uint8":18},"name":"enum"}}
`
testEncode(expected, TypeRef{ref.Ref{}, "enum", 18, []interface{}{"f", "g"}})
// Blob (compound)
testEncode(fmt.Sprintf(`j {"cb":["%s",2]}
`, ref2), CompoundBlob{[]uint64{2}, []ref.Ref{ref2}})

View File

@@ -79,6 +79,9 @@ function decodeSet(input, ref, getChunk) {
});
}
function decodeType(input, ref, getChunk) {
}
function decodeCompoundBlob(value, ref, getChunk) {
// {"cb":["sha1-x",lengthX,"sha1-y",lengthY]}
return new Ref(ref, () => {
@@ -127,6 +130,7 @@ var decode = {
map: decodeMap,
ref: decodeRef,
set: decodeSet,
type: decodeType,
uint8: decodeInt,
uint16: decodeInt,
uint32: decodeInt,

View File

@@ -16,6 +16,7 @@ import (
"text/template"
"github.com/attic-labs/noms/Godeps/_workspace/src/golang.org/x/tools/imports"
"github.com/attic-labs/noms/types"
"github.com/attic-labs/noms/d"
"github.com/attic-labs/noms/nomdl/parse"
@@ -54,6 +55,11 @@ func getOutFileName(in string) string {
return in[:len(in)-len(ext)] + ".go"
}
func getBareFileName(in string) string {
base := filepath.Base(in)
return base[:len(base)-len(filepath.Ext(base))]
}
func generate(packageName, in, out string) {
inFile, err := os.Open(in)
d.Chk.NoError(err)
@@ -61,7 +67,7 @@ func generate(packageName, in, out string) {
var buf bytes.Buffer
pkg := parse.ParsePackage("", inFile)
gen := NewCodeGen(&buf, pkg)
gen := NewCodeGen(&buf, getBareFileName(in), pkg)
gen.WritePackage(packageName)
bs, err := imports.Process(out, buf.Bytes(), nil)
@@ -94,12 +100,13 @@ func getGoPackageName() string {
type codeGen struct {
w io.Writer
pkg parse.Package
fileid string
written map[string]bool
templates *template.Template
}
func NewCodeGen(w io.Writer, pkg parse.Package) *codeGen {
gen := &codeGen{w, pkg, map[string]bool{}, nil}
func NewCodeGen(w io.Writer, fileid string, pkg parse.Package) *codeGen {
gen := &codeGen{w, pkg, fileid, map[string]bool{}, nil}
gen.templates = gen.readTemplates()
return gen
}
@@ -109,15 +116,16 @@ func (gen *codeGen) readTemplates() *template.Template {
glob := path.Join(path.Dir(thisfile), "*.tmpl")
return template.Must(template.New("").Funcs(
template.FuncMap{
"defType": gen.defType,
"defToValue": gen.defToValue,
"valueToDef": gen.valueToDef,
"userType": gen.userType,
"userToValue": gen.userToValue,
"valueToUser": gen.valueToUser,
"userZero": gen.userZero,
"valueZero": gen.valueZero,
"title": strings.Title,
"defType": gen.defType,
"defToValue": gen.defToValue,
"valueToDef": gen.valueToDef,
"userType": gen.userType,
"userToValue": gen.userToValue,
"valueToUser": gen.valueToUser,
"userZero": gen.userZero,
"valueZero": gen.valueZero,
"title": strings.Title,
"toTypesTypeRef": gen.toTypesTypeRef,
}).ParseGlob(glob))
}
@@ -136,18 +144,20 @@ func (gen *codeGen) defType(t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind:
case types.BlobKind:
return "types.Blob"
case parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
return strings.ToLower(primitiveKindToString(k))
case parse.EnumKind:
case types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return strings.ToLower(kindToString(k))
case types.EnumKind:
return gen.userName(t)
case parse.ListKind, parse.MapKind, parse.SetKind, parse.StructKind:
case types.ListKind, types.MapKind, types.SetKind, types.StructKind:
return gen.userName(t) + "Def"
case parse.RefKind:
case types.RefKind:
return "ref.Ref"
case parse.ValueKind:
case types.ValueKind:
return "types.Value"
case types.TypeRefKind:
return "types.TypeRef"
}
panic("unreachable")
}
@@ -156,14 +166,16 @@ func (gen *codeGen) userType(t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind:
case types.BlobKind:
return "types.Blob"
case parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
return strings.ToLower(primitiveKindToString(k))
case parse.EnumKind, parse.ListKind, parse.MapKind, parse.RefKind, parse.SetKind, parse.StructKind:
case types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return strings.ToLower(kindToString(k))
case types.EnumKind, types.ListKind, types.MapKind, types.RefKind, types.SetKind, types.StructKind:
return gen.userName(t)
case parse.ValueKind:
case types.ValueKind:
return "types.Value"
case types.TypeRefKind:
return "types.TypeRef"
}
panic("unreachable")
}
@@ -171,15 +183,15 @@ func (gen *codeGen) userType(t parse.TypeRef) string {
func (gen *codeGen) defToValue(val string, t parse.TypeRef) string {
t = gen.resolve(t)
switch t.Desc.Kind() {
case parse.BlobKind, parse.ValueKind:
case types.BlobKind, types.ValueKind, types.TypeRefKind:
return val // Blob & Value type has no Def
case parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
case types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return gen.nativeToValue(val, t)
case parse.EnumKind:
case types.EnumKind:
return fmt.Sprintf("types.Int32(%s)", val)
case parse.ListKind, parse.MapKind, parse.SetKind, parse.StructKind:
case types.ListKind, types.MapKind, types.SetKind, types.StructKind:
return fmt.Sprintf("%s.New().NomsValue()", val)
case parse.RefKind:
case types.RefKind:
return fmt.Sprintf("types.Ref{R: %s}", val)
}
panic("unreachable")
@@ -188,52 +200,64 @@ func (gen *codeGen) defToValue(val string, t parse.TypeRef) string {
func (gen *codeGen) valueToDef(val string, t parse.TypeRef) string {
t = gen.resolve(t)
switch t.Desc.Kind() {
case parse.BlobKind:
case types.BlobKind:
return gen.valueToUser(val, t)
case parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
case types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return gen.valueToNative(val, t)
case parse.EnumKind:
case types.EnumKind:
return fmt.Sprintf("%s(%s.(types.Int32))", gen.userName(t), val)
case parse.ListKind, parse.MapKind, parse.SetKind, parse.StructKind:
case types.ListKind, types.MapKind, types.SetKind, types.StructKind:
return fmt.Sprintf("%s.Def()", gen.valueToUser(val, t))
case parse.RefKind:
case types.RefKind:
return fmt.Sprintf("%s.Ref()", val)
case parse.ValueKind:
case types.ValueKind:
return val // Value type has no Def
case types.TypeRefKind:
return gen.valueToUser(val, t)
}
panic("unreachable")
}
func primitiveKindToString(k parse.NomsKind) string {
func kindToString(k types.NomsKind) string {
switch k {
case parse.BlobKind:
case types.BlobKind:
return "Blob"
case parse.BoolKind:
case types.BoolKind:
return "Bool"
case parse.Float32Kind:
case types.Float32Kind:
return "Float32"
case parse.Float64Kind:
case types.Float64Kind:
return "Float64"
case parse.Int16Kind:
case types.Int16Kind:
return "Int16"
case parse.Int32Kind:
case types.Int32Kind:
return "Int32"
case parse.Int64Kind:
case types.Int64Kind:
return "Int64"
case parse.Int8Kind:
case types.Int8Kind:
return "Int8"
case parse.StringKind:
case types.StringKind:
return "String"
case parse.UInt16Kind:
case types.UInt16Kind:
return "UInt16"
case parse.UInt32Kind:
case types.UInt32Kind:
return "UInt32"
case parse.UInt64Kind:
case types.UInt64Kind:
return "UInt64"
case parse.UInt8Kind:
case types.UInt8Kind:
return "UInt8"
case parse.ValueKind:
case types.ValueKind:
return "Value"
case types.TypeRefKind:
return "TypeRef"
case types.ListKind:
return "List"
case types.MapKind:
return "Map"
case types.RefKind:
return "Ref"
case types.SetKind:
return "Set"
}
panic("unreachable")
}
@@ -242,11 +266,11 @@ func (gen *codeGen) nativeToValue(val string, t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
return fmt.Sprintf("types.%s(%s)", primitiveKindToString(k), val)
case parse.EnumKind:
case types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return fmt.Sprintf("types.%s(%s)", kindToString(k), val)
case types.EnumKind:
return fmt.Sprintf("types.Int32(%s)", val)
case parse.StringKind:
case types.StringKind:
return "types.NewString(" + val + ")"
}
panic("unreachable")
@@ -255,12 +279,12 @@ func (gen *codeGen) nativeToValue(val string, t parse.TypeRef) string {
func (gen *codeGen) valueToNative(val string, t parse.TypeRef) string {
k := t.Desc.Kind()
switch k {
case parse.EnumKind:
case types.EnumKind:
return fmt.Sprintf("%s(%s.(types.Int32))", gen.userType(t), val)
case parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
n := primitiveKindToString(k)
case types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
n := kindToString(k)
return fmt.Sprintf("%s(%s.(types.%s))", strings.ToLower(n), val, n)
case parse.StringKind:
case types.StringKind:
return val + ".(types.String).String()"
}
panic("unreachable")
@@ -270,11 +294,11 @@ func (gen *codeGen) userToValue(val string, t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind, parse.ValueKind:
case types.BlobKind, types.ValueKind, types.TypeRefKind:
return val
case parse.BoolKind, parse.EnumKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
case types.BoolKind, types.EnumKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return gen.nativeToValue(val, t)
case parse.ListKind, parse.MapKind, parse.RefKind, parse.SetKind, parse.StructKind:
case types.ListKind, types.MapKind, types.RefKind, types.SetKind, types.StructKind:
return fmt.Sprintf("%s.NomsValue()", val)
}
panic("unreachable")
@@ -284,14 +308,16 @@ func (gen *codeGen) valueToUser(val string, t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind:
case types.BlobKind:
return fmt.Sprintf("%s.(types.Blob)", val)
case parse.BoolKind, parse.EnumKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
case types.BoolKind, types.EnumKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return gen.valueToNative(val, t)
case parse.ListKind, parse.MapKind, parse.RefKind, parse.SetKind, parse.StructKind:
case types.ListKind, types.MapKind, types.RefKind, types.SetKind, types.StructKind:
return fmt.Sprintf("%sFromVal(%s)", gen.userName(t), val)
case parse.ValueKind:
case types.ValueKind:
return val
case types.TypeRefKind:
return fmt.Sprintf("%s.(types.TypeRef)", val)
}
panic("unreachable")
}
@@ -300,23 +326,25 @@ func (gen *codeGen) userZero(t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind:
case types.BlobKind:
return "types.NewEmptyBlob()"
case parse.BoolKind:
case types.BoolKind:
return "false"
case parse.EnumKind:
case types.EnumKind:
return fmt.Sprintf("%s(0)", gen.userType(t))
case parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
return fmt.Sprintf("%s(0)", strings.ToLower(primitiveKindToString(k)))
case parse.ListKind, parse.MapKind, parse.SetKind:
case types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return fmt.Sprintf("%s(0)", strings.ToLower(kindToString(k)))
case types.ListKind, types.MapKind, types.SetKind:
return fmt.Sprintf("New%s()", gen.userType(t))
case parse.RefKind:
case types.RefKind:
return fmt.Sprintf("%s{ref.Ref{}}", gen.userType(t))
case parse.StringKind:
case types.StringKind:
return `""`
case parse.ValueKind:
case types.ValueKind:
// TODO: This is where a null Value would have been useful.
return "types.Bool(false)"
case types.TypeRefKind:
return "types.TypeRef{}"
}
panic("unreachable")
}
@@ -325,29 +353,31 @@ func (gen *codeGen) valueZero(t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind:
case types.BlobKind:
return "types.NewEmptyBlob()"
case parse.BoolKind:
case types.BoolKind:
return "types.Bool(false)"
case parse.EnumKind:
case types.EnumKind:
return "types.Int32(0)"
case parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind:
return fmt.Sprintf("types.%s(0)", primitiveKindToString(k))
case parse.ListKind:
case types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind:
return fmt.Sprintf("types.%s(0)", kindToString(k))
case types.ListKind:
return "types.NewList()"
case parse.MapKind:
case types.MapKind:
return "types.NewMap()"
case parse.RefKind:
case types.RefKind:
return "types.Ref{R: ref.Ref{}}"
case parse.SetKind:
case types.SetKind:
return "types.NewSet()"
case parse.StringKind:
case types.StringKind:
return `types.NewString("")`
case parse.StructKind:
case types.StructKind:
return fmt.Sprintf("New%s().NomsValue()", gen.userName(t))
case parse.ValueKind:
case types.ValueKind:
// TODO: This is where a null Value would have been useful.
return "types.Bool(false)"
case types.TypeRefKind:
return "types.TypeRef{}"
}
panic("unreachable")
}
@@ -356,20 +386,20 @@ func (gen *codeGen) userName(t parse.TypeRef) string {
t = gen.resolve(t)
k := t.Desc.Kind()
switch k {
case parse.BlobKind, parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind, parse.ValueKind:
return primitiveKindToString(k)
case parse.EnumKind:
case types.BlobKind, types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind, types.ValueKind, types.TypeRefKind:
return kindToString(k)
case types.EnumKind:
return t.Name
case parse.ListKind:
case types.ListKind:
return fmt.Sprintf("ListOf%s", gen.userName(t.Desc.(parse.CompoundDesc).ElemTypes[0]))
case parse.MapKind:
case types.MapKind:
elemTypes := t.Desc.(parse.CompoundDesc).ElemTypes
return fmt.Sprintf("MapOf%sTo%s", gen.userName(elemTypes[0]), gen.userName(elemTypes[1]))
case parse.RefKind:
case types.RefKind:
return fmt.Sprintf("RefOf%s", gen.userName(t.Desc.(parse.CompoundDesc).ElemTypes[0]))
case parse.SetKind:
case types.SetKind:
return fmt.Sprintf("SetOf%s", gen.userName(t.Desc.(parse.CompoundDesc).ElemTypes[0]))
case parse.StructKind:
case types.StructKind:
// We get an empty name when we have a struct that is used as union
if t.Name == "" {
union := t.Desc.(parse.StructDesc).Union
@@ -387,6 +417,45 @@ func (gen *codeGen) userName(t parse.TypeRef) string {
panic("unreachable")
}
func (gen *codeGen) toTypesTypeRef(t parse.TypeRef) string {
if t.IsUnresolved() {
// needs to be pkgRef
return fmt.Sprintf(`types.MakeTypeRef(types.NewString("%s"), types.Ref{})`, t.Name)
} else if types.IsPrimitiveKind(t.Desc.Kind()) {
return fmt.Sprintf("types.MakePrimitiveTypeRef(types.%sKind)", kindToString(t.Desc.Kind()))
}
switch desc := t.Desc.(type) {
case parse.CompoundDesc:
typerefs := make([]string, len(desc.ElemTypes))
for i, t := range desc.ElemTypes {
typerefs[i] = gen.toTypesTypeRef(t)
}
return fmt.Sprintf(`types.MakeCompoundTypeRef(types.NewString("%s"), types.%sKind, %s)`, t.Name, kindToString(t.Desc.Kind()), strings.Join(typerefs, ", "))
case parse.EnumDesc:
d.Chk.Fail("Don't think these ever wind up nested.")
case parse.StructDesc:
flatten := func(f []parse.Field) string {
out := make([]string, 0, len(f))
for _, field := range f {
out = append(out, fmt.Sprintf(`types.NewString("%s"), %s,`, field.Name, gen.toTypesTypeRef(field.T)))
}
return strings.Join(out, "\n")
}
fields := "nil"
choices := "nil"
if len(desc.Fields) != 0 {
fields = fmt.Sprintf("types.NewList(%s)", flatten(desc.Fields))
}
if desc.Union != nil {
choices = fmt.Sprintf("types.NewList(%s)", flatten(desc.Union.Choices))
}
return fmt.Sprintf(`types.MakeStructTypeRef(types.NewString("%s"), %s, %s)`, t.Name, fields, choices)
default:
d.Chk.Fail("Unknown TypeDesc.", "%#v (%T)", desc, desc)
}
panic("ain't done")
}
func (gen *codeGen) resolve(t parse.TypeRef) parse.TypeRef {
if !t.IsUnresolved() {
return t
@@ -395,10 +464,17 @@ func (gen *codeGen) resolve(t parse.TypeRef) parse.TypeRef {
}
func (gen *codeGen) WritePackage(packageName string) {
gen.pkg.Name = packageName
data := struct {
Name string
HasTypes bool
FileID string
Name string
NamedTypes map[string]parse.TypeRef
}{
packageName,
len(gen.pkg.NamedTypes) > 0,
gen.fileid,
gen.pkg.Name,
gen.pkg.NamedTypes,
}
err := gen.templates.ExecuteTemplate(gen.w, "header.tmpl", data)
d.Exp.NoError(err)
@@ -424,19 +500,19 @@ func (gen *codeGen) write(t parse.TypeRef) {
}
k := t.Desc.Kind()
switch k {
case parse.BlobKind, parse.BoolKind, parse.Float32Kind, parse.Float64Kind, parse.Int16Kind, parse.Int32Kind, parse.Int64Kind, parse.Int8Kind, parse.StringKind, parse.UInt16Kind, parse.UInt32Kind, parse.UInt64Kind, parse.UInt8Kind, parse.ValueKind:
case types.BlobKind, types.BoolKind, types.Float32Kind, types.Float64Kind, types.Int16Kind, types.Int32Kind, types.Int64Kind, types.Int8Kind, types.StringKind, types.UInt16Kind, types.UInt32Kind, types.UInt64Kind, types.UInt8Kind, types.ValueKind, types.TypeRefKind:
return
case parse.EnumKind:
case types.EnumKind:
gen.writeEnum(t)
case parse.ListKind:
case types.ListKind:
gen.writeList(t)
case parse.MapKind:
case types.MapKind:
gen.writeMap(t)
case parse.RefKind:
case types.RefKind:
gen.writeRef(t)
case parse.SetKind:
case types.SetKind:
gen.writeSet(t)
case parse.StructKind:
case types.StructKind:
gen.writeStruct(t)
default:
panic("unreachable")
@@ -452,6 +528,8 @@ func (gen *codeGen) writeTemplate(tmpl string, t parse.TypeRef, data interface{}
func (gen *codeGen) writeStruct(t parse.TypeRef) {
desc := t.Desc.(parse.StructDesc)
data := struct {
FileID string
PackageName string
Name string
Fields []parse.Field
Choices []parse.Field
@@ -459,11 +537,13 @@ func (gen *codeGen) writeStruct(t parse.TypeRef) {
UnionZeroType parse.TypeRef
CanUseDef bool
}{
gen.fileid,
gen.pkg.Name,
gen.userName(t),
desc.Fields,
nil,
desc.Union != nil,
parse.TypeRef{Desc: parse.PrimitiveDesc(parse.UInt32Kind)},
parse.TypeRef{Desc: parse.PrimitiveDesc(types.UInt32Kind)},
gen.canUseDef(t),
}
if data.HasUnion {
@@ -563,14 +643,14 @@ func (gen *codeGen) canUseDef(t parse.TypeRef) bool {
func (gen *codeGen) canUseDefRec(t parse.TypeRef, visited map[string]bool, inKey bool) bool {
t = gen.resolve(t)
switch t.Desc.Kind() {
case parse.ListKind:
case types.ListKind:
return !inKey && gen.canUseDefRec(t.Desc.(parse.CompoundDesc).ElemTypes[0], visited, inKey)
case parse.SetKind:
case types.SetKind:
return !inKey && gen.canUseDefRec(t.Desc.(parse.CompoundDesc).ElemTypes[0], visited, true)
case parse.MapKind:
case types.MapKind:
elemTypes := t.Desc.(parse.CompoundDesc).ElemTypes
return !inKey && gen.canUseDefRec(elemTypes[0], visited, true) && gen.canUseDefRec(elemTypes[1], visited, false)
case parse.StructKind:
case types.StructKind:
// Only structs can be recursive
if visited[gen.userName(t)] {
return true

View File

@@ -31,7 +31,7 @@ func assertOutput(inPath, goldenPath string, t *testing.T) {
var buf bytes.Buffer
pkg := parse.ParsePackage("", inFile)
gen := NewCodeGen(&buf, pkg)
gen := NewCodeGen(&buf, getBareFileName(inPath), pkg)
gen.WritePackage("test")
bs, err := imports.Process("", buf.Bytes(), nil)
@@ -54,7 +54,7 @@ func TestCanUseDef(t *testing.T) {
assertCanUseDef := func(s string, using, named bool) {
pkg := parse.ParsePackage("", bytes.NewBufferString(s))
gen := NewCodeGen(nil, pkg)
gen := NewCodeGen(nil, "fakefile", pkg)
for _, t := range pkg.UsingDeclarations {
assert.Equal(using, gen.canUseDef(t), s)
}

View File

@@ -6,3 +6,13 @@ type {{.Name}} uint32
const ({{range $index, $id := .Ids}}
{{title $id}}{{if eq $index 0}} {{$name}} = iota{{end}}{{end}}
)
// Creates and returns a Noms Value that describes {{.Name}}.
func __typeRefOf{{.Name}}() types.TypeRef {
return types.MakeEnumTypeRef(types.NewString("{{.Name}}"), []types.String{
{{range $index, $id := .Ids}}
types.NewString("{{$id}}"),{{end}}
})
}

View File

@@ -3,3 +3,18 @@
package {{.Name}}
import "github.com/attic-labs/noms/types"
{{if .HasTypes}}
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __{{.Name}}PackageInFile_{{.FileID}}_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
{{range $name, $t := .NamedTypes}}
"{{$name}}": __typeRefOf{{$name}}(),{{end}}
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
{{end}}

View File

@@ -7,6 +7,7 @@ type {{.Name}} struct {
func New{{.Name}}() {{.Name}} {
return {{.Name}}{types.NewMap(
types.NewString("$name"), types.NewString("{{.Name}}"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("{{.Name}}"), __{{.PackageName}}PackageInFile_{{.FileID}}_Ref()),
{{range .Fields}}types.NewString("{{title .Name}}"), {{valueZero .T}},
{{end}}{{if .HasUnion}}types.NewString("$unionIndex"), types.UInt32(0),
types.NewString("$unionValue"), {{valueZero .UnionZeroType}},{{end}}
@@ -20,11 +21,11 @@ func New{{.Name}}() {{.Name}} {
__unionValue interface{}
{{end}}}
func (def {{.Name}}Def) New() {{.Name}} {
return {{.Name}}{
types.NewMap(
types.NewString("$name"), types.NewString("{{.Name}}"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("{{.Name}}"), __{{.PackageName}}PackageInFile_{{.FileID}}_Ref()),
{{range .Fields}}types.NewString("{{title .Name}}"), {{defToValue (print "def." (title .Name)) .T}},
{{end}}{{if .HasUnion}}types.NewString("$unionIndex"), types.UInt32(def.__unionIndex),
types.NewString("$unionValue"), def.__unionDefToValue(),
@@ -59,6 +60,20 @@ func New{{.Name}}() {{.Name}} {
{{end}}
{{end}}
// Creates and returns a Noms Value that describes {{.Name}}.
func __typeRefOf{{.Name}}() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("{{.Name}}"),
types.NewList(
{{range .Fields}}types.NewString("{{.Name}}"), {{toTypesTypeRef .T}},
{{end}}
),
{{if .HasUnion}}types.NewList(
{{range .Choices}}types.NewString("{{.Name}}"), {{toTypesTypeRef .T}},
{{end}}
){{else}}nil{{end}})
}
func {{.Name}}FromVal(val types.Value) {{.Name}} {
// TODO: Validate here
return {{.Name}}{val.(types.Map)}
@@ -76,6 +91,10 @@ func (self {{.Name}}) Ref() ref.Ref {
return self.m.Ref()
}
func (self {{.Name}}) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
{{$name := .Name}}
{{range $index, $field := .Fields}}
func (self {{$name}}) {{title .Name}}() {{userType .T}} {

View File

@@ -7,6 +7,20 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_enum_struct_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"EnumStruct": __typeRefOfEnumStruct(),
"Handedness": __typeRefOfHandedness(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// EnumStruct
type EnumStruct struct {
@@ -16,6 +30,7 @@ type EnumStruct struct {
func NewEnumStruct() EnumStruct {
return EnumStruct{types.NewMap(
types.NewString("$name"), types.NewString("EnumStruct"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("EnumStruct"), __testPackageInFile_enum_struct_Ref()),
types.NewString("Hand"), types.Int32(0),
)}
}
@@ -28,6 +43,7 @@ func (def EnumStructDef) New() EnumStruct {
return EnumStruct{
types.NewMap(
types.NewString("$name"), types.NewString("EnumStruct"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("EnumStruct"), __testPackageInFile_enum_struct_Ref()),
types.NewString("Hand"), types.Int32(def.Hand),
)}
}
@@ -38,6 +54,16 @@ func (self EnumStruct) Def() EnumStructDef {
}
}
// Creates and returns a Noms Value that describes EnumStruct.
func __typeRefOfEnumStruct() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("EnumStruct"),
types.NewList(
types.NewString("hand"), types.MakeTypeRef(types.NewString("Handedness"), types.Ref{}),
),
nil)
}
func EnumStructFromVal(val types.Value) EnumStruct {
// TODO: Validate here
return EnumStruct{val.(types.Map)}
@@ -55,6 +81,10 @@ func (self EnumStruct) Ref() ref.Ref {
return self.m.Ref()
}
func (self EnumStruct) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self EnumStruct) Hand() Handedness {
return Handedness(self.m.Get(types.NewString("Hand")).(types.Int32))
}
@@ -72,3 +102,14 @@ const (
Left
Switch
)
// Creates and returns a Noms Value that describes Handedness.
func __typeRefOfHandedness() types.TypeRef {
return types.MakeEnumTypeRef(types.NewString("Handedness"), []types.String{
types.NewString("right"),
types.NewString("left"),
types.NewString("switch"),
})
}

View File

@@ -8,6 +8,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_ref_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"StructWithRef": __typeRefOfStructWithRef(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// RefOfListOfString
type RefOfListOfString struct {
@@ -321,6 +334,7 @@ type StructWithRef struct {
func NewStructWithRef() StructWithRef {
return StructWithRef{types.NewMap(
types.NewString("$name"), types.NewString("StructWithRef"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithRef"), __testPackageInFile_ref_Ref()),
types.NewString("R"), types.Ref{R: ref.Ref{}},
)}
}
@@ -333,6 +347,7 @@ func (def StructWithRefDef) New() StructWithRef {
return StructWithRef{
types.NewMap(
types.NewString("$name"), types.NewString("StructWithRef"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithRef"), __testPackageInFile_ref_Ref()),
types.NewString("R"), types.Ref{R: def.R},
)}
}
@@ -343,6 +358,16 @@ func (self StructWithRef) Def() StructWithRefDef {
}
}
// Creates and returns a Noms Value that describes StructWithRef.
func __typeRefOfStructWithRef() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("StructWithRef"),
types.NewList(
types.NewString("r"), types.MakeCompoundTypeRef(types.NewString(""), types.RefKind, types.MakeCompoundTypeRef(types.NewString(""), types.SetKind, types.MakePrimitiveTypeRef(types.Float32Kind))),
),
nil)
}
func StructWithRefFromVal(val types.Value) StructWithRef {
// TODO: Validate here
return StructWithRef{val.(types.Map)}
@@ -360,6 +385,10 @@ func (self StructWithRef) Ref() ref.Ref {
return self.m.Ref()
}
func (self StructWithRef) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self StructWithRef) R() RefOfSetOfFloat32 {
return RefOfSetOfFloat32FromVal(self.m.Get(types.NewString("R")))
}

View File

@@ -7,6 +7,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_struct_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"Struct": __typeRefOfStruct(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// Struct
type Struct struct {
@@ -16,6 +29,7 @@ type Struct struct {
func NewStruct() Struct {
return Struct{types.NewMap(
types.NewString("$name"), types.NewString("Struct"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("Struct"), __testPackageInFile_struct_Ref()),
types.NewString("S"), types.NewString(""),
types.NewString("B"), types.Bool(false),
)}
@@ -30,6 +44,7 @@ func (def StructDef) New() Struct {
return Struct{
types.NewMap(
types.NewString("$name"), types.NewString("Struct"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("Struct"), __testPackageInFile_struct_Ref()),
types.NewString("S"), types.NewString(def.S),
types.NewString("B"), types.Bool(def.B),
)}
@@ -42,6 +57,17 @@ func (self Struct) Def() StructDef {
}
}
// Creates and returns a Noms Value that describes Struct.
func __typeRefOfStruct() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("Struct"),
types.NewList(
types.NewString("s"), types.MakePrimitiveTypeRef(types.StringKind),
types.NewString("b"), types.MakePrimitiveTypeRef(types.BoolKind),
),
nil)
}
func StructFromVal(val types.Value) Struct {
// TODO: Validate here
return Struct{val.(types.Map)}
@@ -59,6 +85,10 @@ func (self Struct) Ref() ref.Ref {
return self.m.Ref()
}
func (self Struct) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self Struct) S() string {
return self.m.Get(types.NewString("S")).(types.String).String()
}

View File

@@ -7,6 +7,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_struct_primitives_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"StructPrimitives": __typeRefOfStructPrimitives(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// StructPrimitives
type StructPrimitives struct {
@@ -16,6 +29,7 @@ type StructPrimitives struct {
func NewStructPrimitives() StructPrimitives {
return StructPrimitives{types.NewMap(
types.NewString("$name"), types.NewString("StructPrimitives"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructPrimitives"), __testPackageInFile_struct_primitives_Ref()),
types.NewString("Uint64"), types.UInt64(0),
types.NewString("Uint32"), types.UInt32(0),
types.NewString("Uint16"), types.UInt16(0),
@@ -54,6 +68,7 @@ func (def StructPrimitivesDef) New() StructPrimitives {
return StructPrimitives{
types.NewMap(
types.NewString("$name"), types.NewString("StructPrimitives"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructPrimitives"), __testPackageInFile_struct_primitives_Ref()),
types.NewString("Uint64"), types.UInt64(def.Uint64),
types.NewString("Uint32"), types.UInt32(def.Uint32),
types.NewString("Uint16"), types.UInt16(def.Uint16),
@@ -90,6 +105,29 @@ func (self StructPrimitives) Def() StructPrimitivesDef {
}
}
// Creates and returns a Noms Value that describes StructPrimitives.
func __typeRefOfStructPrimitives() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("StructPrimitives"),
types.NewList(
types.NewString("uint64"), types.MakePrimitiveTypeRef(types.UInt64Kind),
types.NewString("uint32"), types.MakePrimitiveTypeRef(types.UInt32Kind),
types.NewString("uint16"), types.MakePrimitiveTypeRef(types.UInt16Kind),
types.NewString("uint8"), types.MakePrimitiveTypeRef(types.UInt8Kind),
types.NewString("int64"), types.MakePrimitiveTypeRef(types.Int64Kind),
types.NewString("int32"), types.MakePrimitiveTypeRef(types.Int32Kind),
types.NewString("int16"), types.MakePrimitiveTypeRef(types.Int16Kind),
types.NewString("int8"), types.MakePrimitiveTypeRef(types.Int8Kind),
types.NewString("float64"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("float32"), types.MakePrimitiveTypeRef(types.Float32Kind),
types.NewString("bool"), types.MakePrimitiveTypeRef(types.BoolKind),
types.NewString("string"), types.MakePrimitiveTypeRef(types.StringKind),
types.NewString("blob"), types.MakePrimitiveTypeRef(types.BlobKind),
types.NewString("value"), types.MakePrimitiveTypeRef(types.ValueKind),
),
nil)
}
func StructPrimitivesFromVal(val types.Value) StructPrimitives {
// TODO: Validate here
return StructPrimitives{val.(types.Map)}
@@ -107,6 +145,10 @@ func (self StructPrimitives) Ref() ref.Ref {
return self.m.Ref()
}
func (self StructPrimitives) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self StructPrimitives) Uint64() uint64 {
return uint64(self.m.Get(types.NewString("Uint64")).(types.UInt64))
}

View File

@@ -7,6 +7,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_struct_recursive_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"Tree": __typeRefOfTree(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// Tree
type Tree struct {
@@ -16,6 +29,7 @@ type Tree struct {
func NewTree() Tree {
return Tree{types.NewMap(
types.NewString("$name"), types.NewString("Tree"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("Tree"), __testPackageInFile_struct_recursive_Ref()),
types.NewString("Children"), types.NewList(),
)}
}
@@ -28,6 +42,7 @@ func (def TreeDef) New() Tree {
return Tree{
types.NewMap(
types.NewString("$name"), types.NewString("Tree"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("Tree"), __testPackageInFile_struct_recursive_Ref()),
types.NewString("Children"), def.Children.New().NomsValue(),
)}
}
@@ -38,6 +53,16 @@ func (self Tree) Def() TreeDef {
}
}
// Creates and returns a Noms Value that describes Tree.
func __typeRefOfTree() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("Tree"),
types.NewList(
types.NewString("children"), types.MakeCompoundTypeRef(types.NewString(""), types.ListKind, types.MakeTypeRef(types.NewString("Tree"), types.Ref{})),
),
nil)
}
func TreeFromVal(val types.Value) Tree {
// TODO: Validate here
return Tree{val.(types.Map)}
@@ -55,6 +80,10 @@ func (self Tree) Ref() ref.Ref {
return self.m.Ref()
}
func (self Tree) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self Tree) Children() ListOfTree {
return ListOfTreeFromVal(self.m.Get(types.NewString("Children")))
}

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/attic-labs/noms/Godeps/_workspace/src/github.com/stretchr/testify/assert"
"github.com/attic-labs/noms/types"
)
func TestDef(t *testing.T) {
@@ -33,3 +34,13 @@ func TestValue(t *testing.T) {
st2 := StructFromVal(val)
assert.True(st.Equals(st2))
}
func TestType(t *testing.T) {
assert := assert.New(t)
def := StructDef{"hi", true}
st := def.New()
typ := st.Type()
assert.EqualValues(types.NewString("Struct"), typ.Name())
assert.EqualValues(__testPackageInFile_struct_Ref(), typ.PackageRef())
}

View File

@@ -7,6 +7,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_struct_with_list_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"StructWithList": __typeRefOfStructWithList(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// StructWithList
type StructWithList struct {
@@ -16,6 +29,7 @@ type StructWithList struct {
func NewStructWithList() StructWithList {
return StructWithList{types.NewMap(
types.NewString("$name"), types.NewString("StructWithList"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithList"), __testPackageInFile_struct_with_list_Ref()),
types.NewString("L"), types.NewList(),
types.NewString("B"), types.Bool(false),
types.NewString("S"), types.NewString(""),
@@ -34,6 +48,7 @@ func (def StructWithListDef) New() StructWithList {
return StructWithList{
types.NewMap(
types.NewString("$name"), types.NewString("StructWithList"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithList"), __testPackageInFile_struct_with_list_Ref()),
types.NewString("L"), def.L.New().NomsValue(),
types.NewString("B"), types.Bool(def.B),
types.NewString("S"), types.NewString(def.S),
@@ -50,6 +65,19 @@ func (self StructWithList) Def() StructWithListDef {
}
}
// Creates and returns a Noms Value that describes StructWithList.
func __typeRefOfStructWithList() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("StructWithList"),
types.NewList(
types.NewString("l"), types.MakeCompoundTypeRef(types.NewString(""), types.ListKind, types.MakePrimitiveTypeRef(types.UInt8Kind)),
types.NewString("b"), types.MakePrimitiveTypeRef(types.BoolKind),
types.NewString("s"), types.MakePrimitiveTypeRef(types.StringKind),
types.NewString("i"), types.MakePrimitiveTypeRef(types.Int64Kind),
),
nil)
}
func StructWithListFromVal(val types.Value) StructWithList {
// TODO: Validate here
return StructWithList{val.(types.Map)}
@@ -67,6 +95,10 @@ func (self StructWithList) Ref() ref.Ref {
return self.m.Ref()
}
func (self StructWithList) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self StructWithList) L() ListOfUInt8 {
return ListOfUInt8FromVal(self.m.Get(types.NewString("L")))
}

View File

@@ -7,6 +7,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_struct_with_union_field_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"StructWithUnionField": __typeRefOfStructWithUnionField(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// StructWithUnionField
type StructWithUnionField struct {
@@ -16,6 +29,7 @@ type StructWithUnionField struct {
func NewStructWithUnionField() StructWithUnionField {
return StructWithUnionField{types.NewMap(
types.NewString("$name"), types.NewString("StructWithUnionField"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithUnionField"), __testPackageInFile_struct_with_union_field_Ref()),
types.NewString("A"), types.Float32(0),
types.NewString("$unionIndex"), types.UInt32(0),
types.NewString("$unionValue"), types.Float64(0),
@@ -32,6 +46,7 @@ func (def StructWithUnionFieldDef) New() StructWithUnionField {
return StructWithUnionField{
types.NewMap(
types.NewString("$name"), types.NewString("StructWithUnionField"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithUnionField"), __testPackageInFile_struct_with_union_field_Ref()),
types.NewString("A"), types.Float32(def.A),
types.NewString("$unionIndex"), types.UInt32(def.__unionIndex),
types.NewString("$unionValue"), def.__unionDefToValue(),
@@ -78,6 +93,22 @@ func (self StructWithUnionField) __unionValueToDef() interface{} {
panic("unreachable")
}
// Creates and returns a Noms Value that describes StructWithUnionField.
func __typeRefOfStructWithUnionField() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("StructWithUnionField"),
types.NewList(
types.NewString("a"), types.MakePrimitiveTypeRef(types.Float32Kind),
),
types.NewList(
types.NewString("b"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("c"), types.MakePrimitiveTypeRef(types.StringKind),
types.NewString("d"), types.MakePrimitiveTypeRef(types.BlobKind),
types.NewString("e"), types.MakePrimitiveTypeRef(types.ValueKind),
types.NewString("f"), types.MakeCompoundTypeRef(types.NewString(""), types.SetKind, types.MakePrimitiveTypeRef(types.UInt8Kind)),
))
}
func StructWithUnionFieldFromVal(val types.Value) StructWithUnionField {
// TODO: Validate here
return StructWithUnionField{val.(types.Map)}
@@ -95,6 +126,10 @@ func (self StructWithUnionField) Ref() ref.Ref {
return self.m.Ref()
}
func (self StructWithUnionField) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self StructWithUnionField) A() float32 {
return float32(self.m.Get(types.NewString("A")).(types.Float32))
}

View File

@@ -7,6 +7,19 @@ import (
"github.com/attic-labs/noms/types"
)
// This function builds up a Noms value that describes the type
// package implemented by this file and registers it with the global
// type package definition cache.
func __testPackageInFile_struct_with_unions_Ref() types.Ref {
p := types.PackageDef{
Types: types.MapOfStringToTypeRefDef{
"StructWithUnions": __typeRefOfStructWithUnions(),
},
}.New()
return types.Ref{R: types.RegisterPackage(&p)}
}
// StructWithUnions
type StructWithUnions struct {
@@ -16,6 +29,7 @@ type StructWithUnions struct {
func NewStructWithUnions() StructWithUnions {
return StructWithUnions{types.NewMap(
types.NewString("$name"), types.NewString("StructWithUnions"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithUnions"), __testPackageInFile_struct_with_unions_Ref()),
types.NewString("A"), New__unionOfBOfFloat64AndCOfString().NomsValue(),
types.NewString("D"), New__unionOfEOfFloat64AndFOfString().NomsValue(),
)}
@@ -30,6 +44,7 @@ func (def StructWithUnionsDef) New() StructWithUnions {
return StructWithUnions{
types.NewMap(
types.NewString("$name"), types.NewString("StructWithUnions"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("StructWithUnions"), __testPackageInFile_struct_with_unions_Ref()),
types.NewString("A"), def.A.New().NomsValue(),
types.NewString("D"), def.D.New().NomsValue(),
)}
@@ -42,6 +57,19 @@ func (self StructWithUnions) Def() StructWithUnionsDef {
}
}
// Creates and returns a Noms Value that describes StructWithUnions.
func __typeRefOfStructWithUnions() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("StructWithUnions"),
types.NewList(
types.NewString("a"), types.MakeStructTypeRef(types.NewString(""), nil, types.NewList(types.NewString("b"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("c"), types.MakePrimitiveTypeRef(types.StringKind))),
types.NewString("d"), types.MakeStructTypeRef(types.NewString(""), nil, types.NewList(types.NewString("e"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("f"), types.MakePrimitiveTypeRef(types.StringKind))),
),
nil)
}
func StructWithUnionsFromVal(val types.Value) StructWithUnions {
// TODO: Validate here
return StructWithUnions{val.(types.Map)}
@@ -59,6 +87,10 @@ func (self StructWithUnions) Ref() ref.Ref {
return self.m.Ref()
}
func (self StructWithUnions) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self StructWithUnions) A() __unionOfBOfFloat64AndCOfString {
return __unionOfBOfFloat64AndCOfStringFromVal(self.m.Get(types.NewString("A")))
}
@@ -84,6 +116,7 @@ type __unionOfBOfFloat64AndCOfString struct {
func New__unionOfBOfFloat64AndCOfString() __unionOfBOfFloat64AndCOfString {
return __unionOfBOfFloat64AndCOfString{types.NewMap(
types.NewString("$name"), types.NewString("__unionOfBOfFloat64AndCOfString"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("__unionOfBOfFloat64AndCOfString"), __testPackageInFile_struct_with_unions_Ref()),
types.NewString("$unionIndex"), types.UInt32(0),
types.NewString("$unionValue"), types.Float64(0),
)}
@@ -98,6 +131,7 @@ func (def __unionOfBOfFloat64AndCOfStringDef) New() __unionOfBOfFloat64AndCOfStr
return __unionOfBOfFloat64AndCOfString{
types.NewMap(
types.NewString("$name"), types.NewString("__unionOfBOfFloat64AndCOfString"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("__unionOfBOfFloat64AndCOfString"), __testPackageInFile_struct_with_unions_Ref()),
types.NewString("$unionIndex"), types.UInt32(def.__unionIndex),
types.NewString("$unionValue"), def.__unionDefToValue(),
)}
@@ -130,6 +164,17 @@ func (self __unionOfBOfFloat64AndCOfString) __unionValueToDef() interface{} {
panic("unreachable")
}
// Creates and returns a Noms Value that describes __unionOfBOfFloat64AndCOfString.
func __typeRefOf__unionOfBOfFloat64AndCOfString() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("__unionOfBOfFloat64AndCOfString"),
types.NewList(),
types.NewList(
types.NewString("b"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("c"), types.MakePrimitiveTypeRef(types.StringKind),
))
}
func __unionOfBOfFloat64AndCOfStringFromVal(val types.Value) __unionOfBOfFloat64AndCOfString {
// TODO: Validate here
return __unionOfBOfFloat64AndCOfString{val.(types.Map)}
@@ -147,6 +192,10 @@ func (self __unionOfBOfFloat64AndCOfString) Ref() ref.Ref {
return self.m.Ref()
}
func (self __unionOfBOfFloat64AndCOfString) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self __unionOfBOfFloat64AndCOfString) B() (val float64, ok bool) {
if self.m.Get(types.NewString("$unionIndex")).(types.UInt32) != 0 {
return
@@ -204,6 +253,7 @@ type __unionOfEOfFloat64AndFOfString struct {
func New__unionOfEOfFloat64AndFOfString() __unionOfEOfFloat64AndFOfString {
return __unionOfEOfFloat64AndFOfString{types.NewMap(
types.NewString("$name"), types.NewString("__unionOfEOfFloat64AndFOfString"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("__unionOfEOfFloat64AndFOfString"), __testPackageInFile_struct_with_unions_Ref()),
types.NewString("$unionIndex"), types.UInt32(0),
types.NewString("$unionValue"), types.Float64(0),
)}
@@ -218,6 +268,7 @@ func (def __unionOfEOfFloat64AndFOfStringDef) New() __unionOfEOfFloat64AndFOfStr
return __unionOfEOfFloat64AndFOfString{
types.NewMap(
types.NewString("$name"), types.NewString("__unionOfEOfFloat64AndFOfString"),
types.NewString("$type"), types.MakeTypeRef(types.NewString("__unionOfEOfFloat64AndFOfString"), __testPackageInFile_struct_with_unions_Ref()),
types.NewString("$unionIndex"), types.UInt32(def.__unionIndex),
types.NewString("$unionValue"), def.__unionDefToValue(),
)}
@@ -250,6 +301,17 @@ func (self __unionOfEOfFloat64AndFOfString) __unionValueToDef() interface{} {
panic("unreachable")
}
// Creates and returns a Noms Value that describes __unionOfEOfFloat64AndFOfString.
func __typeRefOf__unionOfEOfFloat64AndFOfString() types.TypeRef {
return types.MakeStructTypeRef(types.NewString("__unionOfEOfFloat64AndFOfString"),
types.NewList(),
types.NewList(
types.NewString("e"), types.MakePrimitiveTypeRef(types.Float64Kind),
types.NewString("f"), types.MakePrimitiveTypeRef(types.StringKind),
))
}
func __unionOfEOfFloat64AndFOfStringFromVal(val types.Value) __unionOfEOfFloat64AndFOfString {
// TODO: Validate here
return __unionOfEOfFloat64AndFOfString{val.(types.Map)}
@@ -267,6 +329,10 @@ func (self __unionOfEOfFloat64AndFOfString) Ref() ref.Ref {
return self.m.Ref()
}
func (self __unionOfEOfFloat64AndFOfString) Type() types.TypeRef {
return self.m.Get(types.NewString("$type")).(types.TypeRef)
}
func (self __unionOfEOfFloat64AndFOfString) E() (val float64, ok bool) {
if self.m.Get(types.NewString("$unionIndex")).(types.UInt32) != 0 {
return

View File

@@ -29,14 +29,14 @@ Package <- _ dd:Definition+ _ EOF {
switch d.Desc.Kind() {
default:
return nil, fmt.Errorf("%v can't be defined at the top-level", d)
case ListKind, MapKind, RefKind, SetKind:
case types.ListKind, types.MapKind, types.RefKind, types.SetKind:
for _, u := range usings {
if u.Equals(d) {
return nil, fmt.Errorf("%v is a duplicate using declaration", d)
}
}
usings = append(usings, d)
case EnumKind, StructKind:
case types.EnumKind, types.StructKind:
if _, present := named[d.Name]; present {
return nil, fmt.Errorf("Redefinition of " + d.Name)
}
@@ -44,7 +44,7 @@ Package <- _ dd:Definition+ _ EOF {
}
}
}
return Package{aliases, usings, named}, nil
return Package{"", aliases, usings, named}, nil
}
Definition <- Struct / Using / Alias / Enum
@@ -133,16 +133,16 @@ Type <- t:(PrimitiveType / CompoundType / Union / NamespaceIdent) {
}
CompoundType <- `List` _ `(` _ t:Type _ `)` _ {
return makeCompoundTypeRef(ListKind, []TypeRef{t.(TypeRef)}), nil
return makeCompoundTypeRef(types.ListKind, []TypeRef{t.(TypeRef)}), nil
} / `Map` _ `(` _ k:Type _ `,` _ v:Type _ `)` _ {
return makeCompoundTypeRef(MapKind, []TypeRef{k.(TypeRef), v.(TypeRef)}), nil
return makeCompoundTypeRef(types.MapKind, []TypeRef{k.(TypeRef), v.(TypeRef)}), nil
} / `Set` _ `(` _ t:Type _ `)` _ {
return makeCompoundTypeRef(SetKind, []TypeRef{t.(TypeRef)}), nil
return makeCompoundTypeRef(types.SetKind, []TypeRef{t.(TypeRef)}), nil
} / `Ref` _ `(` _ t:Type _ `)` _ {
return makeCompoundTypeRef(RefKind, []TypeRef{t.(TypeRef)}), nil
return makeCompoundTypeRef(types.RefKind, []TypeRef{t.(TypeRef)}), nil
}
PrimitiveType <- p:(`UInt64` / `UInt32` / `UInt16` / `UInt8` / `Int64` / `Int32` / `Int16` / `Int8` / `Float64` / `Float32` / `Bool` / `String` / `Blob` / `Value`) {
PrimitiveType <- p:(`UInt64` / `UInt32` / `UInt16` / `UInt8` / `Int64` / `Int32` / `Int16` / `Int8` / `Float64` / `Float32` / `Bool` / `String` / `Blob` / `Value` / `TypeRef`) {
return makePrimitiveTypeRef(string(p.([]uint8))), nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ import (
"strings"
"github.com/attic-labs/noms/d"
"github.com/attic-labs/noms/types"
)
// ParsePackage reads a Noms package specification from r and returns a Package. Errors will be annotated with logname and thrown.
@@ -19,6 +20,7 @@ func ParsePackage(logname string, r io.Reader) Package {
// UsingDeclarations is kind of a hack to indicate specializations of Noms containers that need to be generated. These should all be one of ListKind, SetKind, MapKind or RefKind, and Desc should be a CompoundDesc instance.
// NamedTypes is a lookup table for types defined in this package. These should all be EnumKind or StructKind. When traversing the definition of a given type, you may run into a TypeRef that IsUnresolved(). In that case, look it up by name in the NamedTypes of the appropriate package.
type Package struct {
Name string
Aliases map[string]string
UsingDeclarations []TypeRef
NamedTypes map[string]TypeRef
@@ -27,7 +29,7 @@ type Package struct {
// TypeRef represents a possibly-symbolic reference to a type.
// PkgRef will be some kind of reference to another Noms type package, almost certainly a ref.Ref.
// Name is required for StructKind and EnumKind types, and may be allowed for others if we do type aliases. Named types are 'exported' in that they can be addressed from other type packages.
// Desc describes the referenced type. It may contain only a NomsKind, in the case of primitives, or it may contain additional information -- e.g.element TypeRefs for compound type specializations, field descriptions for structs, etc. Either way, checking Desc.Kind() allows code to understand how to interpret the rest of the data.
// Desc describes the referenced type. It may contain only a types.NomsKind, in the case of primitives, or it may contain additional information -- e.g.element TypeRefs for compound type specializations, field descriptions for structs, etc. Either way, checking Desc.Kind() allows code to understand how to interpret the rest of the data.
// NB: If we weren't looking towards Nomifying these datastructures, we'd just type-switch on Desc instead of using Kind().
type TypeRef struct {
PkgRef string // Not yet used.
@@ -72,38 +74,11 @@ func namespaceName(pkgRef, name string) (out string) {
// TypeDesc describes a type of the kind returned by Kind(), e.g. Map, Int32, or a custom type.
type TypeDesc interface {
Kind() NomsKind
Kind() types.NomsKind
Equals(other TypeDesc) bool
describe() string // For use in tests.
}
// NomsKind allows a TypeDesc to indicate what kind of type is described.
type NomsKind int
// All supported kinds of Noms types are enumerated here.
const (
BoolKind NomsKind = iota
UInt8Kind
UInt16Kind
UInt32Kind
UInt64Kind
Int8Kind
Int16Kind
Int32Kind
Int64Kind
Float32Kind
Float64Kind
StringKind
BlobKind
ValueKind
ListKind
MapKind
RefKind
SetKind
EnumKind
StructKind
)
func makePrimitiveTypeRef(p string) TypeRef {
return TypeRef{Desc: primitiveToDesc[p]}
}
@@ -123,10 +98,11 @@ func makePrimitiveTypeRef(p string) TypeRef {
// String
// Blob
// Value
type PrimitiveDesc NomsKind
// TypeRef
type PrimitiveDesc types.NomsKind
func (p PrimitiveDesc) Kind() NomsKind {
return NomsKind(p)
func (p PrimitiveDesc) Kind() types.NomsKind {
return types.NomsKind(p)
}
func (p PrimitiveDesc) Equals(other TypeDesc) bool {
@@ -143,34 +119,35 @@ func (p PrimitiveDesc) describe() string {
}
var primitiveToDesc = map[string]PrimitiveDesc{
"Bool": PrimitiveDesc(BoolKind),
"UInt64": PrimitiveDesc(UInt64Kind),
"UInt32": PrimitiveDesc(UInt32Kind),
"UInt16": PrimitiveDesc(UInt16Kind),
"UInt8": PrimitiveDesc(UInt8Kind),
"Int64": PrimitiveDesc(Int64Kind),
"Int32": PrimitiveDesc(Int32Kind),
"Int16": PrimitiveDesc(Int16Kind),
"Int8": PrimitiveDesc(Int8Kind),
"Float64": PrimitiveDesc(Float64Kind),
"Float32": PrimitiveDesc(Float32Kind),
"String": PrimitiveDesc(StringKind),
"Blob": PrimitiveDesc(BlobKind),
"Value": PrimitiveDesc(ValueKind),
"Bool": PrimitiveDesc(types.BoolKind),
"UInt64": PrimitiveDesc(types.UInt64Kind),
"UInt32": PrimitiveDesc(types.UInt32Kind),
"UInt16": PrimitiveDesc(types.UInt16Kind),
"UInt8": PrimitiveDesc(types.UInt8Kind),
"Int64": PrimitiveDesc(types.Int64Kind),
"Int32": PrimitiveDesc(types.Int32Kind),
"Int16": PrimitiveDesc(types.Int16Kind),
"Int8": PrimitiveDesc(types.Int8Kind),
"Float64": PrimitiveDesc(types.Float64Kind),
"Float32": PrimitiveDesc(types.Float32Kind),
"String": PrimitiveDesc(types.StringKind),
"Blob": PrimitiveDesc(types.BlobKind),
"Value": PrimitiveDesc(types.ValueKind),
"TypeRef": PrimitiveDesc(types.TypeRefKind),
}
func makeCompoundTypeRef(k NomsKind, e []TypeRef) TypeRef {
func makeCompoundTypeRef(k types.NomsKind, e []TypeRef) TypeRef {
return TypeRef{Desc: CompoundDesc{k, e}}
}
// CompoundDesc describes a List, Map, Set or Ref type.
// ElemTypes indicates what type or types are in the container indicated by kind, e.g. Map key and value or Set element.
type CompoundDesc struct {
kind NomsKind
kind types.NomsKind
ElemTypes []TypeRef
}
func (c CompoundDesc) Kind() NomsKind {
func (c CompoundDesc) Kind() types.NomsKind {
return c.kind
}
@@ -194,13 +171,13 @@ func (c CompoundDesc) describe() string {
return strings.Join(out, ", ")
}
switch c.kind {
case ListKind:
case types.ListKind:
return "List(" + descElems() + ")"
case MapKind:
case types.MapKind:
return "Map(" + descElems() + ")"
case RefKind:
case types.RefKind:
return "Ref(" + descElems() + ")"
case SetKind:
case types.SetKind:
return "Set(" + descElems() + ")"
default:
panic(fmt.Errorf("Kind is not compound: %v", c.kind))
@@ -216,8 +193,8 @@ type EnumDesc struct {
IDs []string
}
func (e EnumDesc) Kind() NomsKind {
return EnumKind
func (e EnumDesc) Kind() types.NomsKind {
return types.EnumKind
}
func (e EnumDesc) Equals(other TypeDesc) bool {
@@ -271,8 +248,8 @@ type StructDesc struct {
Union *UnionDesc
}
func (s StructDesc) Kind() NomsKind {
return StructKind
func (s StructDesc) Kind() types.NomsKind {
return types.StructKind
}
func (s StructDesc) Equals(other TypeDesc) bool {

View File

@@ -7,6 +7,7 @@ import (
"github.com/attic-labs/noms/Godeps/_workspace/src/github.com/stretchr/testify/suite"
"github.com/attic-labs/noms/d"
"github.com/attic-labs/noms/types"
)
const (
@@ -51,11 +52,11 @@ using List(Noms.Commit)
pkg := ParsePackage("", strings.NewReader(usingDecls))
suite.Len(pkg.UsingDeclarations, 2)
suite.Equal(MapKind, pkg.UsingDeclarations[0].Desc.Kind())
suite.Equal(types.MapKind, pkg.UsingDeclarations[0].Desc.Kind())
suite.EqualValues([]TypeRef{makePrimitiveTypeRef("String"), makeTypeRef("", "Simple")},
pkg.UsingDeclarations[0].Desc.(CompoundDesc).ElemTypes)
suite.Equal(ListKind, pkg.UsingDeclarations[1].Desc.Kind())
suite.Equal(types.ListKind, pkg.UsingDeclarations[1].Desc.Kind())
suite.EqualValues([]TypeRef{makeTypeRef("Noms", "Commit")},
pkg.UsingDeclarations[1].Desc.(CompoundDesc).ElemTypes)
}
@@ -181,14 +182,14 @@ type ParsedResultTestSuite struct {
func (suite *ParsedResultTestSuite) SetupTest() {
suite.primField = testField{"a", makePrimitiveTypeRef("Int64")}
suite.compoundField = testField{"set", makeCompoundTypeRef(SetKind, []TypeRef{makePrimitiveTypeRef("String")})}
suite.compoundField = testField{"set", makeCompoundTypeRef(types.SetKind, []TypeRef{makePrimitiveTypeRef("String")})}
suite.compoundOfCompoundField = testField{
"listOfSet",
makeCompoundTypeRef(ListKind, []TypeRef{
makeCompoundTypeRef(SetKind, []TypeRef{makePrimitiveTypeRef("String")})})}
makeCompoundTypeRef(types.ListKind, []TypeRef{
makeCompoundTypeRef(types.SetKind, []TypeRef{makePrimitiveTypeRef("String")})})}
suite.mapOfNamedTypeField = testField{
"mapOfStructToOther",
makeCompoundTypeRef(MapKind, []TypeRef{
makeCompoundTypeRef(types.MapKind, []TypeRef{
makeTypeRef("", "Struct"),
makeTypeRef("Elsewhere", "Other"),
}),

351
types/package.go Normal file
View File

@@ -0,0 +1,351 @@
// This file was generated by nomdl/codegen and then had references to this package (types) removed by hand. The $type field of Package was also manually set to the TypeRef that describes a Package directly.
package types
import (
"github.com/attic-labs/noms/chunks"
"github.com/attic-labs/noms/ref"
)
// Package
type PackageDef struct {
Dependencies SetOfRefOfPackageDef
Types MapOfStringToTypeRefDef
}
type Package struct {
m Map
}
func NewPackage() Package {
return Package{NewMap(
NewString("$name"), NewString("Package"),
NewString("$type"), __typeRefOfPackage(),
NewString("Dependencies"), NewSet(),
NewString("Types"), NewMap(),
)}
}
func (def PackageDef) New() Package {
return Package{
NewMap(
NewString("$name"), NewString("Package"),
NewString("$type"), __typeRefOfPackage(),
NewString("Dependencies"), def.Dependencies.New().NomsValue(),
NewString("Types"), def.Types.New().NomsValue(),
)}
}
func (self Package) Def() PackageDef {
return PackageDef{
SetOfRefOfPackageFromVal(self.m.Get(NewString("Dependencies"))).Def(),
MapOfStringToTypeRefFromVal(self.m.Get(NewString("Types"))).Def(),
}
}
// Creates and returns a Noms Value that describes Package.
func __typeRefOfPackage() TypeRef {
return MakeStructTypeRef(NewString("Package"),
NewList(
NewString("Dependencies"), MakeCompoundTypeRef(NewString(""), SetKind, MakeCompoundTypeRef(NewString(""), RefKind, MakeTypeRef(NewString("Package"), Ref{}))),
NewString("Types"), MakeCompoundTypeRef(NewString(""), MapKind, MakePrimitiveTypeRef(StringKind), MakePrimitiveTypeRef(TypeRefKind)),
),
nil)
}
func PackageFromVal(val Value) Package {
// TODO: Validate here
return Package{val.(Map)}
}
func (self Package) NomsValue() Value {
return self.m
}
func (self Package) Equals(other Package) bool {
return self.m.Equals(other.m)
}
func (self Package) Ref() ref.Ref {
return self.m.Ref()
}
func (self Package) Type() TypeRef {
return self.m.Get(NewString("$type")).(TypeRef)
}
func (self Package) Dependencies() SetOfRefOfPackage {
return SetOfRefOfPackageFromVal(self.m.Get(NewString("Dependencies")))
}
func (self Package) SetDependencies(val SetOfRefOfPackage) Package {
return Package{self.m.Set(NewString("Dependencies"), val.NomsValue())}
}
func (self Package) Types() MapOfStringToTypeRef {
return MapOfStringToTypeRefFromVal(self.m.Get(NewString("Types")))
}
func (self Package) SetTypes(val MapOfStringToTypeRef) Package {
return Package{self.m.Set(NewString("Types"), val.NomsValue())}
}
// SetOfRefOfPackage
type SetOfRefOfPackage struct {
s Set
}
type SetOfRefOfPackageDef map[ref.Ref]bool
func NewSetOfRefOfPackage() SetOfRefOfPackage {
return SetOfRefOfPackage{NewSet()}
}
func (def SetOfRefOfPackageDef) New() SetOfRefOfPackage {
l := make([]Value, len(def))
i := 0
for d, _ := range def {
l[i] = Ref{R: d}
i++
}
return SetOfRefOfPackage{NewSet(l...)}
}
func (s SetOfRefOfPackage) Def() SetOfRefOfPackageDef {
def := make(map[ref.Ref]bool, s.Len())
s.s.Iter(func(v Value) bool {
def[v.Ref()] = true
return false
})
return def
}
func SetOfRefOfPackageFromVal(p Value) SetOfRefOfPackage {
return SetOfRefOfPackage{p.(Set)}
}
func (s SetOfRefOfPackage) NomsValue() Value {
return s.s
}
func (s SetOfRefOfPackage) Equals(p SetOfRefOfPackage) bool {
return s.s.Equals(p.s)
}
func (s SetOfRefOfPackage) Ref() ref.Ref {
return s.s.Ref()
}
func (s SetOfRefOfPackage) Empty() bool {
return s.s.Empty()
}
func (s SetOfRefOfPackage) Len() uint64 {
return s.s.Len()
}
func (s SetOfRefOfPackage) Has(p RefOfPackage) bool {
return s.s.Has(p.NomsValue())
}
type SetOfRefOfPackageIterCallback func(p RefOfPackage) (stop bool)
func (s SetOfRefOfPackage) Iter(cb SetOfRefOfPackageIterCallback) {
s.s.Iter(func(v Value) bool {
return cb(RefOfPackageFromVal(v))
})
}
type SetOfRefOfPackageIterAllCallback func(p RefOfPackage)
func (s SetOfRefOfPackage) IterAll(cb SetOfRefOfPackageIterAllCallback) {
s.s.IterAll(func(v Value) {
cb(RefOfPackageFromVal(v))
})
}
type SetOfRefOfPackageFilterCallback func(p RefOfPackage) (keep bool)
func (s SetOfRefOfPackage) Filter(cb SetOfRefOfPackageFilterCallback) SetOfRefOfPackage {
ns := NewSetOfRefOfPackage()
s.IterAll(func(v RefOfPackage) {
if cb(v) {
ns = ns.Insert(v)
}
})
return ns
}
func (s SetOfRefOfPackage) Insert(p ...RefOfPackage) SetOfRefOfPackage {
return SetOfRefOfPackage{s.s.Insert(s.fromElemSlice(p)...)}
}
func (s SetOfRefOfPackage) Remove(p ...RefOfPackage) SetOfRefOfPackage {
return SetOfRefOfPackage{s.s.Remove(s.fromElemSlice(p)...)}
}
func (s SetOfRefOfPackage) Union(others ...SetOfRefOfPackage) SetOfRefOfPackage {
return SetOfRefOfPackage{s.s.Union(s.fromStructSlice(others)...)}
}
func (s SetOfRefOfPackage) Subtract(others ...SetOfRefOfPackage) SetOfRefOfPackage {
return SetOfRefOfPackage{s.s.Subtract(s.fromStructSlice(others)...)}
}
func (s SetOfRefOfPackage) Any() RefOfPackage {
return RefOfPackageFromVal(s.s.Any())
}
func (s SetOfRefOfPackage) fromStructSlice(p []SetOfRefOfPackage) []Set {
r := make([]Set, len(p))
for i, v := range p {
r[i] = v.s
}
return r
}
func (s SetOfRefOfPackage) fromElemSlice(p []RefOfPackage) []Value {
r := make([]Value, len(p))
for i, v := range p {
r[i] = v.NomsValue()
}
return r
}
// RefOfPackage
type RefOfPackage struct {
r ref.Ref
}
func NewRefOfPackage(r ref.Ref) RefOfPackage {
return RefOfPackage{r}
}
func (r RefOfPackage) Ref() ref.Ref {
return r.r
}
func (r RefOfPackage) Equals(other RefOfPackage) bool {
return r.Ref() == other.Ref()
}
func (r RefOfPackage) NomsValue() Value {
return Ref{R: r.r}
}
func RefOfPackageFromVal(p Value) RefOfPackage {
return RefOfPackage{p.(Ref).Ref()}
}
func (r RefOfPackage) GetValue(cs chunks.ChunkSource) Package {
return PackageFromVal(ReadValue(r.r, cs))
}
func (r RefOfPackage) SetValue(val Package, cs chunks.ChunkSink) RefOfPackage {
ref := WriteValue(val.NomsValue(), cs)
return RefOfPackage{ref}
}
// MapOfStringToTypeRef
type MapOfStringToTypeRef struct {
m Map
}
type MapOfStringToTypeRefDef map[string]TypeRef
func NewMapOfStringToTypeRef() MapOfStringToTypeRef {
return MapOfStringToTypeRef{NewMap()}
}
func (def MapOfStringToTypeRefDef) New() MapOfStringToTypeRef {
kv := make([]Value, 0, len(def)*2)
for k, v := range def {
kv = append(kv, NewString(k), v)
}
return MapOfStringToTypeRef{NewMap(kv...)}
}
func (self MapOfStringToTypeRef) Def() MapOfStringToTypeRefDef {
def := make(map[string]TypeRef)
self.m.Iter(func(k, v Value) bool {
def[k.(String).String()] = v.(TypeRef)
return false
})
return def
}
func MapOfStringToTypeRefFromVal(p Value) MapOfStringToTypeRef {
// TODO: Validate here
return MapOfStringToTypeRef{p.(Map)}
}
func (m MapOfStringToTypeRef) NomsValue() Value {
return m.m
}
func (m MapOfStringToTypeRef) Equals(p MapOfStringToTypeRef) bool {
return m.m.Equals(p.m)
}
func (m MapOfStringToTypeRef) Ref() ref.Ref {
return m.m.Ref()
}
func (m MapOfStringToTypeRef) Empty() bool {
return m.m.Empty()
}
func (m MapOfStringToTypeRef) Len() uint64 {
return m.m.Len()
}
func (m MapOfStringToTypeRef) Has(p string) bool {
return m.m.Has(NewString(p))
}
func (m MapOfStringToTypeRef) Get(p string) TypeRef {
return m.m.Get(NewString(p)).(TypeRef)
}
func (m MapOfStringToTypeRef) Set(k string, v TypeRef) MapOfStringToTypeRef {
return MapOfStringToTypeRef{m.m.Set(NewString(k), v)}
}
// TODO: Implement SetM?
func (m MapOfStringToTypeRef) Remove(p string) MapOfStringToTypeRef {
return MapOfStringToTypeRef{m.m.Remove(NewString(p))}
}
type MapOfStringToTypeRefIterCallback func(k string, v TypeRef) (stop bool)
func (m MapOfStringToTypeRef) Iter(cb MapOfStringToTypeRefIterCallback) {
m.m.Iter(func(k, v Value) bool {
return cb(k.(String).String(), v.(TypeRef))
})
}
type MapOfStringToTypeRefIterAllCallback func(k string, v TypeRef)
func (m MapOfStringToTypeRef) IterAll(cb MapOfStringToTypeRefIterAllCallback) {
m.m.IterAll(func(k, v Value) {
cb(k.(String).String(), v.(TypeRef))
})
}
type MapOfStringToTypeRefFilterCallback func(k string, v TypeRef) (keep bool)
func (m MapOfStringToTypeRef) Filter(cb MapOfStringToTypeRefFilterCallback) MapOfStringToTypeRef {
nm := NewMapOfStringToTypeRef()
m.IterAll(func(k string, v TypeRef) {
if cb(k, v) {
nm = nm.Set(k, v)
}
})
return nm
}

4
types/package.noms Normal file
View File

@@ -0,0 +1,4 @@
struct Package {
Dependencies :Set(Ref(Package))
Types :Map(String, TypeRef)
}

21
types/package_table.go Normal file
View File

@@ -0,0 +1,21 @@
package types
import (
"github.com/attic-labs/noms/d"
"github.com/attic-labs/noms/ref"
)
var packages map[ref.Ref]*Package = map[ref.Ref]*Package{}
// LookupPackage looks for a Package by ref.Ref in the global cache of Noms type packages.
func LookupPackage(r ref.Ref) *Package {
return packages[r]
}
// RegisterPackage puts p into the global cache of Noms type packages.
func RegisterPackage(p *Package) (r ref.Ref) {
d.Chk.NotNil(p)
r = p.Ref()
packages[r] = p
return
}

44
types/package_test.go Normal file
View File

@@ -0,0 +1,44 @@
package types
import (
"testing"
"github.com/attic-labs/noms/Godeps/_workspace/src/github.com/stretchr/testify/assert"
)
func TestType(t *testing.T) {
assert := assert.New(t)
st := NewPackage()
typ := st.Type()
name := NewString("Package")
assert.EqualValues(name, typ.Name())
assert.Equal(StructKind, typ.Kind())
fields, choices := typ.StructDesc()
assert.Nil(choices)
assert.EqualValues(4, fields.Len())
find := func(s string) TypeRef {
for i := uint64(0); i < fields.Len(); i++ {
if i%2 == 0 {
f := fields.Get(i).(String)
if f.Equals(NewString(s)) {
return fields.Get(i + 1).(TypeRef)
}
}
}
return TypeRef{}
}
tr := find("Dependencies")
if assert.Equal(SetKind, tr.Kind()) {
elemType := tr.ElemDesc()
if assert.Equal(RefKind, elemType.Kind()) {
assert.EqualValues(name, elemType.ElemDesc().Name())
}
}
tr = find("Types")
if assert.Equal(MapKind, tr.Kind()) {
keyType, valueType := tr.MapElemDesc()
assert.Equal(StringKind, keyType.Kind())
assert.Equal(TypeRefKind, valueType.Kind())
}
}

View File

@@ -2,7 +2,6 @@ package types
import (
"bytes"
"fmt"
"io"
"io/ioutil"
@@ -63,6 +62,15 @@ func fromEncodeable(i interface{}, cs chunks.ChunkSource) Future {
return futureMapFromIterable(i, cs)
case enc.Set:
return futureSetFromIterable(i, cs)
case enc.TypeRef:
kind := NomsKind(i.Kind)
if i.PkgRef != (ref.Ref{}) {
d.Chk.Equal(ValueKind, kind)
d.Chk.Nil(i.Desc)
return futureFromValue(MakeTypeRef(NewString(i.Name), Ref{R: i.PkgRef}))
}
desc := typeDescFromInterface(kind, i.Desc, cs)
return futureFromValue(buildType(NewString(i.Name), kind, desc))
case enc.CompoundBlob:
blobs := make([]Future, len(i.Blobs))
for idx, blobRef := range i.Blobs {
@@ -78,7 +86,7 @@ func fromEncodeable(i interface{}, cs chunks.ChunkSource) Future {
cl := newCompoundList(i.Offsets, lists, cs)
return futureFromValue(cl)
default:
d.Exp.Fail(fmt.Sprintf("Unknown encodeable", "%+v", i))
d.Exp.Fail("Unknown encodeable", "%+v", i)
}
return nil
@@ -99,6 +107,33 @@ func futureSetFromIterable(items []interface{}, cs chunks.ChunkSource) Future {
return futureFromValue(setFromFutures(output, cs))
}
func typeDescFromInterface(kind NomsKind, i interface{}, cs chunks.ChunkSource) Value {
if IsPrimitiveKind(kind) {
d.Chk.Nil(i, "Primitive TypeRefs have no description.")
return nil
}
switch kind {
case ListKind, RefKind, SetKind:
return fromEncodeable(i.(enc.TypeRef), cs).Deref(cs)
case MapKind:
items := i.([]interface{})
d.Chk.Len(items, 2)
return listFromFutures(futuresFromIterable(items, cs), cs)
case EnumKind:
items := i.([]interface{})
for _, item := range items {
d.Chk.IsType("", item, "Each enumeration must be a string.")
}
return listFromFutures(futuresFromIterable(items, cs), cs)
case StructKind:
items := i.(enc.Map)
return mapFromFutures(futuresFromIterable(items, cs), cs)
default:
d.Exp.Fail("Unrecognized Kind:", "%v", kind)
panic("unreachable")
}
}
func futuresFromIterable(items []interface{}, cs chunks.ChunkSource) (f []Future) {
f = make([]Future, len(items))
for i, inVal := range items {

177
types/type_ref.go Normal file
View File

@@ -0,0 +1,177 @@
package types
import (
"github.com/attic-labs/noms/d"
"github.com/attic-labs/noms/ref"
)
// TypeRef structs define and describe Noms types, both custom and built-in.
// Kind and Desc collectively describe any legal Noms type. Kind captures what kind of type the instance describes, e.g. Set, Bool, Map, Struct, etc. Desc captures further information needed to flesh out the definition, such as the type of the elements in a List, or the field names and types of a Struct.
// If Kind refers to a primitive, then Desc is empty.
// If Kind refers to List, Set or Ref, then Desc is a TypeRef describing the element type.
// If Kind refers to Map, then Desc is a 2-element List(TypeRef), describing the key and value types respectively.
// If Kind refers to Struct, then Desc is {"fields": [name, type, ...], "choices": [name, type, ...]}.
// If Kind refers to Enum, then Desc is a List(String) describing the enumerated values.
// Name is optional.
// pkgRef is optional. If set, then pkgRef + name address a type defined in another package.
type TypeRef struct {
kind NomsKind
pkgRef *Ref
name String
desc Value
ref ref.Ref
}
func (t TypeRef) Kind() NomsKind {
return t.kind
}
func (t TypeRef) PackageRef() Ref {
if t.pkgRef == nil {
return Ref{}
}
return *t.pkgRef
}
func (t TypeRef) Name() String {
return t.name
}
func (t TypeRef) ElemDesc() TypeRef {
return t.desc.(TypeRef)
}
// TODO: should return a ListOfString? or just a []String?
func (t TypeRef) EnumDesc() List {
return t.desc.(List)
}
func (t TypeRef) MapElemDesc() (TypeRef, TypeRef) {
l := t.desc.(List)
d.Chk.Equal(uint64(2), l.Len())
return l.Get(0).(TypeRef), l.Get(1).(TypeRef)
}
func (t TypeRef) StructDesc() (fields, choices List) {
m := t.desc.(Map)
f := m.Get(NewString("fields"))
if f != nil {
fields = f.(List)
}
c := m.Get(NewString("choices"))
if c != nil {
choices = c.(List)
}
return
}
func (t TypeRef) Ref() ref.Ref {
return ensureRef(&t.ref, t)
}
func (t TypeRef) Equals(other Value) (res bool) {
if other == nil {
return false
} else {
return t.Ref() == other.Ref()
}
}
func (t TypeRef) Chunks() (out []Future) {
if t.pkgRef != nil {
out = append(out, futureFromRef(t.pkgRef.Ref()))
}
if t.desc != nil {
out = append(out, t.desc.Chunks()...)
}
return
}
// NomsKind allows a TypeDesc to indicate what kind of type is described.
type NomsKind uint8
// All supported kinds of Noms types are enumerated here.
const (
BoolKind NomsKind = iota
UInt8Kind
UInt16Kind
UInt32Kind
UInt64Kind
Int8Kind
Int16Kind
Int32Kind
Int64Kind
Float32Kind
Float64Kind
StringKind
BlobKind
ValueKind
ListKind
MapKind
RefKind
SetKind
EnumKind
StructKind
TypeRefKind
)
func IsPrimitiveKind(k NomsKind) bool {
switch k {
case BoolKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind, Float32Kind, Float64Kind, UInt8Kind, UInt16Kind, UInt32Kind, UInt64Kind, StringKind, BlobKind, ValueKind, TypeRefKind:
return true
default:
return false
}
}
func MakePrimitiveTypeRef(k NomsKind) TypeRef {
return buildType(NewString(""), k, nil)
}
func MakeCompoundTypeRef(name String, kind NomsKind, elemTypes ...TypeRef) TypeRef {
if len(elemTypes) == 1 {
d.Chk.NotEqual(MapKind, kind, "MapKind requires 2 element types.")
return buildType(name, kind, elemTypes[0])
}
d.Chk.Equal(MapKind, kind)
d.Chk.Len(elemTypes, 2, "MapKind requires 2 element types.")
return buildType(name, kind, NewList(elemTypes[0], elemTypes[1]))
}
func MakeEnumTypeRef(name String, ids []String) TypeRef {
vids := make([]Value, len(ids))
for i, id := range ids {
vids[i] = id
}
return buildType(name, EnumKind, NewList(vids...))
}
func MakeStructTypeRef(name String, fields, choices List) TypeRef {
desc := NewMap()
if fields != nil {
desc = desc.Set(NewString("fields"), fields)
}
if choices != nil {
desc = desc.Set(NewString("choices"), choices)
}
return buildType(name, StructKind, desc)
}
func MakeTypeRef(name String, pkg Ref) TypeRef {
return TypeRef{name: name, pkgRef: &pkg, kind: ValueKind}
}
func buildType(name String, kind NomsKind, desc Value) TypeRef {
if IsPrimitiveKind(kind) {
d.Chk.Nil(desc, "Primitive TypeRefs have no description.")
return TypeRef{name: name, kind: kind}
}
switch kind {
case ListKind, RefKind, SetKind, MapKind, EnumKind, StructKind:
return TypeRef{name: name, kind: kind, desc: desc}
default:
d.Exp.Fail("Unrecognized Kind:", "%v", kind)
panic("unreachable")
}
}

52
types/type_ref_test.go Normal file
View File

@@ -0,0 +1,52 @@
package types
import (
"testing"
"github.com/attic-labs/noms/Godeps/_workspace/src/github.com/stretchr/testify/assert"
"github.com/attic-labs/noms/chunks"
)
func TestTypes(t *testing.T) {
assert := assert.New(t)
cs := chunks.NewMemoryStore()
boolType := MakePrimitiveTypeRef(BoolKind)
uint8Type := MakePrimitiveTypeRef(UInt8Kind)
stringType := MakePrimitiveTypeRef(StringKind)
mapType := MakeCompoundTypeRef(NewString("MapOfStringToUInt8"), MapKind, stringType, uint8Type)
setType := MakeCompoundTypeRef(NewString("SetOfString"), SetKind, stringType)
mahType := MakeStructTypeRef(NewString("MahStruct"), NewList(
NewString("Field1"), stringType,
NewString("Field2"), boolType), nil)
otherType := MakeStructTypeRef(NewString("MahOtherStruct"), nil,
NewList(
NewString("StructField"), mahType,
NewString("StringField"), stringType))
mRef := WriteValue(mapType, cs)
setRef := WriteValue(setType, cs)
otherRef := WriteValue(otherType, cs)
mahRef := WriteValue(mahType, cs)
assert.True(otherType.Equals(ReadValue(otherRef, cs)))
assert.True(mapType.Equals(ReadValue(mRef, cs)))
assert.True(setType.Equals(ReadValue(setRef, cs)))
assert.True(mahType.Equals(ReadValue(mahRef, cs)))
}
func TestTypeWithPkgRef(t *testing.T) {
assert := assert.New(t)
cs := chunks.NewMemoryStore()
pkg := PackageDef{
Types: MapOfStringToTypeRefDef{"Spin": MakePrimitiveTypeRef(Float64Kind)},
}.New()
pkgRef := RegisterPackage(&pkg)
unresolvedType := MakeTypeRef(NewString("Spin"), Ref{R: pkgRef})
unresolvedRef := WriteValue(unresolvedType, cs)
assert.EqualValues(pkgRef, ReadValue(unresolvedRef, cs).Chunks()[0].Ref())
assert.NotNil(ReadValue(pkgRef, cs))
}

View File

@@ -42,6 +42,8 @@ func toEncodeable(v Value, cs chunks.ChunkSink) interface{} {
return makeSetEncodeable(v, cs)
case String:
return v.String()
case TypeRef:
return makeTypeEncodeable(v, cs)
default:
return v
}
@@ -92,6 +94,15 @@ func makeSetEncodeable(s Set, cs chunks.ChunkSink) interface{} {
return enc.SetFromItems(items...)
}
func makeTypeEncodeable(t TypeRef, cs chunks.ChunkSink) interface{} {
pkgRef := t.PackageRef().Ref()
p := LookupPackage(pkgRef)
if p != nil {
pkgRef = WriteValue(p.NomsValue(), cs)
}
return enc.TypeRef{PkgRef: pkgRef, Name: t.Name().String(), Kind: uint8(t.kind), Desc: toEncodeable(t.desc, cs)}
}
func processChild(f Future, cs chunks.ChunkSink) interface{} {
if v, ok := f.(*unresolvedFuture); ok {
return v.Ref()

View File

@@ -30,7 +30,6 @@ func TestWriteValue(t *testing.T) {
assert.NoError(err)
testEncode(string([]byte{'b', ' ', 0x00, 0x01, 0x02}), b)
testEncode(string("j \"foo\"\n"), NewString("foo"))
}
func TestWriteBlobLeaf(t *testing.T) {