package main import ( "fmt" "strings" ) func main() { f := GenerateBenchmarkFunc() print(f) } var ( ExprOR = "ExprOR" Smaller = "Smaller" First = "First" Literal = "Literal" NoMatch = "NoMatch" SwitchCase = "SwitchCase" GenericIs = "GenericIs" Larger = "Larger" Middle = "Middle" Last = "Last" Const = "Const" Var = "Var" Method = "Method" ) const ( noMatchSmallChar = `x` noMatchLargeChar = `-` firstSmallChar = ` ` midSmallChar = `\t` lastSmallChar = `\n` firstLargeChar = `a` midLargeChar = `j` lastLargeChar = `z` ) func GenerateBenchmark(sb *strings.Builder, factors Factors, depth int) { var expr string list := strings.Join(factors, ", ") sb.WriteString(tabs(depth) + fmt.Sprintf("// Factors: %s\n", list)) switch strings.Join(factors, "") { case Smaller + ExprOR + First + Literal: expr = fmt.Sprintf(`exprOR('%s')`, firstSmallChar) case Smaller + SwitchCase + First + Literal: expr = fmt.Sprintf(`switchCase('%s')`, firstSmallChar) case Smaller + GenericIs + First + Literal: expr = fmt.Sprintf(`genericIs('%s')`, firstSmallChar) case Smaller + ExprOR + Middle + Literal: expr = fmt.Sprintf(`exprOR('%s')`, midSmallChar) case Smaller + SwitchCase + Middle + Literal: expr = fmt.Sprintf(`switchCase('%s')`, midSmallChar) case Smaller + GenericIs + Middle + Literal: expr = fmt.Sprintf(`genericIs('%s')`, midSmallChar) case Smaller + ExprOR + Last + Literal: expr = fmt.Sprintf(`exprOR('%s')`, lastSmallChar) case Smaller + SwitchCase + Last + Literal: expr = fmt.Sprintf(`switchCase('%s')`, lastSmallChar) case Smaller + GenericIs + Last + Literal: expr = fmt.Sprintf(`genericIs('%s')`, lastSmallChar) case Smaller + ExprOR + NoMatch + Literal: expr = fmt.Sprintf(`exprOR('%s')`, noMatchSmallChar) case Smaller + SwitchCase + NoMatch + Literal: expr = fmt.Sprintf(`switchCase('%s')`, noMatchSmallChar) case Smaller + GenericIs + NoMatch + Literal: expr = fmt.Sprintf(`genericIs('%s')`, noMatchSmallChar) case Smaller + ExprOR + First + Const: expr = `exprOR(firstSmallCharConst)` case Smaller + SwitchCase + First + Const: expr = `switchCase(firstSmallCharConst)` case Smaller + GenericIs + First + Const: expr = `genericIs(firstSmallCharConst)` case Smaller + ExprOR + Middle + Const: expr = `exprOR(midSmallCharConst)` case Smaller + SwitchCase + Middle + Const: expr = `switchCase(midSmallCharConst)` case Smaller + GenericIs + Middle + Const: expr = `genericIs(midSmallCharConst)` case Smaller + ExprOR + Last + Const: expr = `exprOR(lastSmallCharConst)` case Smaller + SwitchCase + Last + Const: expr = `switchCase(lastSmallCharConst)` case Smaller + GenericIs + Last + Const: expr = `genericIs(lastSmallCharConst)` case Smaller + ExprOR + NoMatch + Const: expr = `exprOR(noMatchSmallCharConst)` case Smaller + SwitchCase + NoMatch + Const: expr = `switchCase(noMatchSmallCharConst)` case Smaller + GenericIs + NoMatch + Const: expr = `genericIs(noMatchSmallCharConst)` case Smaller + ExprOR + First + Var: expr = `exprOR(firstSmallCharVar)` case Smaller + SwitchCase + First + Var: expr = `switchCase(firstSmallCharVar)` case Smaller + GenericIs + First + Var: expr = `genericIs(firstSmallCharVar)` case Smaller + ExprOR + Middle + Var: expr = `exprOR(midSmallCharVar)` case Smaller + SwitchCase + Middle + Var: expr = `switchCase(midSmallCharVar)` case Smaller + GenericIs + Middle + Var: expr = `genericIs(midSmallCharVar)` case Smaller + ExprOR + Last + Var: expr = `exprOR(lastSmallCharVar)` case Smaller + SwitchCase + Last + Var: expr = `switchCase(lastSmallCharVar)` case Smaller + GenericIs + Last + Var: expr = `genericIs(lastSmallCharVar)` case Smaller + ExprOR + NoMatch + Var: expr = `exprOR(noMatchSmallCharVar)` case Smaller + SwitchCase + NoMatch + Var: expr = `switchCase(noMatchSmallCharVar)` case Smaller + GenericIs + NoMatch + Var: expr = `genericIs(noMatchSmallCharVar)` case Smaller + ExprOR + First + Method: expr = `exprORMethod(firstLex)` case Smaller + SwitchCase + First + Method: expr = `switchCaseMethod(firstLex)` case Smaller + GenericIs + First + Method: expr = `genericIsMethod(firstLex)` case Smaller + ExprOR + Middle + Method: expr = `exprORMethod(midLex)` case Smaller + SwitchCase + Middle + Method: expr = `switchCaseMethod(midLex)` case Smaller + GenericIs + Middle + Method: expr = `genericIsMethod(midLex)` case Smaller + ExprOR + Last + Method: expr = `exprORMethod(lastLex)` case Smaller + SwitchCase + Last + Method: expr = `switchCaseMethod(lastLex)` case Smaller + GenericIs + Last + Method: expr = `genericIsMethod(lastLex)` case Smaller + ExprOR + NoMatch + Method: expr = `exprORMethod(noMatchLex)` case Smaller + SwitchCase + NoMatch + Method: expr = `switchCaseMethod(noMatchLex)` case Smaller + GenericIs + NoMatch + Method: expr = `genericIsMethod(noMatchLex)` case Larger + ExprOR + First + Literal: expr = fmt.Sprintf(`exprORLarger('%s')`, firstLargeChar) case Larger + SwitchCase + First + Literal: expr = fmt.Sprintf(`switchCaseLarger('%s')`, firstLargeChar) case Larger + GenericIs + First + Literal: expr = fmt.Sprintf(`genericIsLarger('%s')`, firstLargeChar) case Larger + ExprOR + Middle + Literal: expr = fmt.Sprintf(`exprORLarger('%s')`, midLargeChar) case Larger + SwitchCase + Middle + Literal: expr = fmt.Sprintf(`switchCaseLarger('%s')`, midLargeChar) case Larger + GenericIs + Middle + Literal: expr = fmt.Sprintf(`genericIsLarger('%s')`, midLargeChar) case Larger + ExprOR + Last + Literal: expr = fmt.Sprintf(`exprORLarger('%s')`, lastLargeChar) case Larger + SwitchCase + Last + Literal: expr = fmt.Sprintf(`switchCaseLarger('%s')`, lastLargeChar) case Larger + GenericIs + Last + Literal: expr = fmt.Sprintf(`genericIsLarger('%s')`, lastLargeChar) case Larger + ExprOR + NoMatch + Literal: expr = fmt.Sprintf(`exprORLarger('%s')`, noMatchLargeChar) case Larger + SwitchCase + NoMatch + Literal: expr = fmt.Sprintf(`switchCaseLarger('%s')`, noMatchLargeChar) case Larger + GenericIs + NoMatch + Literal: expr = fmt.Sprintf(`genericIsLarger('%s')`, noMatchLargeChar) case Larger + ExprOR + First + Const: expr = `exprORLarger(firstLargeCharConst)` case Larger + SwitchCase + First + Const: expr = `switchCaseLarger(firstLargeCharConst)` case Larger + GenericIs + First + Const: expr = `genericIsLarger(firstLargeCharConst)` case Larger + ExprOR + Middle + Const: expr = `exprORLarger(midLargeCharConst)` case Larger + SwitchCase + Middle + Const: expr = `switchCaseLarger(midLargeCharConst)` case Larger + GenericIs + Middle + Const: expr = `genericIsLarger(midLargeCharConst)` case Larger + ExprOR + Last + Const: expr = `exprORLarger(lastLargeCharConst)` case Larger + SwitchCase + Last + Const: expr = `switchCaseLarger(lastLargeCharConst)` case Larger + GenericIs + Last + Const: expr = `genericIsLarger(lastLargeCharConst)` case Larger + ExprOR + NoMatch + Const: expr = `exprORLarger(noMatchLargeCharConst)` case Larger + SwitchCase + NoMatch + Const: expr = `switchCaseLarger(noMatchLargeCharConst)` case Larger + GenericIs + NoMatch + Const: expr = `genericIsLarger(noMatchLargeCharConst)` case Larger + ExprOR + First + Var: expr = `exprORLarger(firstLargeCharVar)` case Larger + SwitchCase + First + Var: expr = `switchCaseLarger(firstLargeCharVar)` case Larger + GenericIs + First + Var: expr = `genericIsLarger(firstLargeCharVar)` case Larger + ExprOR + Middle + Var: expr = `exprORLarger(midLargeCharVar)` case Larger + SwitchCase + Middle + Var: expr = `switchCaseLarger(midLargeCharVar)` case Larger + GenericIs + Middle + Var: expr = `genericIsLarger(midLargeCharVar)` case Larger + ExprOR + Last + Var: expr = `exprORLarger(lastLargeCharVar)` case Larger + SwitchCase + Last + Var: expr = `switchCaseLarger(lastLargeCharVar)` case Larger + GenericIs + Last + Var: expr = `genericIsLarger(lastLargeCharVar)` case Larger + ExprOR + NoMatch + Var: expr = `exprORLarger(noMatchLargeCharVar)` case Larger + SwitchCase + NoMatch + Var: expr = `switchCaseLarger(noMatchLargeCharVar)` case Larger + GenericIs + NoMatch + Var: expr = `genericIsLarger(noMatchLargeCharVar)` case Larger + ExprOR + First + Method: expr = `exprORMethodLarger(firstLex)` case Larger + SwitchCase + First + Method: expr = `switchCaseMethodLarger(firstLex)` case Larger + GenericIs + First + Method: expr = `genericIsMethodLarger(firstLex)` case Larger + ExprOR + Middle + Method: expr = `exprORMethodLarger(midLex)` case Larger + SwitchCase + Middle + Method: expr = `switchCaseMethodLarger(midLex)` case Larger + GenericIs + Middle + Method: expr = `genericIsMethodLarger(midLex)` case Larger + ExprOR + Last + Method: expr = `exprORMethodLarger(lastLex)` case Larger + SwitchCase + Last + Method: expr = `switchCaseMethodLarger(lastLex)` case Larger + GenericIs + Last + Method: expr = `genericIsMethodLarger(lastLex)` case Larger + ExprOR + NoMatch + Method: expr = `exprORMethodLarger(noMatchLex)` case Larger + SwitchCase + NoMatch + Method: expr = `switchCaseMethodLarger(noMatchLex)` case Larger + GenericIs + NoMatch + Method: expr = `genericIsMethodLarger(noMatchLex)` default: expr = `""` } sb.WriteString(fmt.Sprintf("%s_ = %s\n", tabs(depth), expr)) } var factorNames = [][]string{ {Smaller, Larger}, {ExprOR, SwitchCase, GenericIs}, {First, Middle, Last, NoMatch}, {Literal, Const, Var, Method}, } const ( RunFormat = `%sb.Run("%s", func(b *testing.B) {%s` RunFormatClose = `%s})%s` LoopFormat = `%sfor b.Loop() {%s` LoopFormatClose = `%s}%s` ) var tabs = func(n int) string { return strings.Repeat("\t", n) } func GenerateBenchmarkFunc() string { var sb = strings.Builder{} sb.WriteString("func BenchmarkValueMembership(b *testing.B) {\n") GenerateBenchmarkRun(&sb, factorNames[0], 1) sb.WriteString("}\n") return sb.String() } type Factors []string func (fs Factors) Has(factors ...string) (ok bool) { ok = true for _, factor := range factors { for _, f := range fs { if factor != f { goto end } } } end: return ok } var benchmarkFactors = make(Factors, len(factorNames)) func GenerateBenchmarkRun(sb *strings.Builder, factors []string, depth int) { for _, factor := range factors { sb.WriteString(fmt.Sprintf(RunFormat, tabs(depth), factor, "\n")) benchmarkFactors[depth-1] = factor if depth < len(factorNames) { GenerateBenchmarkRun(sb, factorNames[depth], depth+1) } else { sb.WriteString(fmt.Sprintf(LoopFormat, tabs(depth+1), "\n")) GenerateBenchmark(sb, benchmarkFactors, depth+2) sb.WriteString(fmt.Sprintf(LoopFormatClose, tabs(depth+1), "\n")) } sb.WriteString(fmt.Sprintf(RunFormatClose, tabs(depth), "\n")) } }