Skip to content

Commit

Permalink
pkg: replace some string handling with go/types logic
Browse files Browse the repository at this point in the history
The logic is a bit less repetitive and principled this way;
for example, we don't need to detect lists and maps by string prefix,
and we restrict the use of strings.Title on basic type names.

Be more defensive in the adtKind method by failing if we reach the
default switch case, so that we don't end up on adt.TopKind by accident.

Give the two methods slightly better names and some documentation too.

While here, remove switch cases which are entirely unused
and cannot be used because we don't have support for them in CallCtxt,
such as *big.Rat and time.Time.

Signed-off-by: Daniel Martí <[email protected]>
Change-Id: I0ff8df76358fd558f97d3ba711d19f4d69b1b843
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1201035
TryBot-Result: CUEcueckoo <[email protected]>
Unity-Result: CUE porcuepine <[email protected]>
Reviewed-by: Roger Peppe <[email protected]>
  • Loading branch information
mvdan committed Sep 12, 2024
1 parent a558a4b commit 143be90
Showing 1 changed file with 60 additions and 69 deletions.
129 changes: 60 additions & 69 deletions pkg/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,9 @@ func (g *generator) genFunc(fn *types.Func) {
kind := []string{}
for i := 0; i < params.Len(); i++ {
param := params.At(i)
typ := strings.Title(g.goKind(param.Type()))
argKind := g.goToCUE(param.Type())
vals = append(vals, fmt.Sprintf("c.%s(%d)", typ, len(args)))
methodName := g.callCtxtGetter(param.Type())
argKind := g.adtKind(param.Type())
vals = append(vals, fmt.Sprintf("c.%s(%d)", methodName, len(args)))
args = append(args, param.Name())
kind = append(kind, argKind)
}
Expand All @@ -342,7 +342,7 @@ func (g *generator) genFunc(fn *types.Func) {
}
fmt.Fprintf(g.w, "\n},\n")

fmt.Fprintf(g.w, "Result: %s,\n", g.goToCUE(results.At(0).Type()))
fmt.Fprintf(g.w, "Result: %s,\n", g.adtKind(results.At(0).Type()))
if g.nonConcrete {
fmt.Fprintf(g.w, "NonConcrete: true,\n")
}
Expand All @@ -369,85 +369,76 @@ func (g *generator) genFunc(fn *types.Func) {
}
}

// TODO(mvdan): goKind and goToCUE still use a lot of strings; simplify.

func (g *generator) goKind(typ types.Type) string {
switch str := types.TypeString(typ, nil); str {
// callCtxtGetter returns the name of the [cuelang.org/go/internal/pkg.CallCtxt] method
// which can be used to fetch a parameter of the given type.
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":
return "Bytes"
case "string":
return "StringList"
case "*cuelang.org/go/internal.Decimal":
return "DecimalList"
}
return "List"
}
switch typ.String() {
case "*math/big.Int":
return "bigInt"
return "BigInt"
case "*math/big.Float":
return "bigFloat"
case "*math/big.Rat":
return "bigRat"
case "cuelang.org/go/internal/core/adt.Bottom":
return "error"
return "BigFloat"
case "*cuelang.org/go/internal.Decimal":
return "decimal"
return "Decimal"
case "cuelang.org/go/internal/pkg.List":
return "cueList"
return "CueList"
case "cuelang.org/go/internal/pkg.Struct":
return "struct"
case "[]*cuelang.org/go/internal.Decimal":
return "decimalList"
case "cuelang.org/go/cue.Value":
return "value"
return "Struct"
case "cuelang.org/go/cue.Value",
"cuelang.org/go/cue/ast.Expr":
return "Value"
case "cuelang.org/go/internal/pkg.Schema":
g.nonConcrete = true
return "schema"
case "cuelang.org/go/cue.List":
return "list"
case "[]string":
return "stringList"
case "[]byte":
return "bytes"
case "[]cuelang.org/go/cue.Value":
return "list"
return "Schema"
case "io.Reader":
return "reader"
case "time.Time":
return "string"
default:
return str
return "Reader"
case "error":
return "Bottom" // for [generator.cueTypeExpression]
}
return "Value" // for [generator.cueTypeExpression]
}

func (g *generator) goToCUE(typ types.Type) (cueKind string) {
// 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 k := g.goKind(typ); k {
case "error":
cueKind += "adt.BottomKind"
case "bool":
cueKind += "adt.BoolKind"
case "bytes", "reader":
cueKind += "adt.BytesKind|adt.StringKind"
case "string":
cueKind += "adt.StringKind"
case "int", "int8", "int16", "int32", "rune", "int64",
"uint", "byte", "uint8", "uint16", "uint32", "uint64",
"bigInt":
cueKind += "adt.IntKind"
case "float64", "bigRat", "bigFloat", "decimal":
cueKind += "adt.NumberKind"
case "list", "decimalList", "stringList", "cueList":
cueKind += "adt.ListKind"
case "struct":
cueKind += "adt.StructKind"
case "value":
// Must use callCtxt.value method for these types and resolve manually.
cueKind += "adt.TopKind" // TODO: can be more precise
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 "Complex128":
return "adt.TopKind" // TODO(mvdan): what should we return here?
case "DecimalList", "StringList", "CueList":
return "adt.ListKind"
case "Bytes", "Reader":
return "adt.BytesKind | adt.StringKind"
case "Value", "Schema":
// Must use the CallCtxt.Value method for these types and resolve manually.
return "adt.TopKind" // TODO: can be more precise
default:
switch {
case strings.HasPrefix(k, "[]"):
cueKind += "adt.ListKind"
case strings.HasPrefix(k, "map["):
cueKind += "adt.StructKind"
default:
// log.Println("Unknown type:", k)
// Must use callCtxt.value method for these types and resolve manually.
cueKind += "adt.TopKind" // TODO: can be more precise
}
log.Fatal("unknown CallCtxt type: ", name)
return ""
}
return cueKind
}

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

0 comments on commit 143be90

Please sign in to comment.