From a3b3bb10903d8304b35ccf0d64455342cbdac354 Mon Sep 17 00:00:00 2001 From: Erik Arvidsson Date: Wed, 22 Jul 2015 14:06:36 -0700 Subject: [PATCH] Add Map codegen --- nomgen/map.tmpl | 60 ++++++++++++++++++++++++++++++++++++++++++++++ nomgen/nomgen.go | 54 ++++++++++++++++++++++++++++++++++------- types/list.go | 4 ++++ types/list_test.go | 11 +++++++++ types/map.go | 4 ++++ types/map_test.go | 10 ++++++++ types/set_test.go | 10 ++++++++ 7 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 nomgen/map.tmpl diff --git a/nomgen/map.tmpl b/nomgen/map.tmpl new file mode 100644 index 0000000000..a62ea96013 --- /dev/null +++ b/nomgen/map.tmpl @@ -0,0 +1,60 @@ +// {{.StructName}} + +type {{.StructName}} struct { + m types.Map +} + +type {{.StructName}}IterCallback (func(k {{.KeyName}}, v {{.ValueName}}) (stop bool)) + +func New{{.StructName}}() {{.StructName}} { + return {{.StructName}}{types.NewMap()} +} + +func {{.StructName}}FromVal(p types.Value) {{.StructName}} { + return {{.StructName}}{p.(types.Map)} +} + +func (m {{.StructName}}) NomsValue() types.Map { + return m.m +} + +func (m {{.StructName}}) Equals(p {{.StructName}}) bool { + return m.m.Equals(p.m) +} + +func (m {{.StructName}}) Ref() ref.Ref { + return m.m.Ref() +} + +func (m {{.StructName}}) Empty() bool { + return m.m.Empty() +} + +func (m {{.StructName}}) Len() uint64 { + return m.m.Len() +} + +func (m {{.StructName}}) Has(p {{.KeyName}}) bool { + return m.m.Has(p{{toVal .KeyName}}) +} + +func (m {{.StructName}}) Get(p {{.KeyName}}) {{.ValueName}} { + return {{fromVal .ValueName}}(m.m.Get(p{{toVal .KeyName}})) +} + +func (m {{.StructName}}) Set(k {{.KeyName}}, v {{.ValueName}}) {{.StructName}} { + return {{fromVal .StructName}}(m.m.Set(k{{toVal .KeyName}}, v{{toVal .ValueName}})) +} + +// TODO: Implement SetM? + +func (m {{.StructName}}) Remove(p {{.KeyName}}) {{.StructName}} { + return {{fromVal .StructName}}(m.m.Remove(p{{toVal .KeyName}})) +} + +func (m {{.StructName}}) Iter(cb {{.StructName}}IterCallback) { + m.m.Iter(func(k, v types.Value) bool { + return cb({{fromVal .KeyName}}(k), {{fromVal .ValueName}}(v)) + }) +} + diff --git a/nomgen/nomgen.go b/nomgen/nomgen.go index 62c25af492..0c0f4bbbbb 100644 --- a/nomgen/nomgen.go +++ b/nomgen/nomgen.go @@ -18,6 +18,7 @@ var ( fieldTempl = readTemplate("field.tmpl") headerTmpl = readTemplate("header.tmpl") listTempl = readTemplate("list.tmpl") + mapTempl = readTemplate("map.tmpl") setTempl = readTemplate("set.tmpl") structTempl = readTemplate("struct.tmpl") ) @@ -92,14 +93,17 @@ func readTemplate(name string) *template.Template { func (ng *NG) writeType(val types.Map) { typ := val.Get(types.NewString("$type")).(types.String).String() switch typ { - case "noms.StructDef": - ng.writeStruct(val) + case "noms.ListDef": + ng.writeList(val) + return + case "noms.MapDef": + ng.writeMap(val) return case "noms.SetDef": ng.writeSet(val) return - case "noms.ListDef": - ng.writeList(val) + case "noms.StructDef": + ng.writeStruct(val) return } Chk.Fail(fmt.Sprintf("Unexpected typedef: %+v", val)) @@ -135,6 +139,25 @@ func (ng *NG) writeList(val types.Map) { listTempl.Execute(ng.w, data) } +func (ng *NG) writeMap(val types.Map) { + key := val.Get(types.NewString("key")) + ng.addType(key) + valueName := val.Get(types.NewString("value")) + ng.addType(valueName) + + data := struct { + StructName string + KeyName string + ValueName string + }{ + getGoTypeName(val), + getGoTypeName(key), + getGoTypeName(valueName), + } + + mapTempl.Execute(ng.w, data) +} + func (ng *NG) writeStruct(val types.Map) { structName := getGoTypeName(val) structTempl.Execute(ng.w, struct { @@ -171,23 +194,36 @@ func (ng *NG) writeField(structName, fieldName string, typeDef types.Value) { } func getGoTypeName(typeDef types.Value) string { + typeName := getGoStructName(typeDef) + switch typeDef.(type) { + case types.String: + return fmt.Sprintf("types.%s", typeName) + } + return typeName +} + +func getGoStructName(typeDef types.Value) string { switch typeDef := typeDef.(type) { case types.String: name := typeDef.String() switch name { case "bool", "int16", "int32", "int64", "uint16", "uint32", "uint64", "float32", "float64", "blob", "string", "set", "map", "value": - return fmt.Sprintf("types.%s", strings.Title(typeDef.String())) + return strings.Title(typeDef.String()) } Chk.Fail("unexpected noms type name: %s", name) case types.Map: typ := typeDef.Get(types.NewString("$type")).(types.String).String() switch typ { + case "noms.ListDef": + return fmt.Sprintf("%sList", getGoStructName(typeDef.Get(types.NewString("elem")))) + case "noms.MapDef": + return fmt.Sprintf("%s%sMap", + getGoStructName(typeDef.Get(types.NewString("key"))), + getGoStructName(typeDef.Get(types.NewString("value")))) + case "noms.SetDef": + return fmt.Sprintf("%sSet", getGoStructName(typeDef.Get(types.NewString("elem")))) case "noms.StructDef": return typeDef.Get(types.NewString("$name")).(types.String).String() - case "noms.SetDef": - return fmt.Sprintf("%sSet", getGoTypeName(typeDef.Get(types.NewString("elem")))) - case "noms.ListDef": - return fmt.Sprintf("%sList", getGoTypeName(typeDef.Get(types.NewString("elem")))) } } Chk.Fail("Unexpected typeDef struct: %+v", typeDef) diff --git a/types/list.go b/types/list.go index ab9dbb9d40..75f0d16a2e 100644 --- a/types/list.go +++ b/types/list.go @@ -32,6 +32,10 @@ func (l List) Len() uint64 { return uint64(len(l.list)) } +func (l List) Empty() bool { + return l.Len() == uint64(0) +} + func (l List) Get(idx uint64) Value { v, err := l.list[idx].Deref(l.cs) // This is the kind of thing that makes me feel like hiding deref'ing is probably not the right idea. But we'll go with it for now. diff --git a/types/list_test.go b/types/list_test.go index 1d56d71a8f..36e4ec5455 100644 --- a/types/list_test.go +++ b/types/list_test.go @@ -17,6 +17,17 @@ func TestListLen(t *testing.T) { assert.Equal(uint64(3), l.Len()) } +func TestListEmpty(t *testing.T) { + assert := assert.New(t) + + l := NewList() + assert.True(l.Empty()) + l = l.Append(Bool(true)) + assert.False(l.Empty()) + l = l.Append(Bool(false), Bool(false)) + assert.False(l.Empty()) +} + func TestListGet(t *testing.T) { assert := assert.New(t) diff --git a/types/map.go b/types/map.go index 322a9f134b..e13a459bec 100644 --- a/types/map.go +++ b/types/map.go @@ -28,6 +28,10 @@ func (fm Map) Len() uint64 { return uint64(len(fm.m)) } +func (fm Map) Empty() bool { + return fm.Len() == uint64(0) +} + func (fm Map) Has(key Value) bool { idx := indexMapData(fm.m, key.Ref()) return idx < len(fm.m) && futureEqualsValue(fm.m[idx].key, key) diff --git a/types/map_test.go b/types/map_test.go index a2bc09ddc7..b49f2059c7 100644 --- a/types/map_test.go +++ b/types/map_test.go @@ -156,3 +156,13 @@ func TestMapNotStringKeys(t *testing.T) { } assert.Nil(m1.Get(Int32(42))) } + +func TestMapEmpty(t *testing.T) { + assert := assert.New(t) + m := NewMap() + assert.True(m.Empty()) + m = m.Set(Bool(false), NewString("hi")) + assert.False(m.Empty()) + m = m.Set(NewList(), NewMap()) + assert.False(m.Empty()) +} diff --git a/types/set_test.go b/types/set_test.go index ed68fa7a69..b0e7ac02e8 100644 --- a/types/set_test.go +++ b/types/set_test.go @@ -16,6 +16,16 @@ func TestSetLen(t *testing.T) { assert.Equal(uint64(3), s3.Len()) } +func TestSetEmpty(t *testing.T) { + assert := assert.New(t) + s := NewSet() + assert.True(s.Empty()) + s = s.Insert(Bool(false)) + assert.False(s.Empty()) + s = s.Insert(Int32(42)) + assert.False(s.Empty()) +} + // BUG 98 func TestSetDuplicateInsert(t *testing.T) { assert := assert.New(t)