Skip to content

Instantly share code, notes, and snippets.

@CAFxX
Created November 16, 2022 08:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CAFxX/08e23aee1407655f06cf9eec379a204a to your computer and use it in GitHub Desktop.
Save CAFxX/08e23aee1407655f06cf9eec379a204a to your computer and use it in GitHub Desktop.
Generate objects with optional methods (Golang)
package main
import "fmt"
func genOptIface(name string, opt ...string) {
if len(opt) == 0 {
panic("zero opt types")
}
if len(opt) > 10 {
panic("too many opt types")
}
iter := func(pre, iter, post func(int)) {
for idx := 1; idx < 1<<len(opt); idx++ {
if pre != nil {
pre(idx)
}
for j := 0; j < len(opt); j++ {
if 1<<j&idx != 0 {
if iter != nil {
iter(j)
}
}
}
if post != nil {
post(idx)
}
}
}
fmt.Printf("func gen%s(types ...any) any {\n", name)
iter(
func(idx int) { fmt.Printf("type %s%d struct {\n", name, idx) },
func(j int) { fmt.Println(opt[j]) },
func(_ int) { fmt.Println("}") },
)
fmt.Println("var idx int")
for _, t := range opt {
fmt.Printf("var val%[1]s %[1]s\n", t)
}
fmt.Println(`
for _, t := range types {
switch t := t.(type) {
default: panic("unknown type")
`)
for j, t := range opt {
fmt.Printf(`
case %[1]s:
idx += 1<<%[2]d
val%[1]s = t
`, t, j)
}
fmt.Println(`
}
}
`)
fmt.Println(`
switch idx {
default: panic("unreacheable")
`)
iter(
func(idx int) { fmt.Printf("case %[1]d: \n return %[2]s%[1]d{ \n", idx, name) },
func(j int) { fmt.Printf("%[1]s: val%[1]s,\n", opt[j]) },
func(_ int) { fmt.Println("}") },
)
fmt.Println(`
}
`)
}
func main() {
genOptIface("x", "foo", "bar", "baz")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment