From 0005e23011d7491220fb040928ca13123ef30bcb Mon Sep 17 00:00:00 2001 From: Cory Slep Date: Thu, 3 Jan 2019 21:36:10 +0100 Subject: [PATCH] Hook up LessThan for properties. --- tools/exp/props/funcprop.go | 66 ++++++++++++++++++++++++++++++++-- tools/exp/props/nonfuncprop.go | 39 +++++++++++++++++++- tools/exp/props/property.go | 2 +- tools/exp/props/type.go | 1 + 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/tools/exp/props/funcprop.go b/tools/exp/props/funcprop.go index 2b7865e..ce75d2f 100644 --- a/tools/exp/props/funcprop.go +++ b/tools/exp/props/funcprop.go @@ -388,7 +388,6 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co // singleTypeDef generates a special-case simplified API for a functional // property that can only be a single Kind of value. func (p *FunctionalPropertyGenerator) singleTypeDef() *codegen.Struct { - // TODO: Comparison LessThan method var comment jen.Code var kindMembers []jen.Code if p.Kinds[0].Nilable { @@ -554,13 +553,32 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method { clearComment, )) } + // LessThan Method + // LessFn is nil case -- call comparison Less method directly on the LHS + // TODO: Move this logic to a Kind method (see nonfuncprop.go too) + lessCall := jen.Id(codegen.This()).Dot(compareLessMethod).Call(jen.Id("o")) + if p.Kinds[0].LessFn != nil { + // LessFn is indeed a function -- call this function + lessCall = p.Kinds[0].LessFn.Clone().Call( + jen.Id(codegen.This()), + jen.Id("o"), + ) + } + methods = append(methods, codegen.NewCommentedValueMethod( + p.GetPrivatePackage().Path(), + compareLessMethod, + p.StructName(), + []jen.Code{jen.Id("o").Id(p.InterfaceName())}, + []jen.Code{jen.Bool()}, + []jen.Code{jen.Return(lessCall)}, + jen.Commentf("%s compares two instances of this property with an arbitrary but stable comparison.", compareLessMethod), + )) return methods } // multiTypeDef generates an API for a functional property that can be multiple // Kinds of value. func (p *FunctionalPropertyGenerator) multiTypeDef() *codegen.Struct { - // TODO: Comparison LessThan method kindMembers := make([]jen.Code, 0, len(p.Kinds)) for i, kind := range p.Kinds { if kind.Nilable { @@ -757,6 +775,50 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method { getComment, )) } + // LessThan Method + lessCode := jen.Empty().Add( + jen.Id("idx1").Op(":=").Id(codegen.This()).Dot(kindIndexMethod).Call().Line(), + jen.Id("idx2").Op(":=").Id("o").Dot(kindIndexMethod).Call().Line(), + jen.If(jen.Id("idx1").Op("<").Id("idx2")).Block( + jen.Return(jen.True()), + ).Else().If(jen.Id("idx1").Op(">").Id("idx2")).Block( + jen.Return(jen.False()), + )) + for i, kind := range p.Kinds { + // LessFn is nil case -- call comparison Less method directly on the LHS + // TODO: Move this logic to a Kind method (see nonfuncprop.go too) + if p.Kinds[i].LessFn == nil { + lessCode.Add( + jen.Else().If( + jen.Id(codegen.This()).Dot(p.isMethodName(i)).Call(), + ).Block( + jen.Return(jen.Id(codegen.This()).Dot(p.getFnName(i)).Call().Dot(compareLessMethod).Call(jen.Id("o").Dot(p.getFnName(i)).Call())))) + } else { + // LessFn is indeed a function -- call this function + lessCode.Add( + jen.Else().If( + jen.Id(codegen.This()).Dot(p.isMethodName(i)).Call(), + ).Block( + kind.LessFn.Clone().Call( + jen.Id(codegen.This()).Dot(p.getFnName(i)).Call(), + jen.Id("o").Dot(p.getFnName(i)).Call(), + ), + )) + } + } + methods = append(methods, codegen.NewCommentedValueMethod( + p.GetPrivatePackage().Path(), + compareLessMethod, + p.StructName(), + []jen.Code{jen.Id("o").Id(p.InterfaceName())}, + []jen.Code{jen.Bool()}, + []jen.Code{ + lessCode, + // TODO: Unknown member comparison. + jen.Return(jen.False()), + }, + jen.Commentf("%s compares two instances of this property with an arbitrary but stable comparison.", compareLessMethod), + )) return methods } diff --git a/tools/exp/props/nonfuncprop.go b/tools/exp/props/nonfuncprop.go index 14f79b9..8482d5d 100644 --- a/tools/exp/props/nonfuncprop.go +++ b/tools/exp/props/nonfuncprop.go @@ -155,6 +155,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { less.Else() } // LessFn is nil case -- call comparison Less method directly on the LHS. + // TODO: Move this logic to a Kind method (see funcprop.go too) lessCall := jen.Id("lhs").Dot(compareLessMethod).Call(jen.Id("rhs")) if kind.LessFn != nil { // LessFn is indeed a function -- call this function @@ -280,7 +281,43 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { ), }, jen.Commentf("%s computes an arbitrary value for indexing this kind of value.", kindIndexMethod))) - // TODO: Comparison LessThan method + // LessThan Method + lessCode := jen.Empty().Add( + jen.Id("l1").Op(":=").Id(codegen.This()).Dot(lenMethod).Call().Line(), + jen.Id("l2").Op(":=").Id("o").Dot(lenMethod).Call().Line(), + jen.Id("l").Op(":=").Id("l1").Line(), + jen.If( + jen.Id("l2").Op("<").Id("l1"), + ).Block( + jen.Id("l").Op("=").Id("l2"), + )) + methods = append(methods, codegen.NewCommentedValueMethod( + p.GetPrivatePackage().Path(), + compareLessMethod, + p.StructName(), + []jen.Code{jen.Id("o").Id(p.InterfaceName())}, + []jen.Code{jen.Bool()}, + []jen.Code{ + lessCode, + jen.For( + jen.Id("i").Op(":=").Lit(0), + jen.Id("i").Op("<").Id("l"), + jen.Id("i").Op("++"), + ).Block( + jen.If( + jen.Id(codegen.This()).Index(jen.Id("i")).Dot(compareLessMethod).Call(jen.Id("o").Index(jen.Id("i"))), + ).Block( + jen.Return(jen.True()), + ).Else().If( + jen.Id("o").Index(jen.Id("i")).Dot(compareLessMethod).Call(jen.Id(codegen.This()).Index(jen.Id("i"))), + ).Block( + jen.Return(jen.False()), + ), + ), + jen.Return(jen.Id("l1").Op("<").Id("l2")), + }, + jen.Commentf("%s compares two instances of this property with an arbitrary but stable comparison.", compareLessMethod), + )) return methods } diff --git a/tools/exp/props/property.go b/tools/exp/props/property.go index 9be5159..d7ed297 100644 --- a/tools/exp/props/property.go +++ b/tools/exp/props/property.go @@ -131,7 +131,7 @@ func (p *PropertyGenerator) StructName() string { return fmt.Sprintf("%sProperty", p.Name.CamelName) } -// InterfaceNAme returns the interface name of the property type. +// InterfaceName returns the interface name of the property type. func (p *PropertyGenerator) InterfaceName() string { return fmt.Sprintf("%sInterface", p.StructName()) } diff --git a/tools/exp/props/type.go b/tools/exp/props/type.go index 96dfb8e..e45346b 100644 --- a/tools/exp/props/type.go +++ b/tools/exp/props/type.go @@ -317,6 +317,7 @@ func (t *TypeGenerator) members() (members []jen.Code) { for _, property := range p { members = append(members, jen.Id(t.memberName(property)).Qual(property.GetPublicPackage().Path(), property.InterfaceName())) } + // TODO: Unknown member return }