SlideShare a Scribd company logo
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
for i in range(10):
print(i)
(1..100).each do |n|
print n
end
for (i in 1..4) print(i)
Generating Union types w/ Static Analysis
PROGRAMMING LANGUAGE
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
union types
union types
from go structs
with static analysis
union types
from go structs
with static analysis
function padLeft(value: string, padding: any) {
if (typeof padding === "number") {
//...
}
if (typeof padding === "string") {
//...
}
throw new Error("wat");
}
function padLeft(value: string, padding: any) {
if (typeof padding === "number") {
//...
}
if (typeof padding === "string") {
//...
}
throw new Error("wat");
}
type Padding = number | string;
function padLeft(value: string, padding: Padding) {
if (typeof padding === "number") {
//...
}
if (typeof padding === "string") {
//...
}
throw new Error("wat");
}
type Ordered interface {
int | float32 | ~string
}
type Ordered interface {
int | float32 | ~string
}
func GMin[T Ordered](x, y T) T {
if x < y {
return x
}
return y
}
—Golang Team
“…the new syntactic forms may only be used as
[generics] constraints. But it’s not hard to imagine how
explicitly type-constrained interfaces might be useful in
general.”
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
curl --header "Authorization: Bearer <token>" 
https://www.meetup.com/api/v1/profiles/me
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
1. Go source can’t express union types
2. API has union types
3. Docs/schema generated from source
// Code generated by cmd/genereate_input_mapping DO NOT EDIT.
package server
import (
"reflect"
"github.com/danielgtaylor/huma/v2"
"github.com/mosaic-avantos/avantos/internal/expression"
)
type ExpressionInput map[string]interface{}
func (e ExpressionInput) Schema(r huma.Registry) *huma.Schema {
r.RegisterTypeAlias(reflect.TypeFor[expression.Expression](), reflect.TypeOf(ExpressionInput{}))
// Create a discriminator schema
return &huma.Schema{
OneOf: []*huma.Schema{
r.Schema(reflect.TypeOf(expression.ActionComponentDataExpression{}), true, "actionComponentData"),
r.Schema(reflect.TypeOf(expression.ActionDataExpression{}), true, "actionData"),
r.Schema(reflect.TypeOf(expression.AggregateExpression{}), true, "aggregate"),
r.Schema(reflect.TypeOf(expression.AndExpression{}), true, "and"),
r.Schema(reflect.TypeOf(expression.BinaryExpression{}), true, "binary"),
r.Schema(reflect.TypeOf(expression.ClientOrganisationExpression{}), true, "clientOrganisation"),
r.Schema(reflect.TypeOf(expression.ColumnExpression{}), true, "column"),
r.Schema(reflect.TypeOf(expression.ExistsExpression{}), true, "exists"),
r.Schema(reflect.TypeOf(expression.FormFieldExpression{}), true, "formField"),
r.Schema(reflect.TypeOf(expression.LiteralExpression{}), true, "literal"),
r.Schema(reflect.TypeOf(expression.NotExpression{}), true, "not"),
r.Schema(reflect.TypeOf(expression.OrExpression{}), true, "or"),
r.Schema(reflect.TypeOf(expression.PropertyExpression{}), true, "property"),
},
Discriminator: &huma.Discriminator{
PropertyName: "type",
Mapping: map[string]string{
"action_component_data": "#/components/schemas/ActionComponentDataExpression",
"action_data": "#/components/schemas/ActionDataExpression",
"aggregate": "#/components/schemas/AggregateExpression",
"and": "#/components/schemas/AndExpression",
"binary": "#/components/schemas/BinaryExpression",
"client_organisation": "#/components/schemas/ClientOrganisationExpression",
"column": "#/components/schemas/ColumnExpression",
"exists": "#/components/schemas/ExistsExpression",
"form_field": "#/components/schemas/FormFieldExpression",
"literal": "#/components/schemas/LiteralExpression",
"not": "#/components/schemas/NotExpression",
"or": "#/components/schemas/OrExpression",
"property": "#/components/schemas/PropertyExpression",
},
},
}
}
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis
abstract syntax trees
abstract syntax trees
a s t
ast
func main() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "expression.go", nil, 0)
ast.Print(fset, f)
}
package main
func main() {
println("Hello, World!")
}
*ast.File {
Package: 2:1
Name: *ast.Ident {
. NamePos: 2:9
. Name: "main"
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
. . Body: *ast.BlockStmt {
. . . Lbrace: 3:13
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . . Rbrace: 5:1
. . }
. }
}
FileStart: 1:1
FileEnd: 5:3
Scope: *ast.Scope {
. Objects: map[string]*ast.Object (len = 1) {
. . "main": *(obj @ 11)
. }
}
Unresolved: []*ast.Ident (len = 1) {
. 0: *(obj @ 29)
}
GoVersion: ""
}
package main
func main() {
println("Hello, World!")
}
*ast.File {
Package: 2:1
Name: *ast.Ident {
. NamePos: 2:9
. Name: "main"
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
. . Body: *ast.BlockStmt {
. . . Lbrace: 3:13
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . . Rbrace: 5:1
. . }
. }
}
FileStart: 1:1
FileEnd: 5:3
Scope: *ast.Scope {
. Objects: map[string]*ast.Object (len = 1) {
. . "main": *(obj @ 11)
. }
}
Unresolved: []*ast.Ident (len = 1) {
. 0: *(obj @ 29)
}
GoVersion: ""
}
package main
func main() {
println("Hello, World!")
}
*ast.File {
Package: 2:1
Name: *ast.Ident {
. NamePos: 2:9
. Name: "main"
}
}
package main
func main() {
println("Hello, World!")
}
*ast.File {
Package: 2:1
Name: *ast.Ident {
. NamePos: 2:9
. Name: "main"
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
. . Body: *ast.BlockStmt {
. . . Lbrace: 3:13
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . . Rbrace: 5:1
. . }
. }
}
FileStart: 1:1
FileEnd: 5:3
Scope: *ast.Scope {
. Objects: map[string]*ast.Object (len = 1) {
. . "main": *(obj @ 11)
. }
}
Unresolved: []*ast.Ident (len = 1) {
. 0: *(obj @ 29)
}
GoVersion: ""
}
package main
func main() {
println("Hello, World!")
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
package main
func main() {
println("Hello, World!")
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
package main
func main() {
println("Hello, World!")
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
package main
func main() {
println("Hello, World!")
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
package main
func main() {
println("Hello, World!")
}
*ast.File {
Package: 2:1
Name: *ast.Ident {
. NamePos: 2:9
. Name: "main"
}
Decls: []ast.Decl (len = 1) {
. 0: *ast.FuncDecl {
. . Name: *ast.Ident {
. . . NamePos: 3:6
. . . Name: "main"
. . . Obj: *ast.Object {
. . . . Kind: func
. . . . Name: "main"
. . . . Decl: *(obj @ 7)
. . . }
. . }
. . Type: *ast.FuncType {
. . . Func: 3:1
. . . Params: *ast.FieldList {
. . . . Opening: 3:10
. . . . Closing: 3:11
. . . }
. . }
. . Body: *ast.BlockStmt {
. . . Lbrace: 3:13
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . . Rbrace: 5:1
. . }
. }
}
FileStart: 1:1
FileEnd: 5:3
Scope: *ast.Scope {
. Objects: map[string]*ast.Object (len = 1) {
. . "main": *(obj @ 11)
. }
}
Unresolved: []*ast.Ident (len = 1) {
. 0: *(obj @ 29)
}
GoVersion: ""
}
package main
func main() {
println("Hello, World!")
}
. . Body: *ast.BlockStmt {
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . }
. }
package main
func main() {
println("Hello, World!")
}
. . Body: *ast.BlockStmt {
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . }
. }
package main
func main() {
println("Hello, World!")
}
. . Body: *ast.BlockStmt {
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . }
. }
package main
func main() {
println("Hello, World!")
}
. . Body: *ast.BlockStmt {
. . . List: []ast.Stmt (len = 1) {
. . . . 0: *ast.ExprStmt {
. . . . . X: *ast.CallExpr {
. . . . . . Fun: *ast.Ident {
. . . . . . . NamePos: 4:2
. . . . . . . Name: "println"
. . . . . . }
. . . . . . Lparen: 4:9
. . . . . . Args: []ast.Expr (len = 1) {
. . . . . . . 0: *ast.BasicLit {
. . . . . . . . ValuePos: 4:10
. . . . . . . . Kind: STRING
. . . . . . . . Value: ""Hello, World!""
. . . . . . . }
. . . . . . }
. . . . . . Ellipsis: -
. . . . . . Rparen: 4:25
. . . . . }
. . . . }
. . . }
. . }
. }
type Expression interface {
GetType() ExpressionType
//...
}
class AndExpression implements Expression {}
PROGRAMMING LANGUAGE
structured
type-system
137
LoC w/ comments
func inspectInterfaceMethodDecl(
f
*
ast.File,
methodNames []string,
inspector func(name, methodName string),
)
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
*ast.FuncDecl {
. . . Recv: *ast.FieldList {
. . . . List: []*ast.Field (len = 1) {
. . . . . 0: *ast.Field {
. . . . . . Names: []*ast.Ident (len = 1) {
. . . . . . . 0: *ast.Ident {
. . . . . . . . Name: "a"
. . . . . . . . Obj: *ast.Object {
. . . . . . . . . Kind: var
. . . . . . . . . Name: "a"
. . . . . . . . . Decl: *(obj @ 2039)
. . . . . . . . }
. . . . . . . }
. . . . . . }
. . . . . . Type: *ast.Ident {
. . . . . . . Name: "AndExpression"
. . . . . . . Obj: *(obj @ 48)
. . . . . . }
. . . . . }
. . . . }
. . . }
. . . Name: *ast.Ident {
. . . . Name: "GetExpressionEntityTypes"
. . . }
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
*ast.FuncDecl {
. . . Recv: *ast.FieldList {
. . . . List: []*ast.Field (len = 1) {
. . . . . 0: *ast.Field {
. . . . . . Names: []*ast.Ident (len = 1) {
. . . . . . . 0: *ast.Ident {
. . . . . . . . Name: "a"
. . . . . . . . Obj: *ast.Object {
. . . . . . . . . Kind: var
. . . . . . . . . Name: "a"
. . . . . . . . . Decl: *(obj @ 2039)
. . . . . . . . }
. . . . . . . }
. . . . . . }
. . . . . . Type: *ast.Ident {
. . . . . . . Name: "AndExpression"
. . . . . . . Obj: *(obj @ 48)
. . . . . . }
. . . . . }
. . . . }
. . . }
. . . Name: *ast.Ident {
. . . . Name: "GetExpressionEntityTypes"
. . . }
*ast.FuncDecl {
. . . Recv: *ast.FieldList {
. . . . List: []*ast.Field (len = 1) {
. . . . . 0: *ast.Field {
. . . . . . Names: []*ast.Ident (len = 1) {
. . . . . . . 0: *ast.Ident {
. . . . . . . . Name: "a"
. . . . . . . . Obj: *ast.Object {
. . . . . . . . . Kind: var
. . . . . . . . . Name: "a"
. . . . . . . . . Decl: *(obj @ 2039)
. . . . . . . . }
. . . . . . . }
. . . . . . }
. . . . . . Type: *ast.Ident {
. . . . . . . Name: "AndExpression"
. . . . . . . Obj: *(obj @ 48)
. . . . . . }
. . . . . }
. . . . }
. . . }
. . . Name: *ast.Ident {
. . . . Name: "GetExpressionEntityTypes"
. . . }
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
for _, decl := range f.Decls {
switch fDecl := decl.(type) {
case *ast.FuncDecl:
if slices.Contains(methodNames, fDecl.Name.Name) {
ast.Inspect(fDecl.Recv, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.Ident:
if x.Obj.Kind != ast.Var {
//...
}
}
return true
})
}
}
}
//go:generate go run ../../cmd/generate_expression_input
type Expression interface {
GetType() ExpressionType
//…
}
go generate
// Code generated by cmd/genereate_input_mapping DO NOT EDIT.
package server
import (
"reflect"
"github.com/danielgtaylor/huma/v2"
"github.com/mosaic-avantos/avantos/internal/expression"
)
type ExpressionInput map[string]interface{}
func (e ExpressionInput) Schema(r huma.Registry) *huma.Schema {
r.RegisterTypeAlias(reflect.TypeFor[expression.Expression](), reflect.TypeOf(ExpressionInput{}))
// Create a discriminator schema
return &huma.Schema{
OneOf: []*huma.Schema{
r.Schema(reflect.TypeOf(expression.ActionComponentDataExpression{}), true, "actionComponentData"),
r.Schema(reflect.TypeOf(expression.ActionDataExpression{}), true, "actionData"),
r.Schema(reflect.TypeOf(expression.AggregateExpression{}), true, "aggregate"),
r.Schema(reflect.TypeOf(expression.AndExpression{}), true, "and"),
r.Schema(reflect.TypeOf(expression.BinaryExpression{}), true, "binary"),
r.Schema(reflect.TypeOf(expression.ClientOrganisationExpression{}), true, "clientOrganisation"),
r.Schema(reflect.TypeOf(expression.ColumnExpression{}), true, "column"),
r.Schema(reflect.TypeOf(expression.ExistsExpression{}), true, "exists"),
r.Schema(reflect.TypeOf(expression.FormFieldExpression{}), true, "formField"),
r.Schema(reflect.TypeOf(expression.LiteralExpression{}), true, "literal"),
r.Schema(reflect.TypeOf(expression.NotExpression{}), true, "not"),
r.Schema(reflect.TypeOf(expression.OrExpression{}), true, "or"),
r.Schema(reflect.TypeOf(expression.PropertyExpression{}), true, "property"),
},
Discriminator: &huma.Discriminator{
PropertyName: "type",
Mapping: map[string]string{
"action_component_data": "#/components/schemas/ActionComponentDataExpression",
"action_data": "#/components/schemas/ActionDataExpression",
"aggregate": "#/components/schemas/AggregateExpression",
"and": "#/components/schemas/AndExpression",
"binary": "#/components/schemas/BinaryExpression",
"client_organisation": "#/components/schemas/ClientOrganisationExpression",
"column": "#/components/schemas/ColumnExpression",
"exists": "#/components/schemas/ExistsExpression",
"form_field": "#/components/schemas/FormFieldExpression",
"literal": "#/components/schemas/LiteralExpression",
"not": "#/components/schemas/NotExpression",
"or": "#/components/schemas/OrExpression",
"property": "#/components/schemas/PropertyExpression",
},
},
}
}
148
LoC w/ comments
Generating Union types w/ Static Analysis
Generating Union types w/ Static Analysis

More Related Content

PDF
My question is pretty simple, I just want to know how to call my ope.pdf
PDF
Introduction to Go for Java Programmers
PPTX
beginners_python_cheat_sheet_pcc_all (3).pptx
PDF
Help please, I have attached LinkedList.cpp and LinkedList.hPlease.pdf
DOCX
lab08build.bat@echo offclsset DRIVE_LETTER=1s.docx
PDF
Scala - en bedre og mere effektiv Java?
PDF
Writing a compiler in go
DOCX
Provide copy constructor- destructor- and assignment operator for the.docx
My question is pretty simple, I just want to know how to call my ope.pdf
Introduction to Go for Java Programmers
beginners_python_cheat_sheet_pcc_all (3).pptx
Help please, I have attached LinkedList.cpp and LinkedList.hPlease.pdf
lab08build.bat@echo offclsset DRIVE_LETTER=1s.docx
Scala - en bedre og mere effektiv Java?
Writing a compiler in go
Provide copy constructor- destructor- and assignment operator for the.docx

Similar to Generating Union types w/ Static Analysis (20)

PDF
Scala - en bedre Java?
PPT
2025pylab engineering 2025pylab engineering
PDF
Grammarware Memes
PDF
#include sstream #include linkylist.h #include iostream.pdf
PDF
The Ring programming language version 1.7 book - Part 25 of 196
KEY
連邦の白いヤツ 「Objective-C」
PDF
Python cheatsheet for beginners
PDF
1. python
PDF
Beginners python cheat sheet - Basic knowledge
 
PDF
Kotlin Advanced - Apalon Kotlin Sprint Part 3
PDF
Scala Paradigms
PDF
6. Generics. Collections. Streams
PDF
ハイブリッド言語Scalaを使う
PDF
The Ring programming language version 1.6 book - Part 36 of 189
PDF
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
PDF
Swift Study #7
PDF
Beginner's Python Cheat Sheet.pdf
PDF
beginners_python_cheat_sheet_pcc_all.pdf
PDF
beginners_python_cheat_sheet_pcc_all.pdf
DOCX
Game unleashedjavascript
Scala - en bedre Java?
2025pylab engineering 2025pylab engineering
Grammarware Memes
#include sstream #include linkylist.h #include iostream.pdf
The Ring programming language version 1.7 book - Part 25 of 196
連邦の白いヤツ 「Objective-C」
Python cheatsheet for beginners
1. python
Beginners python cheat sheet - Basic knowledge
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Scala Paradigms
6. Generics. Collections. Streams
ハイブリッド言語Scalaを使う
The Ring programming language version 1.6 book - Part 36 of 189
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
Swift Study #7
Beginner's Python Cheat Sheet.pdf
beginners_python_cheat_sheet_pcc_all.pdf
beginners_python_cheat_sheet_pcc_all.pdf
Game unleashedjavascript
Ad

More from K. Matthew Dupree (9)

PDF
intro-to-metaprogramming-in-r.pdf
PDF
Intro To Gradient Descent in Javascript
PDF
Dagger 2, 2 years later
PDF
An Introduction to RxJava
PDF
If Android Tests Could Talk
PDF
Writing testable android apps
PDF
Di and Dagger
PDF
Functional Testing for React Native Apps
PDF
Testable android apps
intro-to-metaprogramming-in-r.pdf
Intro To Gradient Descent in Javascript
Dagger 2, 2 years later
An Introduction to RxJava
If Android Tests Could Talk
Writing testable android apps
Di and Dagger
Functional Testing for React Native Apps
Testable android apps
Ad

Recently uploaded (20)

PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PPTX
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
PDF
A REACT POMODORO TIMER WEB APPLICATION.pdf
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PPTX
ai tools demonstartion for schools and inter college
PPTX
Mastering-Cybersecurity-The-Crucial-Role-of-Antivirus-Support-Services.pptx
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
L1 - Introduction to python Backend.pptx
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
System and Network Administraation Chapter 3
DOCX
The Five Best AI Cover Tools in 2025.docx
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
Materi_Pemrograman_Komputer-Looping.pptx
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Best Practices for Rolling Out Competency Management Software.pdf
PDF
System and Network Administration Chapter 2
PDF
AI in Product Development-omnex systems
PPTX
ISO 45001 Occupational Health and Safety Management System
PDF
top salesforce developer skills in 2025.pdf
2025 Textile ERP Trends: SAP, Odoo & Oracle
VVF-Customer-Presentation2025-Ver1.9.pptx
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
A REACT POMODORO TIMER WEB APPLICATION.pdf
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
ai tools demonstartion for schools and inter college
Mastering-Cybersecurity-The-Crucial-Role-of-Antivirus-Support-Services.pptx
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
L1 - Introduction to python Backend.pptx
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
System and Network Administraation Chapter 3
The Five Best AI Cover Tools in 2025.docx
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Materi_Pemrograman_Komputer-Looping.pptx
Understanding Forklifts - TECH EHS Solution
Best Practices for Rolling Out Competency Management Software.pdf
System and Network Administration Chapter 2
AI in Product Development-omnex systems
ISO 45001 Occupational Health and Safety Management System
top salesforce developer skills in 2025.pdf

Generating Union types w/ Static Analysis

  • 4. for i in range(10): print(i) (1..100).each do |n| print n end for (i in 1..4) print(i)
  • 11. union types from go structs with static analysis
  • 12. union types from go structs with static analysis
  • 13. function padLeft(value: string, padding: any) { if (typeof padding === "number") { //... } if (typeof padding === "string") { //... } throw new Error("wat"); }
  • 14. function padLeft(value: string, padding: any) { if (typeof padding === "number") { //... } if (typeof padding === "string") { //... } throw new Error("wat"); }
  • 15. type Padding = number | string; function padLeft(value: string, padding: Padding) { if (typeof padding === "number") { //... } if (typeof padding === "string") { //... } throw new Error("wat"); }
  • 16. type Ordered interface { int | float32 | ~string }
  • 17. type Ordered interface { int | float32 | ~string } func GMin[T Ordered](x, y T) T { if x < y { return x } return y }
  • 18. —Golang Team “…the new syntactic forms may only be used as [generics] constraints. But it’s not hard to imagine how explicitly type-constrained interfaces might be useful in general.”
  • 24. curl --header "Authorization: Bearer <token>" https://www.meetup.com/api/v1/profiles/me
  • 33. 1. Go source can’t express union types 2. API has union types 3. Docs/schema generated from source
  • 34. // Code generated by cmd/genereate_input_mapping DO NOT EDIT. package server import ( "reflect" "github.com/danielgtaylor/huma/v2" "github.com/mosaic-avantos/avantos/internal/expression" ) type ExpressionInput map[string]interface{} func (e ExpressionInput) Schema(r huma.Registry) *huma.Schema { r.RegisterTypeAlias(reflect.TypeFor[expression.Expression](), reflect.TypeOf(ExpressionInput{})) // Create a discriminator schema return &huma.Schema{ OneOf: []*huma.Schema{ r.Schema(reflect.TypeOf(expression.ActionComponentDataExpression{}), true, "actionComponentData"), r.Schema(reflect.TypeOf(expression.ActionDataExpression{}), true, "actionData"), r.Schema(reflect.TypeOf(expression.AggregateExpression{}), true, "aggregate"), r.Schema(reflect.TypeOf(expression.AndExpression{}), true, "and"), r.Schema(reflect.TypeOf(expression.BinaryExpression{}), true, "binary"), r.Schema(reflect.TypeOf(expression.ClientOrganisationExpression{}), true, "clientOrganisation"), r.Schema(reflect.TypeOf(expression.ColumnExpression{}), true, "column"), r.Schema(reflect.TypeOf(expression.ExistsExpression{}), true, "exists"), r.Schema(reflect.TypeOf(expression.FormFieldExpression{}), true, "formField"), r.Schema(reflect.TypeOf(expression.LiteralExpression{}), true, "literal"), r.Schema(reflect.TypeOf(expression.NotExpression{}), true, "not"), r.Schema(reflect.TypeOf(expression.OrExpression{}), true, "or"), r.Schema(reflect.TypeOf(expression.PropertyExpression{}), true, "property"), }, Discriminator: &huma.Discriminator{ PropertyName: "type", Mapping: map[string]string{ "action_component_data": "#/components/schemas/ActionComponentDataExpression", "action_data": "#/components/schemas/ActionDataExpression", "aggregate": "#/components/schemas/AggregateExpression", "and": "#/components/schemas/AndExpression", "binary": "#/components/schemas/BinaryExpression", "client_organisation": "#/components/schemas/ClientOrganisationExpression", "column": "#/components/schemas/ColumnExpression", "exists": "#/components/schemas/ExistsExpression", "form_field": "#/components/schemas/FormFieldExpression", "literal": "#/components/schemas/LiteralExpression", "not": "#/components/schemas/NotExpression", "or": "#/components/schemas/OrExpression", "property": "#/components/schemas/PropertyExpression", }, }, } }
  • 39. a s t
  • 40. ast
  • 41. func main() { fset := token.NewFileSet() f, _ := parser.ParseFile(fset, "expression.go", nil, 0) ast.Print(fset, f) }
  • 42. package main func main() { println("Hello, World!") } *ast.File { Package: 2:1 Name: *ast.Ident { . NamePos: 2:9 . Name: "main" } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . } . . Body: *ast.BlockStmt { . . . Lbrace: 3:13 . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . . Rbrace: 5:1 . . } . } } FileStart: 1:1 FileEnd: 5:3 Scope: *ast.Scope { . Objects: map[string]*ast.Object (len = 1) { . . "main": *(obj @ 11) . } } Unresolved: []*ast.Ident (len = 1) { . 0: *(obj @ 29) } GoVersion: "" }
  • 43. package main func main() { println("Hello, World!") } *ast.File { Package: 2:1 Name: *ast.Ident { . NamePos: 2:9 . Name: "main" } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . } . . Body: *ast.BlockStmt { . . . Lbrace: 3:13 . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . . Rbrace: 5:1 . . } . } } FileStart: 1:1 FileEnd: 5:3 Scope: *ast.Scope { . Objects: map[string]*ast.Object (len = 1) { . . "main": *(obj @ 11) . } } Unresolved: []*ast.Ident (len = 1) { . 0: *(obj @ 29) } GoVersion: "" }
  • 44. package main func main() { println("Hello, World!") } *ast.File { Package: 2:1 Name: *ast.Ident { . NamePos: 2:9 . Name: "main" } }
  • 45. package main func main() { println("Hello, World!") } *ast.File { Package: 2:1 Name: *ast.Ident { . NamePos: 2:9 . Name: "main" } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . } . . Body: *ast.BlockStmt { . . . Lbrace: 3:13 . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . . Rbrace: 5:1 . . } . } } FileStart: 1:1 FileEnd: 5:3 Scope: *ast.Scope { . Objects: map[string]*ast.Object (len = 1) { . . "main": *(obj @ 11) . } } Unresolved: []*ast.Ident (len = 1) { . 0: *(obj @ 29) } GoVersion: "" }
  • 46. package main func main() { println("Hello, World!") } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . }
  • 47. package main func main() { println("Hello, World!") } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . }
  • 48. package main func main() { println("Hello, World!") } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . }
  • 49. package main func main() { println("Hello, World!") } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . }
  • 50. package main func main() { println("Hello, World!") } *ast.File { Package: 2:1 Name: *ast.Ident { . NamePos: 2:9 . Name: "main" } Decls: []ast.Decl (len = 1) { . 0: *ast.FuncDecl { . . Name: *ast.Ident { . . . NamePos: 3:6 . . . Name: "main" . . . Obj: *ast.Object { . . . . Kind: func . . . . Name: "main" . . . . Decl: *(obj @ 7) . . . } . . } . . Type: *ast.FuncType { . . . Func: 3:1 . . . Params: *ast.FieldList { . . . . Opening: 3:10 . . . . Closing: 3:11 . . . } . . } . . Body: *ast.BlockStmt { . . . Lbrace: 3:13 . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . . Rbrace: 5:1 . . } . } } FileStart: 1:1 FileEnd: 5:3 Scope: *ast.Scope { . Objects: map[string]*ast.Object (len = 1) { . . "main": *(obj @ 11) . } } Unresolved: []*ast.Ident (len = 1) { . 0: *(obj @ 29) } GoVersion: "" }
  • 51. package main func main() { println("Hello, World!") } . . Body: *ast.BlockStmt { . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . } . }
  • 52. package main func main() { println("Hello, World!") } . . Body: *ast.BlockStmt { . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . } . }
  • 53. package main func main() { println("Hello, World!") } . . Body: *ast.BlockStmt { . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . } . }
  • 54. package main func main() { println("Hello, World!") } . . Body: *ast.BlockStmt { . . . List: []ast.Stmt (len = 1) { . . . . 0: *ast.ExprStmt { . . . . . X: *ast.CallExpr { . . . . . . Fun: *ast.Ident { . . . . . . . NamePos: 4:2 . . . . . . . Name: "println" . . . . . . } . . . . . . Lparen: 4:9 . . . . . . Args: []ast.Expr (len = 1) { . . . . . . . 0: *ast.BasicLit { . . . . . . . . ValuePos: 4:10 . . . . . . . . Kind: STRING . . . . . . . . Value: ""Hello, World!"" . . . . . . . } . . . . . . } . . . . . . Ellipsis: - . . . . . . Rparen: 4:25 . . . . . } . . . . } . . . } . . } . }
  • 55. type Expression interface { GetType() ExpressionType //... }
  • 61. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 62. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 63. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 64. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 65. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 66. *ast.FuncDecl { . . . Recv: *ast.FieldList { . . . . List: []*ast.Field (len = 1) { . . . . . 0: *ast.Field { . . . . . . Names: []*ast.Ident (len = 1) { . . . . . . . 0: *ast.Ident { . . . . . . . . Name: "a" . . . . . . . . Obj: *ast.Object { . . . . . . . . . Kind: var . . . . . . . . . Name: "a" . . . . . . . . . Decl: *(obj @ 2039) . . . . . . . . } . . . . . . . } . . . . . . } . . . . . . Type: *ast.Ident { . . . . . . . Name: "AndExpression" . . . . . . . Obj: *(obj @ 48) . . . . . . } . . . . . } . . . . } . . . } . . . Name: *ast.Ident { . . . . Name: "GetExpressionEntityTypes" . . . } for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 67. *ast.FuncDecl { . . . Recv: *ast.FieldList { . . . . List: []*ast.Field (len = 1) { . . . . . 0: *ast.Field { . . . . . . Names: []*ast.Ident (len = 1) { . . . . . . . 0: *ast.Ident { . . . . . . . . Name: "a" . . . . . . . . Obj: *ast.Object { . . . . . . . . . Kind: var . . . . . . . . . Name: "a" . . . . . . . . . Decl: *(obj @ 2039) . . . . . . . . } . . . . . . . } . . . . . . } . . . . . . Type: *ast.Ident { . . . . . . . Name: "AndExpression" . . . . . . . Obj: *(obj @ 48) . . . . . . } . . . . . } . . . . } . . . } . . . Name: *ast.Ident { . . . . Name: "GetExpressionEntityTypes" . . . }
  • 68. *ast.FuncDecl { . . . Recv: *ast.FieldList { . . . . List: []*ast.Field (len = 1) { . . . . . 0: *ast.Field { . . . . . . Names: []*ast.Ident (len = 1) { . . . . . . . 0: *ast.Ident { . . . . . . . . Name: "a" . . . . . . . . Obj: *ast.Object { . . . . . . . . . Kind: var . . . . . . . . . Name: "a" . . . . . . . . . Decl: *(obj @ 2039) . . . . . . . . } . . . . . . . } . . . . . . } . . . . . . Type: *ast.Ident { . . . . . . . Name: "AndExpression" . . . . . . . Obj: *(obj @ 48) . . . . . . } . . . . . } . . . . } . . . } . . . Name: *ast.Ident { . . . . Name: "GetExpressionEntityTypes" . . . }
  • 69. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 70. for _, decl := range f.Decls { switch fDecl := decl.(type) { case *ast.FuncDecl: if slices.Contains(methodNames, fDecl.Name.Name) { ast.Inspect(fDecl.Recv, func(n ast.Node) bool { switch x := n.(type) { case *ast.Ident: if x.Obj.Kind != ast.Var { //... } } return true }) } } }
  • 71. //go:generate go run ../../cmd/generate_expression_input type Expression interface { GetType() ExpressionType //… }
  • 73. // Code generated by cmd/genereate_input_mapping DO NOT EDIT. package server import ( "reflect" "github.com/danielgtaylor/huma/v2" "github.com/mosaic-avantos/avantos/internal/expression" ) type ExpressionInput map[string]interface{} func (e ExpressionInput) Schema(r huma.Registry) *huma.Schema { r.RegisterTypeAlias(reflect.TypeFor[expression.Expression](), reflect.TypeOf(ExpressionInput{})) // Create a discriminator schema return &huma.Schema{ OneOf: []*huma.Schema{ r.Schema(reflect.TypeOf(expression.ActionComponentDataExpression{}), true, "actionComponentData"), r.Schema(reflect.TypeOf(expression.ActionDataExpression{}), true, "actionData"), r.Schema(reflect.TypeOf(expression.AggregateExpression{}), true, "aggregate"), r.Schema(reflect.TypeOf(expression.AndExpression{}), true, "and"), r.Schema(reflect.TypeOf(expression.BinaryExpression{}), true, "binary"), r.Schema(reflect.TypeOf(expression.ClientOrganisationExpression{}), true, "clientOrganisation"), r.Schema(reflect.TypeOf(expression.ColumnExpression{}), true, "column"), r.Schema(reflect.TypeOf(expression.ExistsExpression{}), true, "exists"), r.Schema(reflect.TypeOf(expression.FormFieldExpression{}), true, "formField"), r.Schema(reflect.TypeOf(expression.LiteralExpression{}), true, "literal"), r.Schema(reflect.TypeOf(expression.NotExpression{}), true, "not"), r.Schema(reflect.TypeOf(expression.OrExpression{}), true, "or"), r.Schema(reflect.TypeOf(expression.PropertyExpression{}), true, "property"), }, Discriminator: &huma.Discriminator{ PropertyName: "type", Mapping: map[string]string{ "action_component_data": "#/components/schemas/ActionComponentDataExpression", "action_data": "#/components/schemas/ActionDataExpression", "aggregate": "#/components/schemas/AggregateExpression", "and": "#/components/schemas/AndExpression", "binary": "#/components/schemas/BinaryExpression", "client_organisation": "#/components/schemas/ClientOrganisationExpression", "column": "#/components/schemas/ColumnExpression", "exists": "#/components/schemas/ExistsExpression", "form_field": "#/components/schemas/FormFieldExpression", "literal": "#/components/schemas/LiteralExpression", "not": "#/components/schemas/NotExpression", "or": "#/components/schemas/OrExpression", "property": "#/components/schemas/PropertyExpression", }, }, } }