Skip to content

Commit

Permalink
pkg: use more go/types logic in code generation
Browse files Browse the repository at this point in the history
Don't chain callCtxtGetter with adtKind, which caused callCtxtGetter
to have some logic which only existed for the sake of adtKind.
This does mean the two funcs now repeat a few Go types like cue.Value,
but we continue to integrate some more principled logic on go/types.

Signed-off-by: Daniel Martí <[email protected]>
Change-Id: I82772807fe2e4668329aa9c6047adf73fc17aedd
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1201377
TryBot-Result: CUEcueckoo <[email protected]>
Unity-Result: CUE porcuepine <[email protected]>
Reviewed-by: Roger Peppe <[email protected]>
  • Loading branch information
mvdan committed Sep 17, 2024
1 parent 93c1124 commit 2fceb5c
Showing 1 changed file with 43 additions and 29 deletions.
72 changes: 43 additions & 29 deletions pkg/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,10 @@ func (g *generator) processGo(pkg *packages.Package) error {
return nil
}

var errorType = types.Universe.Lookup("error").Type()
var (
typeError = types.Universe.Lookup("error").Type()
typeByte = types.Universe.Lookup("byte").Type()
)

func (g *generator) genFunc(fn *types.Func) {
g.nonConcrete = false
Expand All @@ -313,7 +316,7 @@ func (g *generator) genFunc(fn *types.Func) {
}
params := sign.Params()
results := sign.Results()
if results == nil || (results.Len() != 1 && results.At(1).Type() != errorType) {
if results == nil || (results.Len() != 1 && results.At(1).Type() != typeError) {
fmt.Printf("Dropped func %s.%s: must have one return value or a value and an error %v\n", g.cuePkgPath, fn.Name(), sign)
return
}
Expand Down Expand Up @@ -375,8 +378,6 @@ func (g *generator) callCtxtGetter(typ types.Type) string {
switch typ := typ.(type) {
case *types.Basic:
return strings.Title(typ.String()) // "int" turns into "Int"
case *types.Map:
return "Struct"
case *types.Slice:
switch typ.Elem().String() {
case "byte":
Expand Down Expand Up @@ -407,43 +408,56 @@ func (g *generator) callCtxtGetter(typ types.Type) string {
return "Schema"
case "io.Reader":
return "Reader"
case "error":
return "Bottom" // for [generator.adtKind]

// Some builtin functions return custom types, like [cuelang.org/go/pkg/time.Split].
// TODO: we can simplify this once the CUE API declarations in ./pkg/...
// use CUE function signatures to validate their parameters and results.
case "*cuelang.org/go/pkg/time.Parts":
return "Struct"
}
log.Fatal("unknown Go type: ", typ.String())
log.Fatal("callCtxtGetter: unhandled Go type ", typ.String())
return ""
}

// adtKind provides a Go expression string which describes
// a [cuelang.org/go/internal/core/adt.Kind] value for the given type.
func (g *generator) adtKind(typ types.Type) string {
// TODO: detect list and structs types for return values.
switch name := g.callCtxtGetter(typ); name {
case "Bottom", "Bool", "String", "Struct", "Int", "List":
return "adt." + name + "Kind"
case "Int8", "Int16", "Int32", "Rune", "Int64",
"Uint", "Byte", "Uint8", "Uint16", "Uint32", "Uint64",
"BigInt":
return "adt.IntKind"
case "Float64", "BigFloat", "Decimal":
return "adt.NumberKind"
case "DecimalList", "StringList", "CueList":
switch typ := typ.(type) {
case *types.Slice:
if typ.Elem() == typeByte {
return "adt.BytesKind | adt.StringKind"
}
return "adt.ListKind"
case "Bytes", "Reader":
case *types.Map:
return "adt.StructKind"
case *types.Basic:
if typ.Info()&types.IsInteger != 0 {
return "adt.IntKind"
}
if typ.Kind() == types.Float64 {
return "adt.NumberKind"
}
return "adt." + strings.Title(typ.String()) + "Kind" // "bool" turns into "adt.BoolKind"
}
switch typ.String() {
case "error":
return "adt.BottomKind"
case "io.Reader":
return "adt.BytesKind | adt.StringKind"
case "Value", "Schema":
// Must use the CallCtxt.Value method for these types and resolve manually.
case "cuelang.org/go/internal/pkg.Struct":
return "adt.StructKind"
case "cuelang.org/go/internal/pkg.List":
return "adt.ListKind"
case "*math/big.Int":
return "adt.IntKind"
case "*cuelang.org/go/internal.Decimal", "*math/big.Float":
return "adt.NumberKind"
case "cuelang.org/go/cue.Value", "cuelang.org/go/cue/ast.Expr", "cuelang.org/go/internal/pkg.Schema":
return "adt.TopKind" // TODO: can be more precise
default:
log.Fatal("unknown CallCtxt type: ", name)
return ""

// Some builtin functions return custom types, like [cuelang.org/go/pkg/time.Split].
// TODO: we can simplify this once the CUE API declarations in ./pkg/...
// use CUE function signatures to validate their parameters and results.
case "*cuelang.org/go/pkg/time.Parts":
return "adt.StructKind"
}
log.Fatal("adtKind: unhandled Go type ", typ.String())
return ""
}

var errNoCUEFiles = errors.New("no CUE files in directory")
Expand Down

0 comments on commit 2fceb5c

Please sign in to comment.