Skip to content

Commit 136e51b

Browse files
committed
internal/core: allow variable arg functions
This is mostly to allow os-dependent functions that are convenient, yet still hermetic. E.g. path.Base(str, path.Unix) Most of the files in this CL are generated. Only files not starting with pkg/ and pkg/internal/builtin.go are relevant. The basic idea is that to intead of just specifying the kind of paramter, to also allow a default value. As this is just a CUE value, this will also allow for constraints down the line. The old shim implementation in pkg/internal/builtin.go keeps it simple, though. Builtins with default values will have to be hand-coded later on. Change-Id: I184d672a8704f4ec6c53491d08caddd1f774bda2 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7842 Reviewed-by: Marcel van Lohuizen <[email protected]> Reviewed-by: CUE cueckoo <[email protected]>
1 parent fa6308f commit 136e51b

File tree

26 files changed

+1025
-446
lines changed

26 files changed

+1025
-446
lines changed

internal/core/adt/expr.go

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ func (x *CallExpr) evaluate(c *OpContext) Value {
937937
// A Builtin is a value representing a native function call.
938938
type Builtin struct {
939939
// TODO: make these values for better type checking.
940-
Params []Kind
940+
Params []Param
941941
Result Kind
942942
Func func(c *OpContext, args []Value) Expr
943943

@@ -947,6 +947,23 @@ type Builtin struct {
947947
Const string
948948
}
949949

950+
type Param struct {
951+
Name Feature // name of the argument; mostly for documentation
952+
Value Value // Could become Value later, using disjunctions for defaults.
953+
}
954+
955+
func (p Param) Kind() Kind {
956+
return p.Value.Kind()
957+
}
958+
959+
func (p Param) Default() Value {
960+
d, ok := p.Value.(*Disjunction)
961+
if !ok || d.NumDefaults != 1 {
962+
return nil
963+
}
964+
return d.Values[0]
965+
}
966+
950967
func (x *Builtin) WriteName(w io.Writer, c *OpContext) {
951968
_, _ = fmt.Fprintf(w, "%s.%s", x.Package.StringValue(c), x.Name)
952969
}
@@ -956,7 +973,7 @@ func (x *Builtin) Kind() Kind {
956973
if len(x.Params) == 0 {
957974
return BottomKind
958975
}
959-
return x.Params[0]
976+
return x.Params[0].Kind()
960977
}
961978

962979
func (x *Builtin) validate(c *OpContext, v Value) *Bottom {
@@ -984,32 +1001,36 @@ func (x *Builtin) call(c *OpContext, call *ast.CallExpr, args []Value) Expr {
9841001
// We have a custom builtin
9851002
return &BuiltinValidator{call, x, args}
9861003
}
987-
switch {
988-
case len(x.Params) < len(args):
1004+
if len(args) > len(x.Params) {
9891005
c.addErrf(0, call.Rparen,
9901006
"too many arguments in call to %s (have %d, want %d)",
9911007
call.Fun, len(args), len(x.Params))
9921008
return nil
993-
case len(x.Params) > len(args):
994-
c.addErrf(0, call.Rparen,
995-
"not enough arguments in call to %s (have %d, want %d)",
996-
call.Fun, len(args), len(x.Params))
997-
return nil
1009+
}
1010+
for i := len(args); i < len(x.Params); i++ {
1011+
v := x.Params[i].Default()
1012+
if v == nil {
1013+
c.addErrf(0, call.Rparen,
1014+
"not enough arguments in call to %s (have %d, want %d)",
1015+
call.Fun, len(args), len(x.Params))
1016+
return nil
1017+
}
1018+
args = append(args, v)
9981019
}
9991020
for i, a := range args {
1000-
if x.Params[i] != BottomKind {
1021+
if x.Params[i].Kind() != BottomKind {
10011022
if b := bottom(a); b != nil {
10021023
return b
10031024
}
1004-
if k := kind(a); x.Params[i]&k == BottomKind {
1025+
if k := kind(a); x.Params[i].Kind()&k == BottomKind {
10051026
code := EvalError
10061027
b, _ := args[i].(*Bottom)
10071028
if b != nil {
10081029
code = b.Code
10091030
}
10101031
c.addErrf(code, pos(a),
10111032
"cannot use %s (type %s) as %s in argument %d to %s",
1012-
a, k, x.Params[i], i+1, call.Fun)
1033+
a, k, x.Params[i].Kind(), i+1, call.Fun)
10131034
return nil
10141035
}
10151036
}
@@ -1038,7 +1059,7 @@ func (x *BuiltinValidator) Source() ast.Node {
10381059
}
10391060

10401061
func (x *BuiltinValidator) Kind() Kind {
1041-
return x.Builtin.Params[0]
1062+
return x.Builtin.Params[0].Kind()
10421063
}
10431064

10441065
func (x *BuiltinValidator) validate(c *OpContext, v Value) *Bottom {

internal/core/compile/builtin.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,16 @@ import (
2626

2727
const supportedByLen = adt.StructKind | adt.BytesKind | adt.StringKind | adt.ListKind
2828

29+
var (
30+
stringParam = adt.Param{Value: &adt.BasicType{K: adt.StringKind}}
31+
structParam = adt.Param{Value: &adt.BasicType{K: adt.StructKind}}
32+
listParam = adt.Param{Value: &adt.BasicType{K: adt.ListKind}}
33+
intParam = adt.Param{Value: &adt.BasicType{K: adt.IntKind}}
34+
)
35+
2936
var lenBuiltin = &adt.Builtin{
3037
Name: "len",
31-
Params: []adt.Kind{supportedByLen},
38+
Params: []adt.Param{{Value: &adt.BasicType{K: supportedByLen}}},
3239
Result: adt.IntKind,
3340
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
3441
v := args[0]
@@ -74,7 +81,7 @@ var lenBuiltin = &adt.Builtin{
7481

7582
var closeBuiltin = &adt.Builtin{
7683
Name: "close",
77-
Params: []adt.Kind{adt.StructKind},
84+
Params: []adt.Param{structParam},
7885
Result: adt.StructKind,
7986
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
8087
s, ok := args[0].(*adt.Vertex)
@@ -92,7 +99,7 @@ var closeBuiltin = &adt.Builtin{
9299

93100
var andBuiltin = &adt.Builtin{
94101
Name: "and",
95-
Params: []adt.Kind{adt.ListKind},
102+
Params: []adt.Param{listParam},
96103
Result: adt.IntKind,
97104
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
98105
list := c.Elems(args[0])
@@ -109,7 +116,7 @@ var andBuiltin = &adt.Builtin{
109116

110117
var orBuiltin = &adt.Builtin{
111118
Name: "or",
112-
Params: []adt.Kind{adt.ListKind},
119+
Params: []adt.Param{listParam},
113120
Result: adt.IntKind,
114121
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
115122
d := []adt.Disjunct{}
@@ -141,7 +148,7 @@ var orBuiltin = &adt.Builtin{
141148

142149
var divBuiltin = &adt.Builtin{
143150
Name: "div",
144-
Params: []adt.Kind{adt.IntKind, adt.IntKind},
151+
Params: []adt.Param{intParam, intParam},
145152
Result: adt.IntKind,
146153
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
147154
const name = "argument to div builtin"
@@ -152,7 +159,7 @@ var divBuiltin = &adt.Builtin{
152159

153160
var modBuiltin = &adt.Builtin{
154161
Name: "mod",
155-
Params: []adt.Kind{adt.IntKind, adt.IntKind},
162+
Params: []adt.Param{intParam, intParam},
156163
Result: adt.IntKind,
157164
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
158165
const name = "argument to mod builtin"
@@ -163,7 +170,7 @@ var modBuiltin = &adt.Builtin{
163170

164171
var quoBuiltin = &adt.Builtin{
165172
Name: "quo",
166-
Params: []adt.Kind{adt.IntKind, adt.IntKind},
173+
Params: []adt.Param{intParam, intParam},
167174
Result: adt.IntKind,
168175
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
169176
const name = "argument to quo builtin"
@@ -174,7 +181,7 @@ var quoBuiltin = &adt.Builtin{
174181

175182
var remBuiltin = &adt.Builtin{
176183
Name: "rem",
177-
Params: []adt.Kind{adt.IntKind, adt.IntKind},
184+
Params: []adt.Param{intParam, intParam},
178185
Result: adt.IntKind,
179186
Func: func(c *adt.OpContext, args []adt.Value) adt.Expr {
180187
const name = "argument to rem builtin"

pkg/crypto/md5/pkg.go

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/crypto/sha1/pkg.go

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/crypto/sha256/pkg.go

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/crypto/sha512/pkg.go

Lines changed: 16 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/encoding/base64/pkg.go

Lines changed: 20 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/encoding/csv/pkg.go

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)