Add Map codegen

This commit is contained in:
Erik Arvidsson
2015-07-22 14:06:36 -07:00
parent 85b2292505
commit a3b3bb1090
7 changed files with 144 additions and 9 deletions

60
nomgen/map.tmpl Normal file
View File

@@ -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))
})
}

View File

@@ -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)

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)

View File

@@ -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())
}

View File

@@ -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)