func makeCommitType(valueType *types.Type, parentsValueTypes []*types.Type, metaType *types.Type, parentsMetaTypes []*types.Type) *types.Type { tmp := make([]*types.Type, len(parentsValueTypes), len(parentsValueTypes)+1) copy(tmp, parentsValueTypes) tmp = append(tmp, valueType) parentsValueUnionType := types.MakeUnionType(tmp...) tmp2 := make([]*types.Type, len(parentsMetaTypes), len(parentsMetaTypes)+1) copy(tmp2, parentsMetaTypes) tmp2 = append(tmp2, metaType) parentsMetaUnionType := types.MakeUnionType(tmp2...) fieldNames := []string{MetaField, ParentsField, ValueField} var parentsType *types.Type if parentsValueUnionType.Equals(valueType) && parentsMetaUnionType.Equals(metaType) { parentsType = types.MakeSetType(types.MakeRefType(types.MakeCycleType(0))) } else { parentsType = types.MakeSetType(types.MakeRefType( types.MakeStructType("Commit", fieldNames, []*types.Type{ parentsMetaUnionType, types.MakeSetType(types.MakeRefType(types.MakeCycleType(0))), parentsValueUnionType, }))) } fieldTypes := []*types.Type{ metaType, parentsType, valueType, } return types.MakeStructType("Commit", fieldNames, fieldTypes) }
func TestNewCommit(t *testing.T) { assert := assert.New(t) commitFieldNames := []string{MetaField, ParentsField, ValueField} assertTypeEquals := func(e, a *types.Type) { assert.True(a.Equals(e), "Actual: %s\nExpected %s", a.Describe(), e.Describe()) } commit := NewCommit(types.Number(1), types.NewSet(), types.EmptyStruct) at := commit.Type() et := types.MakeStructType("Commit", commitFieldNames, []*types.Type{ types.EmptyStructType, types.MakeSetType(types.MakeRefType(types.MakeCycleType(0))), types.NumberType, }) assertTypeEquals(et, at) // Commiting another Number commit2 := NewCommit(types.Number(2), types.NewSet(types.NewRef(commit)), types.EmptyStruct) at2 := commit2.Type() et2 := et assertTypeEquals(et2, at2) // Now commit a String commit3 := NewCommit(types.String("Hi"), types.NewSet(types.NewRef(commit2)), types.EmptyStruct) at3 := commit3.Type() et3 := types.MakeStructType("Commit", commitFieldNames, []*types.Type{ types.EmptyStructType, types.MakeSetType(types.MakeRefType(types.MakeStructType("Commit", commitFieldNames, []*types.Type{ types.EmptyStructType, types.MakeSetType(types.MakeRefType(types.MakeCycleType(0))), types.MakeUnionType(types.NumberType, types.StringType), }))), types.StringType, }) assertTypeEquals(et3, at3) // Now commit a String with MetaInfo meta := types.NewStruct("Meta", types.StructData{"date": types.String("some date"), "number": types.Number(9)}) metaType := types.MakeStructType("Meta", []string{"date", "number"}, []*types.Type{types.StringType, types.NumberType}) assertTypeEquals(metaType, meta.Type()) commit4 := NewCommit(types.String("Hi"), types.NewSet(types.NewRef(commit2)), meta) at4 := commit4.Type() et4 := types.MakeStructType("Commit", commitFieldNames, []*types.Type{ metaType, types.MakeSetType(types.MakeRefType(types.MakeStructType("Commit", commitFieldNames, []*types.Type{ types.MakeUnionType(types.EmptyStructType, metaType), types.MakeSetType(types.MakeRefType(types.MakeCycleType(0))), types.MakeUnionType(types.NumberType, types.StringType), }))), types.StringType, }) assertTypeEquals(et4, at4) }
func init() { inodeType = types.MakeStructType("Inode", []string{"attr", "contents"}, []*types.Type{ types.MakeStructType("Attr", []string{"ctime", "gid", "mode", "mtime", "uid", "xattr"}, []*types.Type{types.NumberType, types.NumberType, types.NumberType, types.NumberType, types.NumberType, types.MakeMapType(types.StringType, types.BlobType)}), types.MakeUnionType(types.MakeStructType("Directory", []string{"entries"}, []*types.Type{ types.MakeMapType(types.StringType, types.MakeCycleType(1))}), types.MakeStructType("File", []string{"data"}, []*types.Type{types.MakeRefType(types.BlobType)}), types.MakeStructType("Symlink", []string{"targetPath"}, []*types.Type{types.StringType}), ), }) // Root around for some useful types. attrType = inodeType.Desc.(types.StructDesc).Field("attr") for _, elemType := range inodeType.Desc.(types.StructDesc).Field("contents").Desc.(types.CompoundDesc).ElemTypes { switch elemType.Desc.(types.StructDesc).Name { case "Directory": directoryType = elemType case "File": fileType = elemType case "Symlink": symlinkType = elemType } } fsType = types.MakeStructType("Filesystem", []string{"root"}, []*types.Type{inodeType}) }