mirror of
https://github.com/go-delve/delve.git
synced 2025-10-31 02:36:18 +08:00
starbind: Make the time module available to star scripts (#3375)
This patch makes the time library available to Starlark scripts. This library is one of the very few few that are built into starlark-go (the others are json, math, proto). I've played around with Starlark scripting today, and immediately I wanted to measure how long certain computations take.
This commit is contained in:
@ -74,6 +74,8 @@ cur_scope() | Returns the current evaluation scope
|
|||||||
default_load_config() | Returns the current default load configuration
|
default_load_config() | Returns the current default load configuration
|
||||||
<!-- END MAPPING TABLE -->
|
<!-- END MAPPING TABLE -->
|
||||||
|
|
||||||
|
In addition to these built-ins, the [time](https://pkg.go.dev/go.starlark.net/lib/time#pkg-variables) library from the starlark-go project is also available to scripts.
|
||||||
|
|
||||||
## Should I use raw_command or dlv_command?
|
## Should I use raw_command or dlv_command?
|
||||||
|
|
||||||
There are two ways to resume the execution of the target program:
|
There are two ways to resume the execution of the target program:
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
startime "go.starlark.net/lib/time"
|
||||||
"go.starlark.net/resolve"
|
"go.starlark.net/resolve"
|
||||||
"go.starlark.net/starlark"
|
"go.starlark.net/starlark"
|
||||||
|
|
||||||
@ -67,6 +68,9 @@ func New(ctx Context, out EchoWriter) *Env {
|
|||||||
env.ctx = ctx
|
env.ctx = ctx
|
||||||
env.out = out
|
env.out = out
|
||||||
|
|
||||||
|
// Make the "time" module available to Starlark scripts.
|
||||||
|
starlark.Universe["time"] = startime.Module
|
||||||
|
|
||||||
env.env = env.starlarkPredeclare()
|
env.env = env.starlarkPredeclare()
|
||||||
env.env[dlvCommandBuiltinName] = starlark.NewBuiltin(dlvCommandBuiltinName, func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
env.env[dlvCommandBuiltinName] = starlark.NewBuiltin(dlvCommandBuiltinName, func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
if err := isCancelled(thread); err != nil {
|
if err := isCancelled(thread); err != nil {
|
||||||
|
|||||||
507
vendor/go.starlark.net/lib/time/time.go
generated
vendored
Normal file
507
vendor/go.starlark.net/lib/time/time.go
generated
vendored
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
// Copyright 2021 The Bazel Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package time provides time-related constants and functions.
|
||||||
|
package time // import "go.starlark.net/lib/time"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
"go.starlark.net/starlarkstruct"
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Module time is a Starlark module of time-related functions and constants.
|
||||||
|
// The module defines the following functions:
|
||||||
|
//
|
||||||
|
// from_timestamp(sec, nsec) - Converts the given Unix time corresponding to the number of seconds
|
||||||
|
// and (optionally) nanoseconds since January 1, 1970 UTC into an object
|
||||||
|
// of type Time. For more details, refer to https://pkg.go.dev/time#Unix.
|
||||||
|
//
|
||||||
|
// is_valid_timezone(loc) - Reports whether loc is a valid time zone name.
|
||||||
|
//
|
||||||
|
// now() - Returns the current local time. Applications may replace this function by a deterministic one.
|
||||||
|
//
|
||||||
|
// parse_duration(d) - Parses the given duration string. For more details, refer to
|
||||||
|
// https://pkg.go.dev/time#ParseDuration.
|
||||||
|
//
|
||||||
|
// parseTime(x, format, location) - Parses the given time string using a specific time format and location.
|
||||||
|
// The expected arguments are a time string (mandatory), a time format
|
||||||
|
// (optional, set to RFC3339 by default, e.g. "2021-03-22T23:20:50.52Z")
|
||||||
|
// and a name of location (optional, set to UTC by default). For more details,
|
||||||
|
// refer to https://pkg.go.dev/time#Parse and https://pkg.go.dev/time#ParseInLocation.
|
||||||
|
//
|
||||||
|
// time(year, month, day, hour, minute, second, nanosecond, location) - Returns the Time corresponding to
|
||||||
|
// yyyy-mm-dd hh:mm:ss + nsec nanoseconds
|
||||||
|
// in the appropriate zone for that time
|
||||||
|
// in the given location. All the parameters
|
||||||
|
// are optional.
|
||||||
|
// The module also defines the following constants:
|
||||||
|
//
|
||||||
|
// nanosecond - A duration representing one nanosecond.
|
||||||
|
// microsecond - A duration representing one microsecond.
|
||||||
|
// millisecond - A duration representing one millisecond.
|
||||||
|
// second - A duration representing one second.
|
||||||
|
// minute - A duration representing one minute.
|
||||||
|
// hour - A duration representing one hour.
|
||||||
|
//
|
||||||
|
var Module = &starlarkstruct.Module{
|
||||||
|
Name: "time",
|
||||||
|
Members: starlark.StringDict{
|
||||||
|
"from_timestamp": starlark.NewBuiltin("from_timestamp", fromTimestamp),
|
||||||
|
"is_valid_timezone": starlark.NewBuiltin("is_valid_timezone", isValidTimezone),
|
||||||
|
"now": starlark.NewBuiltin("now", now),
|
||||||
|
"parse_duration": starlark.NewBuiltin("parse_duration", parseDuration),
|
||||||
|
"parse_time": starlark.NewBuiltin("parse_time", parseTime),
|
||||||
|
"time": starlark.NewBuiltin("time", newTime),
|
||||||
|
|
||||||
|
"nanosecond": Duration(time.Nanosecond),
|
||||||
|
"microsecond": Duration(time.Microsecond),
|
||||||
|
"millisecond": Duration(time.Millisecond),
|
||||||
|
"second": Duration(time.Second),
|
||||||
|
"minute": Duration(time.Minute),
|
||||||
|
"hour": Duration(time.Hour),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// NowFunc is a function that generates the current time. Intentionally exported
|
||||||
|
// so that it can be overridden, for example by applications that require their
|
||||||
|
// Starlark scripts to be fully deterministic.
|
||||||
|
var NowFunc = time.Now
|
||||||
|
|
||||||
|
func parseDuration(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var d Duration
|
||||||
|
err := starlark.UnpackPositionalArgs("parse_duration", args, kwargs, 1, &d)
|
||||||
|
return d, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidTimezone(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var s string
|
||||||
|
if err := starlark.UnpackPositionalArgs("is_valid_timezone", args, kwargs, 1, &s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err := time.LoadLocation(s)
|
||||||
|
return starlark.Bool(err == nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var (
|
||||||
|
x string
|
||||||
|
location = "UTC"
|
||||||
|
format = time.RFC3339
|
||||||
|
)
|
||||||
|
if err := starlark.UnpackArgs("parse_time", args, kwargs, "x", &x, "format?", &format, "location?", &location); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if location == "UTC" {
|
||||||
|
t, err := time.Parse(format, x)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Time(t), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
loc, err := time.LoadLocation(location)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t, err := time.ParseInLocation(format, x, loc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Time(t), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromTimestamp(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var (
|
||||||
|
sec int64
|
||||||
|
nsec int64 = 0
|
||||||
|
)
|
||||||
|
if err := starlark.UnpackPositionalArgs("from_timestamp", args, kwargs, 1, &sec, &nsec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Time(time.Unix(sec, nsec)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func now(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
return Time(NowFunc()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration is a Starlark representation of a duration.
|
||||||
|
type Duration time.Duration
|
||||||
|
|
||||||
|
// Assert at compile time that Duration implements Unpacker.
|
||||||
|
var _ starlark.Unpacker = (*Duration)(nil)
|
||||||
|
|
||||||
|
// Unpack is a custom argument unpacker
|
||||||
|
func (d *Duration) Unpack(v starlark.Value) error {
|
||||||
|
switch x := v.(type) {
|
||||||
|
case Duration:
|
||||||
|
*d = x
|
||||||
|
return nil
|
||||||
|
case starlark.String:
|
||||||
|
dur, err := time.ParseDuration(string(x))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = Duration(dur)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("got %s, want a duration, string, or int", v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements the Stringer interface.
|
||||||
|
func (d Duration) String() string { return time.Duration(d).String() }
|
||||||
|
|
||||||
|
// Type returns a short string describing the value's type.
|
||||||
|
func (d Duration) Type() string { return "time.duration" }
|
||||||
|
|
||||||
|
// Freeze renders Duration immutable. required by starlark.Value interface
|
||||||
|
// because duration is already immutable this is a no-op.
|
||||||
|
func (d Duration) Freeze() {}
|
||||||
|
|
||||||
|
// Hash returns a function of x such that Equals(x, y) => Hash(x) == Hash(y)
|
||||||
|
// required by starlark.Value interface.
|
||||||
|
func (d Duration) Hash() (uint32, error) {
|
||||||
|
return uint32(d) ^ uint32(int64(d)>>32), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truth reports whether the duration is non-zero.
|
||||||
|
func (d Duration) Truth() starlark.Bool { return d != 0 }
|
||||||
|
|
||||||
|
// Attr gets a value for a string attribute, implementing dot expression support
|
||||||
|
// in starklark. required by starlark.HasAttrs interface.
|
||||||
|
func (d Duration) Attr(name string) (starlark.Value, error) {
|
||||||
|
switch name {
|
||||||
|
case "hours":
|
||||||
|
return starlark.Float(time.Duration(d).Hours()), nil
|
||||||
|
case "minutes":
|
||||||
|
return starlark.Float(time.Duration(d).Minutes()), nil
|
||||||
|
case "seconds":
|
||||||
|
return starlark.Float(time.Duration(d).Seconds()), nil
|
||||||
|
case "milliseconds":
|
||||||
|
return starlark.MakeInt64(time.Duration(d).Milliseconds()), nil
|
||||||
|
case "microseconds":
|
||||||
|
return starlark.MakeInt64(time.Duration(d).Microseconds()), nil
|
||||||
|
case "nanoseconds":
|
||||||
|
return starlark.MakeInt64(time.Duration(d).Nanoseconds()), nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unrecognized %s attribute %q", d.Type(), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttrNames lists available dot expression strings. required by
|
||||||
|
// starlark.HasAttrs interface.
|
||||||
|
func (d Duration) AttrNames() []string {
|
||||||
|
return []string{
|
||||||
|
"hours",
|
||||||
|
"minutes",
|
||||||
|
"seconds",
|
||||||
|
"milliseconds",
|
||||||
|
"microseconds",
|
||||||
|
"nanoseconds",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareSameType implements comparison of two Duration values. required by
|
||||||
|
// starlark.Comparable interface.
|
||||||
|
func (d Duration) CompareSameType(op syntax.Token, v starlark.Value, depth int) (bool, error) {
|
||||||
|
cmp := 0
|
||||||
|
if x, y := d, v.(Duration); x < y {
|
||||||
|
cmp = -1
|
||||||
|
} else if x > y {
|
||||||
|
cmp = 1
|
||||||
|
}
|
||||||
|
return threeway(op, cmp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary implements binary operators, which satisfies the starlark.HasBinary
|
||||||
|
// interface. operators:
|
||||||
|
// duration + duration = duration
|
||||||
|
// duration + time = time
|
||||||
|
// duration - duration = duration
|
||||||
|
// duration / duration = float
|
||||||
|
// duration / int = duration
|
||||||
|
// duration / float = duration
|
||||||
|
// duration // duration = int
|
||||||
|
// duration * int = duration
|
||||||
|
func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
|
||||||
|
x := time.Duration(d)
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case syntax.PLUS:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case Duration:
|
||||||
|
return Duration(x + time.Duration(y)), nil
|
||||||
|
case Time:
|
||||||
|
return Time(time.Time(y).Add(x)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case syntax.MINUS:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case Duration:
|
||||||
|
return Duration(x - time.Duration(y)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case syntax.SLASH:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case Duration:
|
||||||
|
if y == 0 {
|
||||||
|
return nil, fmt.Errorf("%s division by zero", d.Type())
|
||||||
|
}
|
||||||
|
return starlark.Float(x.Nanoseconds()) / starlark.Float(time.Duration(y).Nanoseconds()), nil
|
||||||
|
case starlark.Int:
|
||||||
|
if side == starlark.Right {
|
||||||
|
return nil, fmt.Errorf("unsupported operation")
|
||||||
|
}
|
||||||
|
i, ok := y.Int64()
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("int value out of range (want signed 64-bit value)")
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return nil, fmt.Errorf("%s division by zero", d.Type())
|
||||||
|
}
|
||||||
|
return d / Duration(i), nil
|
||||||
|
case starlark.Float:
|
||||||
|
f := float64(y)
|
||||||
|
if f == 0 {
|
||||||
|
return nil, fmt.Errorf("%s division by zero", d.Type())
|
||||||
|
}
|
||||||
|
return Duration(float64(x.Nanoseconds()) / f), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case syntax.SLASHSLASH:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case Duration:
|
||||||
|
if y == 0 {
|
||||||
|
return nil, fmt.Errorf("%s division by zero", d.Type())
|
||||||
|
}
|
||||||
|
return starlark.MakeInt64(x.Nanoseconds() / time.Duration(y).Nanoseconds()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case syntax.STAR:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case starlark.Int:
|
||||||
|
i, ok := y.Int64()
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("int value out of range (want signed 64-bit value)")
|
||||||
|
}
|
||||||
|
return d * Duration(i), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time is a Starlark representation of a moment in time.
|
||||||
|
type Time time.Time
|
||||||
|
|
||||||
|
func newTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var (
|
||||||
|
year, month, day, hour, min, sec, nsec int
|
||||||
|
loc string
|
||||||
|
)
|
||||||
|
if err := starlark.UnpackArgs("time", args, kwargs,
|
||||||
|
"year?", &year,
|
||||||
|
"month?", &month,
|
||||||
|
"day?", &day,
|
||||||
|
"hour?", &hour,
|
||||||
|
"minute?", &min,
|
||||||
|
"second?", &sec,
|
||||||
|
"nanosecond?", &nsec,
|
||||||
|
"location?", &loc,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(args) > 0 {
|
||||||
|
return nil, fmt.Errorf("time: unexpected positional arguments")
|
||||||
|
}
|
||||||
|
location, err := time.LoadLocation(loc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Time(time.Date(year, time.Month(month), day, hour, min, sec, nsec, location)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the time formatted using the format string
|
||||||
|
// "2006-01-02 15:04:05.999999999 -0700 MST".
|
||||||
|
func (t Time) String() string { return time.Time(t).String() }
|
||||||
|
|
||||||
|
// Type returns "time.time".
|
||||||
|
func (t Time) Type() string { return "time.time" }
|
||||||
|
|
||||||
|
// Freeze renders time immutable. required by starlark.Value interface
|
||||||
|
// because Time is already immutable this is a no-op.
|
||||||
|
func (t Time) Freeze() {}
|
||||||
|
|
||||||
|
// Hash returns a function of x such that Equals(x, y) => Hash(x) == Hash(y)
|
||||||
|
// required by starlark.Value interface.
|
||||||
|
func (t Time) Hash() (uint32, error) {
|
||||||
|
return uint32(time.Time(t).UnixNano()) ^ uint32(int64(time.Time(t).UnixNano())>>32), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truth returns the truth value of an object required by starlark.Value
|
||||||
|
// interface.
|
||||||
|
func (t Time) Truth() starlark.Bool { return starlark.Bool(time.Time(t).IsZero()) }
|
||||||
|
|
||||||
|
// Attr gets a value for a string attribute, implementing dot expression support
|
||||||
|
// in starklark. required by starlark.HasAttrs interface.
|
||||||
|
func (t Time) Attr(name string) (starlark.Value, error) {
|
||||||
|
switch name {
|
||||||
|
case "year":
|
||||||
|
return starlark.MakeInt(time.Time(t).Year()), nil
|
||||||
|
case "month":
|
||||||
|
return starlark.MakeInt(int(time.Time(t).Month())), nil
|
||||||
|
case "day":
|
||||||
|
return starlark.MakeInt(time.Time(t).Day()), nil
|
||||||
|
case "hour":
|
||||||
|
return starlark.MakeInt(time.Time(t).Hour()), nil
|
||||||
|
case "minute":
|
||||||
|
return starlark.MakeInt(time.Time(t).Minute()), nil
|
||||||
|
case "second":
|
||||||
|
return starlark.MakeInt(time.Time(t).Second()), nil
|
||||||
|
case "nanosecond":
|
||||||
|
return starlark.MakeInt(time.Time(t).Nanosecond()), nil
|
||||||
|
case "unix":
|
||||||
|
return starlark.MakeInt64(time.Time(t).Unix()), nil
|
||||||
|
case "unix_nano":
|
||||||
|
return starlark.MakeInt64(time.Time(t).UnixNano()), nil
|
||||||
|
}
|
||||||
|
return builtinAttr(t, name, timeMethods)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttrNames lists available dot expression strings for time. required by
|
||||||
|
// starlark.HasAttrs interface.
|
||||||
|
func (t Time) AttrNames() []string {
|
||||||
|
return append(builtinAttrNames(timeMethods),
|
||||||
|
"year",
|
||||||
|
"month",
|
||||||
|
"day",
|
||||||
|
"hour",
|
||||||
|
"minute",
|
||||||
|
"second",
|
||||||
|
"nanosecond",
|
||||||
|
"unix",
|
||||||
|
"unix_nano",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareSameType implements comparison of two Time values. required by
|
||||||
|
// starlark.Comparable interface.
|
||||||
|
func (t Time) CompareSameType(op syntax.Token, yV starlark.Value, depth int) (bool, error) {
|
||||||
|
x := time.Time(t)
|
||||||
|
y := time.Time(yV.(Time))
|
||||||
|
cmp := 0
|
||||||
|
if x.Before(y) {
|
||||||
|
cmp = -1
|
||||||
|
} else if x.After(y) {
|
||||||
|
cmp = 1
|
||||||
|
}
|
||||||
|
return threeway(op, cmp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary implements binary operators, which satisfies the starlark.HasBinary
|
||||||
|
// interface
|
||||||
|
// time + duration = time
|
||||||
|
// time - duration = time
|
||||||
|
// time - time = duration
|
||||||
|
func (t Time) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
|
||||||
|
x := time.Time(t)
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case syntax.PLUS:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case Duration:
|
||||||
|
return Time(x.Add(time.Duration(y))), nil
|
||||||
|
}
|
||||||
|
case syntax.MINUS:
|
||||||
|
switch y := y.(type) {
|
||||||
|
case Duration:
|
||||||
|
return Time(x.Add(time.Duration(-y))), nil
|
||||||
|
case Time:
|
||||||
|
// time - time = duration
|
||||||
|
return Duration(x.Sub(time.Time(y))), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeMethods = map[string]builtinMethod{
|
||||||
|
"in_location": timeIn,
|
||||||
|
"format": timeFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeFormat(fnname string, recV starlark.Value, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var x string
|
||||||
|
if err := starlark.UnpackPositionalArgs("format", args, kwargs, 1, &x); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
recv := time.Time(recV.(Time))
|
||||||
|
return starlark.String(recv.Format(x)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeIn(fnname string, recV starlark.Value, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var x string
|
||||||
|
if err := starlark.UnpackPositionalArgs("in_location", args, kwargs, 1, &x); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
loc, err := time.LoadLocation(x)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
recv := time.Time(recV.(Time))
|
||||||
|
return Time(recv.In(loc)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type builtinMethod func(fnname string, recv starlark.Value, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error)
|
||||||
|
|
||||||
|
func builtinAttr(recv starlark.Value, name string, methods map[string]builtinMethod) (starlark.Value, error) {
|
||||||
|
method := methods[name]
|
||||||
|
if method == nil {
|
||||||
|
return nil, nil // no such method
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a closure over 'method'.
|
||||||
|
impl := func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
return method(b.Name(), b.Receiver(), args, kwargs)
|
||||||
|
}
|
||||||
|
return starlark.NewBuiltin(name, impl).BindReceiver(recv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func builtinAttrNames(methods map[string]builtinMethod) []string {
|
||||||
|
names := make([]string, 0, len(methods))
|
||||||
|
for name := range methods {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
// Threeway interprets a three-way comparison value cmp (-1, 0, +1)
|
||||||
|
// as a boolean comparison (e.g. x < y).
|
||||||
|
func threeway(op syntax.Token, cmp int) bool {
|
||||||
|
switch op {
|
||||||
|
case syntax.EQL:
|
||||||
|
return cmp == 0
|
||||||
|
case syntax.NEQ:
|
||||||
|
return cmp != 0
|
||||||
|
case syntax.LE:
|
||||||
|
return cmp <= 0
|
||||||
|
case syntax.LT:
|
||||||
|
return cmp < 0
|
||||||
|
case syntax.GE:
|
||||||
|
return cmp >= 0
|
||||||
|
case syntax.GT:
|
||||||
|
return cmp > 0
|
||||||
|
}
|
||||||
|
panic(op)
|
||||||
|
}
|
||||||
43
vendor/go.starlark.net/starlarkstruct/module.go
generated
vendored
Normal file
43
vendor/go.starlark.net/starlarkstruct/module.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package starlarkstruct
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Module is a named collection of values,
|
||||||
|
// typically a suite of functions imported by a load statement.
|
||||||
|
//
|
||||||
|
// It differs from Struct primarily in that its string representation
|
||||||
|
// does not enumerate its fields.
|
||||||
|
type Module struct {
|
||||||
|
Name string
|
||||||
|
Members starlark.StringDict
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ starlark.HasAttrs = (*Module)(nil)
|
||||||
|
|
||||||
|
func (m *Module) Attr(name string) (starlark.Value, error) { return m.Members[name], nil }
|
||||||
|
func (m *Module) AttrNames() []string { return m.Members.Keys() }
|
||||||
|
func (m *Module) Freeze() { m.Members.Freeze() }
|
||||||
|
func (m *Module) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", m.Type()) }
|
||||||
|
func (m *Module) String() string { return fmt.Sprintf("<module %q>", m.Name) }
|
||||||
|
func (m *Module) Truth() starlark.Bool { return true }
|
||||||
|
func (m *Module) Type() string { return "module" }
|
||||||
|
|
||||||
|
// MakeModule may be used as the implementation of a Starlark built-in
|
||||||
|
// function, module(name, **kwargs). It returns a new module with the
|
||||||
|
// specified name and members.
|
||||||
|
func MakeModule(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var name string
|
||||||
|
if err := starlark.UnpackPositionalArgs(b.Name(), args, nil, 1, &name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
members := make(starlark.StringDict, len(kwargs))
|
||||||
|
for _, kwarg := range kwargs {
|
||||||
|
k := string(kwarg[0].(starlark.String))
|
||||||
|
members[k] = kwarg[1]
|
||||||
|
}
|
||||||
|
return &Module{name, members}, nil
|
||||||
|
}
|
||||||
281
vendor/go.starlark.net/starlarkstruct/struct.go
generated
vendored
Normal file
281
vendor/go.starlark.net/starlarkstruct/struct.go
generated
vendored
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
// Copyright 2017 The Bazel Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package starlarkstruct defines the Starlark types 'struct' and
|
||||||
|
// 'module', both optional language extensions.
|
||||||
|
//
|
||||||
|
package starlarkstruct // import "go.starlark.net/starlarkstruct"
|
||||||
|
|
||||||
|
// It is tempting to introduce a variant of Struct that is a wrapper
|
||||||
|
// around a Go struct value, for stronger typing guarantees and more
|
||||||
|
// efficient and convenient field lookup. However:
|
||||||
|
// 1) all fields of Starlark structs are optional, so we cannot represent
|
||||||
|
// them using more specific types such as String, Int, *Depset, and
|
||||||
|
// *File, as such types give no way to represent missing fields.
|
||||||
|
// 2) the efficiency gain of direct struct field access is rather
|
||||||
|
// marginal: finding the index of a field by binary searching on the
|
||||||
|
// sorted list of field names is quite fast compared to the other
|
||||||
|
// overheads.
|
||||||
|
// 3) the gains in compactness and spatial locality are also rather
|
||||||
|
// marginal: the array behind the []entry slice is (due to field name
|
||||||
|
// strings) only a factor of 2 larger than the corresponding Go struct
|
||||||
|
// would be, and, like the Go struct, requires only a single allocation.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Make is the implementation of a built-in function that instantiates
|
||||||
|
// an immutable struct from the specified keyword arguments.
|
||||||
|
//
|
||||||
|
// An application can add 'struct' to the Starlark environment like so:
|
||||||
|
//
|
||||||
|
// globals := starlark.StringDict{
|
||||||
|
// "struct": starlark.NewBuiltin("struct", starlarkstruct.Make),
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Make(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
if len(args) > 0 {
|
||||||
|
return nil, fmt.Errorf("struct: unexpected positional arguments")
|
||||||
|
}
|
||||||
|
return FromKeywords(Default, kwargs), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromKeywords returns a new struct instance whose fields are specified by the
|
||||||
|
// key/value pairs in kwargs. (Each kwargs[i][0] must be a starlark.String.)
|
||||||
|
func FromKeywords(constructor starlark.Value, kwargs []starlark.Tuple) *Struct {
|
||||||
|
if constructor == nil {
|
||||||
|
panic("nil constructor")
|
||||||
|
}
|
||||||
|
s := &Struct{
|
||||||
|
constructor: constructor,
|
||||||
|
entries: make(entries, 0, len(kwargs)),
|
||||||
|
}
|
||||||
|
for _, kwarg := range kwargs {
|
||||||
|
k := string(kwarg[0].(starlark.String))
|
||||||
|
v := kwarg[1]
|
||||||
|
s.entries = append(s.entries, entry{k, v})
|
||||||
|
}
|
||||||
|
sort.Sort(s.entries)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStringDict returns a new struct instance whose elements are those of d.
|
||||||
|
// The constructor parameter specifies the constructor; use Default for an ordinary struct.
|
||||||
|
func FromStringDict(constructor starlark.Value, d starlark.StringDict) *Struct {
|
||||||
|
if constructor == nil {
|
||||||
|
panic("nil constructor")
|
||||||
|
}
|
||||||
|
s := &Struct{
|
||||||
|
constructor: constructor,
|
||||||
|
entries: make(entries, 0, len(d)),
|
||||||
|
}
|
||||||
|
for k, v := range d {
|
||||||
|
s.entries = append(s.entries, entry{k, v})
|
||||||
|
}
|
||||||
|
sort.Sort(s.entries)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Struct is an immutable Starlark type that maps field names to values.
|
||||||
|
// It is not iterable and does not support len.
|
||||||
|
//
|
||||||
|
// A struct has a constructor, a distinct value that identifies a class
|
||||||
|
// of structs, and which appears in the struct's string representation.
|
||||||
|
//
|
||||||
|
// Operations such as x+y fail if the constructors of the two operands
|
||||||
|
// are not equal.
|
||||||
|
//
|
||||||
|
// The default constructor, Default, is the string "struct", but
|
||||||
|
// clients may wish to 'brand' structs for their own purposes.
|
||||||
|
// The constructor value appears in the printed form of the value,
|
||||||
|
// and is accessible using the Constructor method.
|
||||||
|
//
|
||||||
|
// Use Attr to access its fields and AttrNames to enumerate them.
|
||||||
|
type Struct struct {
|
||||||
|
constructor starlark.Value
|
||||||
|
entries entries // sorted by name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default is the default constructor for structs.
|
||||||
|
// It is merely the string "struct".
|
||||||
|
const Default = starlark.String("struct")
|
||||||
|
|
||||||
|
type entries []entry
|
||||||
|
|
||||||
|
func (a entries) Len() int { return len(a) }
|
||||||
|
func (a entries) Less(i, j int) bool { return a[i].name < a[j].name }
|
||||||
|
func (a entries) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
name string
|
||||||
|
value starlark.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ starlark.HasAttrs = (*Struct)(nil)
|
||||||
|
_ starlark.HasBinary = (*Struct)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToStringDict adds a name/value entry to d for each field of the struct.
|
||||||
|
func (s *Struct) ToStringDict(d starlark.StringDict) {
|
||||||
|
for _, e := range s.entries {
|
||||||
|
d[e.name] = e.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) String() string {
|
||||||
|
buf := new(strings.Builder)
|
||||||
|
if s.constructor == Default {
|
||||||
|
// NB: The Java implementation always prints struct
|
||||||
|
// even for Bazel provider instances.
|
||||||
|
buf.WriteString("struct") // avoid String()'s quotation
|
||||||
|
} else {
|
||||||
|
buf.WriteString(s.constructor.String())
|
||||||
|
}
|
||||||
|
buf.WriteByte('(')
|
||||||
|
for i, e := range s.entries {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteString(", ")
|
||||||
|
}
|
||||||
|
buf.WriteString(e.name)
|
||||||
|
buf.WriteString(" = ")
|
||||||
|
buf.WriteString(e.value.String())
|
||||||
|
}
|
||||||
|
buf.WriteByte(')')
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor returns the constructor used to create this struct.
|
||||||
|
func (s *Struct) Constructor() starlark.Value { return s.constructor }
|
||||||
|
|
||||||
|
func (s *Struct) Type() string { return "struct" }
|
||||||
|
func (s *Struct) Truth() starlark.Bool { return true } // even when empty
|
||||||
|
func (s *Struct) Hash() (uint32, error) {
|
||||||
|
// Same algorithm as Tuple.hash, but with different primes.
|
||||||
|
var x, m uint32 = 8731, 9839
|
||||||
|
for _, e := range s.entries {
|
||||||
|
namehash, _ := starlark.String(e.name).Hash()
|
||||||
|
x = x ^ 3*namehash
|
||||||
|
y, err := e.value.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
x = x ^ y*m
|
||||||
|
m += 7349
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
func (s *Struct) Freeze() {
|
||||||
|
for _, e := range s.entries {
|
||||||
|
e.value.Freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Struct) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
|
||||||
|
if y, ok := y.(*Struct); ok && op == syntax.PLUS {
|
||||||
|
if side == starlark.Right {
|
||||||
|
x, y = y, x
|
||||||
|
}
|
||||||
|
|
||||||
|
if eq, err := starlark.Equal(x.constructor, y.constructor); err != nil {
|
||||||
|
return nil, fmt.Errorf("in %s + %s: error comparing constructors: %v",
|
||||||
|
x.constructor, y.constructor, err)
|
||||||
|
} else if !eq {
|
||||||
|
return nil, fmt.Errorf("cannot add structs of different constructors: %s + %s",
|
||||||
|
x.constructor, y.constructor)
|
||||||
|
}
|
||||||
|
|
||||||
|
z := make(starlark.StringDict, x.len()+y.len())
|
||||||
|
for _, e := range x.entries {
|
||||||
|
z[e.name] = e.value
|
||||||
|
}
|
||||||
|
for _, e := range y.entries {
|
||||||
|
z[e.name] = e.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return FromStringDict(x.constructor, z), nil
|
||||||
|
}
|
||||||
|
return nil, nil // unhandled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attr returns the value of the specified field.
|
||||||
|
func (s *Struct) Attr(name string) (starlark.Value, error) {
|
||||||
|
// Binary search the entries.
|
||||||
|
// This implementation is a specialization of
|
||||||
|
// sort.Search that avoids dynamic dispatch.
|
||||||
|
n := len(s.entries)
|
||||||
|
i, j := 0, n
|
||||||
|
for i < j {
|
||||||
|
h := int(uint(i+j) >> 1)
|
||||||
|
if s.entries[h].name < name {
|
||||||
|
i = h + 1
|
||||||
|
} else {
|
||||||
|
j = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i < n && s.entries[i].name == name {
|
||||||
|
return s.entries[i].value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var ctor string
|
||||||
|
if s.constructor != Default {
|
||||||
|
ctor = s.constructor.String() + " "
|
||||||
|
}
|
||||||
|
return nil, starlark.NoSuchAttrError(
|
||||||
|
fmt.Sprintf("%sstruct has no .%s attribute", ctor, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) len() int { return len(s.entries) }
|
||||||
|
|
||||||
|
// AttrNames returns a new sorted list of the struct fields.
|
||||||
|
func (s *Struct) AttrNames() []string {
|
||||||
|
names := make([]string, len(s.entries))
|
||||||
|
for i, e := range s.entries {
|
||||||
|
names[i] = e.name
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Struct) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) {
|
||||||
|
y := y_.(*Struct)
|
||||||
|
switch op {
|
||||||
|
case syntax.EQL:
|
||||||
|
return structsEqual(x, y, depth)
|
||||||
|
case syntax.NEQ:
|
||||||
|
eq, err := structsEqual(x, y, depth)
|
||||||
|
return !eq, err
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func structsEqual(x, y *Struct, depth int) (bool, error) {
|
||||||
|
if x.len() != y.len() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if eq, err := starlark.Equal(x.constructor, y.constructor); err != nil {
|
||||||
|
return false, fmt.Errorf("error comparing struct constructors %v and %v: %v",
|
||||||
|
x.constructor, y.constructor, err)
|
||||||
|
} else if !eq {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, n := 0, x.len(); i < n; i++ {
|
||||||
|
if x.entries[i].name != y.entries[i].name {
|
||||||
|
return false, nil
|
||||||
|
} else if eq, err := starlark.EqualDepth(x.entries[i].value, y.entries[i].value, depth-1); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !eq {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -62,8 +62,10 @@ github.com/spf13/pflag
|
|||||||
## explicit
|
## explicit
|
||||||
go.starlark.net/internal/compile
|
go.starlark.net/internal/compile
|
||||||
go.starlark.net/internal/spell
|
go.starlark.net/internal/spell
|
||||||
|
go.starlark.net/lib/time
|
||||||
go.starlark.net/resolve
|
go.starlark.net/resolve
|
||||||
go.starlark.net/starlark
|
go.starlark.net/starlark
|
||||||
|
go.starlark.net/starlarkstruct
|
||||||
go.starlark.net/syntax
|
go.starlark.net/syntax
|
||||||
# golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4
|
# golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4
|
||||||
## explicit
|
## explicit
|
||||||
|
|||||||
Reference in New Issue
Block a user