feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
267
vendor/go.starlark.net/starlark/eval.go
generated
vendored
267
vendor/go.starlark.net/starlark/eval.go
generated
vendored
@@ -9,13 +9,14 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"go.starlark.net/internal/compile"
|
||||
"go.starlark.net/internal/spell"
|
||||
@@ -46,6 +47,21 @@ type Thread struct {
|
||||
// See example_test.go for some example implementations of Load.
|
||||
Load func(thread *Thread, module string) (StringDict, error)
|
||||
|
||||
// OnMaxSteps is called when the thread reaches the limit set by SetMaxExecutionSteps.
|
||||
// The default behavior is to call thread.Cancel("too many steps").
|
||||
OnMaxSteps func(thread *Thread)
|
||||
|
||||
// Steps a count of abstract computation steps executed
|
||||
// by this thread. It is incremented by the interpreter. It may be used
|
||||
// as a measure of the approximate cost of Starlark execution, by
|
||||
// computing the difference in its value before and after a computation.
|
||||
//
|
||||
// The precise meaning of "step" is not specified and may change.
|
||||
Steps, maxSteps uint64
|
||||
|
||||
// cancelReason records the reason from the first call to Cancel.
|
||||
cancelReason *string
|
||||
|
||||
// locals holds arbitrary "thread-local" Go values belonging to the client.
|
||||
// They are accessible to the client but not to any Starlark program.
|
||||
locals map[string]interface{}
|
||||
@@ -54,6 +70,42 @@ type Thread struct {
|
||||
proftime time.Duration
|
||||
}
|
||||
|
||||
// ExecutionSteps returns the current value of Steps.
|
||||
func (thread *Thread) ExecutionSteps() uint64 {
|
||||
return thread.Steps
|
||||
}
|
||||
|
||||
// SetMaxExecutionSteps sets a limit on the number of Starlark
|
||||
// computation steps that may be executed by this thread. If the
|
||||
// thread's step counter exceeds this limit, the interpreter calls
|
||||
// the optional OnMaxSteps function or the default behavior
|
||||
// of calling thread.Cancel("too many steps").
|
||||
func (thread *Thread) SetMaxExecutionSteps(max uint64) {
|
||||
thread.maxSteps = max
|
||||
}
|
||||
|
||||
// Uncancel resets the cancellation state.
|
||||
//
|
||||
// Unlike most methods of Thread, it is safe to call Uncancel from any
|
||||
// goroutine, even if the thread is actively executing.
|
||||
func (thread *Thread) Uncancel() {
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil)
|
||||
}
|
||||
|
||||
// Cancel causes execution of Starlark code in the specified thread to
|
||||
// promptly fail with an EvalError that includes the specified reason.
|
||||
// There may be a delay before the interpreter observes the cancellation
|
||||
// if the thread is currently in a call to a built-in function.
|
||||
//
|
||||
// Call [Uncancel] to reset the cancellation state.
|
||||
//
|
||||
// Unlike most methods of Thread, it is safe to call Cancel from any
|
||||
// goroutine, even if the thread is actively executing.
|
||||
func (thread *Thread) Cancel(reason string) {
|
||||
// Atomically set cancelReason, preserving earlier reason if any.
|
||||
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil, unsafe.Pointer(&reason))
|
||||
}
|
||||
|
||||
// SetLocal sets the thread-local value associated with the specified key.
|
||||
// It must not be called after execution begins.
|
||||
func (thread *Thread) SetLocal(key string, value interface{}) {
|
||||
@@ -178,7 +230,9 @@ func (stack *CallStack) Pop() CallFrame {
|
||||
// String returns a user-friendly description of the stack.
|
||||
func (stack CallStack) String() string {
|
||||
out := new(strings.Builder)
|
||||
fmt.Fprintf(out, "Traceback (most recent call last):\n")
|
||||
if len(stack) > 0 {
|
||||
fmt.Fprintf(out, "Traceback (most recent call last):\n")
|
||||
}
|
||||
for _, fr := range stack {
|
||||
fmt.Fprintf(out, " %s: in %s\n", fr.Pos, fr.Name)
|
||||
}
|
||||
@@ -220,7 +274,15 @@ func (e *EvalError) Error() string { return e.Msg }
|
||||
// Backtrace returns a user-friendly error message describing the stack
|
||||
// of calls that led to this error.
|
||||
func (e *EvalError) Backtrace() string {
|
||||
return fmt.Sprintf("%sError: %s", e.CallStack, e.Msg)
|
||||
// If the topmost stack frame is a built-in function,
|
||||
// remove it from the stack and add print "Error in fn:".
|
||||
stack := e.CallStack
|
||||
suffix := ""
|
||||
if last := len(stack) - 1; last >= 0 && stack[last].Pos.Filename() == builtinFilename {
|
||||
suffix = " in " + stack[last].Name
|
||||
stack = stack[:last]
|
||||
}
|
||||
return fmt.Sprintf("%sError%s: %s", stack, suffix, e.Msg)
|
||||
}
|
||||
|
||||
func (e *EvalError) Unwrap() error { return e.cause }
|
||||
@@ -429,6 +491,8 @@ func makeToplevelFunction(prog *compile.Program, predeclared StringDict) *Functi
|
||||
v = MakeBigInt(c)
|
||||
case string:
|
||||
v = String(c)
|
||||
case compile.Bytes:
|
||||
v = Bytes(c)
|
||||
case float64:
|
||||
v = Float(c)
|
||||
default:
|
||||
@@ -674,14 +738,22 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
case Int:
|
||||
return x.Add(y), nil
|
||||
case Float:
|
||||
return x.Float() + y, nil
|
||||
xf, err := x.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return xf + y, nil
|
||||
}
|
||||
case Float:
|
||||
switch y := y.(type) {
|
||||
case Float:
|
||||
return x + y, nil
|
||||
case Int:
|
||||
return x + y.Float(), nil
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x + yf, nil
|
||||
}
|
||||
case *List:
|
||||
if y, ok := y.(*List); ok {
|
||||
@@ -706,14 +778,22 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
case Int:
|
||||
return x.Sub(y), nil
|
||||
case Float:
|
||||
return x.Float() - y, nil
|
||||
xf, err := x.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return xf - y, nil
|
||||
}
|
||||
case Float:
|
||||
switch y := y.(type) {
|
||||
case Float:
|
||||
return x - y, nil
|
||||
case Int:
|
||||
return x - y.Float(), nil
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x - yf, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,9 +804,15 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
case Int:
|
||||
return x.Mul(y), nil
|
||||
case Float:
|
||||
return x.Float() * y, nil
|
||||
xf, err := x.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return xf * y, nil
|
||||
case String:
|
||||
return stringRepeat(y, x)
|
||||
case Bytes:
|
||||
return bytesRepeat(y, x)
|
||||
case *List:
|
||||
elems, err := tupleRepeat(Tuple(y.elems), x)
|
||||
if err != nil {
|
||||
@@ -741,12 +827,20 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
case Float:
|
||||
return x * y, nil
|
||||
case Int:
|
||||
return x * y.Float(), nil
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x * yf, nil
|
||||
}
|
||||
case String:
|
||||
if y, ok := y.(Int); ok {
|
||||
return stringRepeat(x, y)
|
||||
}
|
||||
case Bytes:
|
||||
if y, ok := y.(Int); ok {
|
||||
return bytesRepeat(x, y)
|
||||
}
|
||||
case *List:
|
||||
if y, ok := y.(Int); ok {
|
||||
elems, err := tupleRepeat(Tuple(x.elems), y)
|
||||
@@ -765,30 +859,40 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
case syntax.SLASH:
|
||||
switch x := x.(type) {
|
||||
case Int:
|
||||
xf, err := x.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch y := y.(type) {
|
||||
case Int:
|
||||
yf := y.Float()
|
||||
if yf == 0.0 {
|
||||
return nil, fmt.Errorf("real division by zero")
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x.Float() / yf, nil
|
||||
if yf == 0.0 {
|
||||
return nil, fmt.Errorf("floating-point division by zero")
|
||||
}
|
||||
return xf / yf, nil
|
||||
case Float:
|
||||
if y == 0.0 {
|
||||
return nil, fmt.Errorf("real division by zero")
|
||||
return nil, fmt.Errorf("floating-point division by zero")
|
||||
}
|
||||
return x.Float() / y, nil
|
||||
return xf / y, nil
|
||||
}
|
||||
case Float:
|
||||
switch y := y.(type) {
|
||||
case Float:
|
||||
if y == 0.0 {
|
||||
return nil, fmt.Errorf("real division by zero")
|
||||
return nil, fmt.Errorf("floating-point division by zero")
|
||||
}
|
||||
return x / y, nil
|
||||
case Int:
|
||||
yf := y.Float()
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if yf == 0.0 {
|
||||
return nil, fmt.Errorf("real division by zero")
|
||||
return nil, fmt.Errorf("floating-point division by zero")
|
||||
}
|
||||
return x / yf, nil
|
||||
}
|
||||
@@ -804,10 +908,14 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
}
|
||||
return x.Div(y), nil
|
||||
case Float:
|
||||
xf, err := x.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if y == 0.0 {
|
||||
return nil, fmt.Errorf("floored division by zero")
|
||||
}
|
||||
return floor((x.Float() / y)), nil
|
||||
return floor(xf / y), nil
|
||||
}
|
||||
case Float:
|
||||
switch y := y.(type) {
|
||||
@@ -817,7 +925,10 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
}
|
||||
return floor(x / y), nil
|
||||
case Int:
|
||||
yf := y.Float()
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if yf == 0.0 {
|
||||
return nil, fmt.Errorf("floored division by zero")
|
||||
}
|
||||
@@ -835,23 +946,31 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
}
|
||||
return x.Mod(y), nil
|
||||
case Float:
|
||||
if y == 0 {
|
||||
return nil, fmt.Errorf("float modulo by zero")
|
||||
xf, err := x.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x.Float().Mod(y), nil
|
||||
if y == 0 {
|
||||
return nil, fmt.Errorf("floating-point modulo by zero")
|
||||
}
|
||||
return xf.Mod(y), nil
|
||||
}
|
||||
case Float:
|
||||
switch y := y.(type) {
|
||||
case Float:
|
||||
if y == 0.0 {
|
||||
return nil, fmt.Errorf("float modulo by zero")
|
||||
return nil, fmt.Errorf("floating-point modulo by zero")
|
||||
}
|
||||
return Float(math.Mod(float64(x), float64(y))), nil
|
||||
return x.Mod(y), nil
|
||||
case Int:
|
||||
if y.Sign() == 0 {
|
||||
return nil, fmt.Errorf("float modulo by zero")
|
||||
return nil, fmt.Errorf("floating-point modulo by zero")
|
||||
}
|
||||
return x.Mod(y.Float()), nil
|
||||
yf, err := y.finiteFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x.Mod(yf), nil
|
||||
}
|
||||
case String:
|
||||
return interpolate(string(x), y)
|
||||
@@ -898,6 +1017,19 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
return nil, fmt.Errorf("'in <string>' requires string as left operand, not %s", x.Type())
|
||||
}
|
||||
return Bool(strings.Contains(string(y), string(needle))), nil
|
||||
case Bytes:
|
||||
switch needle := x.(type) {
|
||||
case Bytes:
|
||||
return Bool(strings.Contains(string(y), string(needle))), nil
|
||||
case Int:
|
||||
var b byte
|
||||
if err := AsInt(needle, &b); err != nil {
|
||||
return nil, fmt.Errorf("int in bytes: %s", err)
|
||||
}
|
||||
return Bool(strings.IndexByte(string(y), b) >= 0), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("'in bytes' requires bytes or int as left operand, not %s", x.Type())
|
||||
}
|
||||
case rangeValue:
|
||||
i, err := NumberToInt(x)
|
||||
if err != nil {
|
||||
@@ -912,6 +1044,12 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
if y, ok := y.(Int); ok {
|
||||
return x.Or(y), nil
|
||||
}
|
||||
|
||||
case *Dict: // union
|
||||
if y, ok := y.(*Dict); ok {
|
||||
return x.Union(y), nil
|
||||
}
|
||||
|
||||
case *Set: // union
|
||||
if y, ok := y.(*Set); ok {
|
||||
iter := Iterate(y)
|
||||
@@ -932,10 +1070,10 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
if x.Len() > y.Len() {
|
||||
x, y = y, x // opt: range over smaller set
|
||||
}
|
||||
for _, xelem := range x.elems() {
|
||||
for xe := x.ht.head; xe != nil; xe = xe.next {
|
||||
// Has, Insert cannot fail here.
|
||||
if found, _ := y.Has(xelem); found {
|
||||
set.Insert(xelem)
|
||||
if found, _ := y.Has(xe.key); found {
|
||||
set.Insert(xe.key)
|
||||
}
|
||||
}
|
||||
return set, nil
|
||||
@@ -951,14 +1089,14 @@ func Binary(op syntax.Token, x, y Value) (Value, error) {
|
||||
case *Set: // symmetric difference
|
||||
if y, ok := y.(*Set); ok {
|
||||
set := new(Set)
|
||||
for _, xelem := range x.elems() {
|
||||
if found, _ := y.Has(xelem); !found {
|
||||
set.Insert(xelem)
|
||||
for xe := x.ht.head; xe != nil; xe = xe.next {
|
||||
if found, _ := y.Has(xe.key); !found {
|
||||
set.Insert(xe.key)
|
||||
}
|
||||
}
|
||||
for _, yelem := range y.elems() {
|
||||
if found, _ := x.Has(yelem); !found {
|
||||
set.Insert(yelem)
|
||||
for ye := y.ht.head; ye != nil; ye = ye.next {
|
||||
if found, _ := x.Has(ye.key); !found {
|
||||
set.Insert(ye.key)
|
||||
}
|
||||
}
|
||||
return set, nil
|
||||
@@ -1027,7 +1165,8 @@ func tupleRepeat(elems Tuple, n Int) (Tuple, error) {
|
||||
// Inv: i > 0, len > 0
|
||||
sz := len(elems) * i
|
||||
if sz < 0 || sz >= maxAlloc { // sz < 0 => overflow
|
||||
return nil, fmt.Errorf("excessive repeat (%d elements)", sz)
|
||||
// Don't print sz.
|
||||
return nil, fmt.Errorf("excessive repeat (%d * %d elements)", len(elems), i)
|
||||
}
|
||||
res := make([]Value, sz)
|
||||
// copy elems into res, doubling each time
|
||||
@@ -1039,6 +1178,11 @@ func tupleRepeat(elems Tuple, n Int) (Tuple, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func bytesRepeat(b Bytes, n Int) (Bytes, error) {
|
||||
res, err := stringRepeat(String(b), n)
|
||||
return Bytes(res), err
|
||||
}
|
||||
|
||||
func stringRepeat(s String, n Int) (String, error) {
|
||||
if s == "" {
|
||||
return "", nil
|
||||
@@ -1053,7 +1197,8 @@ func stringRepeat(s String, n Int) (String, error) {
|
||||
// Inv: i > 0, len > 0
|
||||
sz := len(s) * i
|
||||
if sz < 0 || sz >= maxAlloc { // sz < 0 => overflow
|
||||
return "", fmt.Errorf("excessive repeat (%d elements)", sz)
|
||||
// Don't print sz.
|
||||
return "", fmt.Errorf("excessive repeat (%d * %d elements)", len(s), i)
|
||||
}
|
||||
return String(strings.Repeat(string(s), i)), nil
|
||||
}
|
||||
@@ -1075,13 +1220,35 @@ func Call(thread *Thread, fn Value, args Tuple, kwargs []Tuple) (Value, error) {
|
||||
if fr == nil {
|
||||
fr = new(frame)
|
||||
}
|
||||
|
||||
if thread.stack == nil {
|
||||
// one-time initialization of thread
|
||||
if thread.maxSteps == 0 {
|
||||
thread.maxSteps-- // (MaxUint64)
|
||||
}
|
||||
}
|
||||
|
||||
thread.stack = append(thread.stack, fr) // push
|
||||
|
||||
fr.callable = c
|
||||
|
||||
thread.beginProfSpan()
|
||||
|
||||
// Use defer to ensure that panics from built-ins
|
||||
// pass through the interpreter without leaving
|
||||
// it in a bad state.
|
||||
defer func() {
|
||||
thread.endProfSpan()
|
||||
|
||||
// clear out any references
|
||||
// TODO(adonovan): opt: zero fr.Locals and
|
||||
// reuse it if it is large enough.
|
||||
*fr = frame{}
|
||||
|
||||
thread.stack = thread.stack[:len(thread.stack)-1] // pop
|
||||
}()
|
||||
|
||||
result, err := c.CallInternal(thread, args, kwargs)
|
||||
thread.endProfSpan()
|
||||
|
||||
// Sanity check: nil is not a valid Starlark value.
|
||||
if result == nil && err == nil {
|
||||
@@ -1095,9 +1262,6 @@ func Call(thread *Thread, fn Value, args Tuple, kwargs []Tuple) (Value, error) {
|
||||
}
|
||||
}
|
||||
|
||||
*fr = frame{} // clear out any references
|
||||
thread.stack = thread.stack[:len(thread.stack)-1] // pop
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -1113,7 +1277,7 @@ func slice(x, lo, hi, step_ Value) (Value, error) {
|
||||
var err error
|
||||
step, err = AsInt32(step_)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("got %s for slice step, want int", step_.Type())
|
||||
return nil, fmt.Errorf("invalid slice step: %s", err)
|
||||
}
|
||||
if step == 0 {
|
||||
return nil, fmt.Errorf("zero is not a valid slice step")
|
||||
@@ -1207,7 +1371,7 @@ func asIndex(v Value, len int, result *int) error {
|
||||
var err error
|
||||
*result, err = AsInt32(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("got %s, want int", v.Type())
|
||||
return err
|
||||
}
|
||||
if *result < 0 {
|
||||
*result += len
|
||||
@@ -1448,20 +1612,7 @@ func interpolate(format string, x Value) (Value, error) {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%%%c format requires float, not %s", c, arg.Type())
|
||||
}
|
||||
switch c {
|
||||
case 'e':
|
||||
fmt.Fprintf(buf, "%e", f)
|
||||
case 'f':
|
||||
fmt.Fprintf(buf, "%f", f)
|
||||
case 'g':
|
||||
fmt.Fprintf(buf, "%g", f)
|
||||
case 'E':
|
||||
fmt.Fprintf(buf, "%E", f)
|
||||
case 'F':
|
||||
fmt.Fprintf(buf, "%F", f)
|
||||
case 'G':
|
||||
fmt.Fprintf(buf, "%G", f)
|
||||
}
|
||||
Float(f).format(buf, c)
|
||||
case 'c':
|
||||
switch arg := arg.(type) {
|
||||
case Int:
|
||||
|
||||
Reference in New Issue
Block a user