Skip to content

Commit a4a3b8a

Browse files
committed
time: Applied remarks
1 parent 4760e8f commit a4a3b8a

File tree

3 files changed

+146
-119
lines changed

3 files changed

+146
-119
lines changed

cmd/starlark/starlark.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func doMain() int {
9292
// Ideally this statement would update the predeclared environment.
9393
// TODO(adonovan): plumb predeclared env through to the REPL.
9494
starlark.Universe["json"] = starlarkjson.Module
95-
starlark.Universe[time.ModuleName] = time.Module
95+
starlark.Universe["time"] = time.Module
9696

9797
switch {
9898
case flag.NArg() == 1 || *execprog != "":

lib/time/time.go

Lines changed: 46 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,15 @@ import (
1111
"go.starlark.net/syntax"
1212
)
1313

14-
// ModuleName defines the expected name for this Module when used in the
15-
// starlark runtime.
16-
const ModuleName = "time"
17-
1814
// Module time is a Starlark module of time-related functions.
1915
var Module = &starlarkstruct.Module{
20-
Name: ModuleName,
16+
Name: "time",
2117
Members: starlark.StringDict{
2218
"parse_duration": starlark.NewBuiltin("parse_duration", parseDuration),
2319
"parse_location": starlark.NewBuiltin("parse_location", parseLocation),
2420
"now": starlark.NewBuiltin("now", now),
2521
"time": starlark.NewBuiltin("time", newTime),
2622
"parse_time": starlark.NewBuiltin("time", parseTime),
27-
"sleep": starlark.NewBuiltin("sleep", sleep),
2823
"from_timestamp": starlark.NewBuiltin("from_timestamp", fromTimestamp),
2924

3025
"nanosecond": Duration(time.Nanosecond),
@@ -36,14 +31,6 @@ var Module = &starlarkstruct.Module{
3631
},
3732
}
3833

39-
// LoadModule loads the time module.
40-
// It is concurrency-safe and idempotent.
41-
func LoadModule() (starlark.StringDict, error) {
42-
return starlark.StringDict{
43-
ModuleName: Module,
44-
}, nil
45-
}
46-
4734
// NowFunc is a function that generates the current time. Intentionally exported
4835
// so that it can be overridden, for example by applications that require their
4936
// Starlark scripts to be fully deterministic.
@@ -68,21 +55,6 @@ func parseLocation(thread *starlark.Thread, _ *starlark.Builtin, args starlark.T
6855
return starlark.String(loc.String()), nil
6956
}
7057

71-
// SleepFunc is a function that pauses the current goroutine for at least d.
72-
// Intentionally exported so that it can be overridden, for example by
73-
// applications that require their Starlark scripts to be fully deterministic.
74-
var SleepFunc = time.Sleep
75-
76-
func sleep(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
77-
var dur Duration
78-
if err := starlark.UnpackPositionalArgs("sleep", args, kwargs, 1, &dur); err != nil {
79-
return starlark.None, err
80-
}
81-
82-
SleepFunc(time.Duration(dur))
83-
return starlark.None, nil
84-
}
85-
8658
func parseTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
8759
var (
8860
x, location string
@@ -135,13 +107,6 @@ func (d *Duration) Unpack(v starlark.Value) error {
135107
case Duration:
136108
*d = x
137109
return nil
138-
case starlark.Int:
139-
i, ok := x.Int64()
140-
if !ok {
141-
return fmt.Errorf("int value out of range (want signed 64-bit value)")
142-
}
143-
*d = Duration(i)
144-
return nil
145110
case starlark.String:
146111
dur, err := time.ParseDuration(string(x))
147112
if err != nil {
@@ -159,7 +124,7 @@ func (d *Duration) Unpack(v starlark.Value) error {
159124
func (d Duration) String() string { return time.Duration(d).String() }
160125

161126
// Type returns a short string describing the value's type.
162-
func (d Duration) Type() string { return ModuleName + ".duration" }
127+
func (d Duration) Type() string { return "time.duration" }
163128

164129
// Freeze renders Duration immutable. required by starlark.Value interface
165130
// because duration is already immutable this is a no-op.
@@ -236,54 +201,67 @@ func (d Duration) CompareSameType(op syntax.Token, v starlark.Value, depth int)
236201
// duration - duration = duration
237202
// duration / duration = float
238203
// duration / int = duration
204+
// duration / float = duration
239205
// duration // duration = int
240206
// duration // int = duration
241207
// duration * int = duration
242-
func (d Duration) Binary(op syntax.Token, yV starlark.Value, _ starlark.Side) (starlark.Value, error) {
208+
func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
243209
x := time.Duration(d)
244210

245211
switch op {
246212
case syntax.PLUS:
247-
switch y := yV.(type) {
213+
switch y := y.(type) {
248214
case Duration:
249215
return Duration(x + time.Duration(y)), nil
250216
case Time:
251217
return Time(time.Time(y).Add(x)), nil
252218
}
253219

254220
case syntax.MINUS:
255-
switch y := yV.(type) {
221+
switch y := y.(type) {
256222
case Duration:
257223
return Duration(x - time.Duration(y)), nil
258224
}
259225

260226
case syntax.SLASH:
261-
switch y := yV.(type) {
227+
switch y := y.(type) {
262228
case Duration:
263229
if int64(y) == 0 {
264230
return nil, fmt.Errorf("%s division by zero", d.Type())
265231
}
266232
return starlark.Float(float64(x.Nanoseconds()) / float64(time.Duration(y).Nanoseconds())), nil
267233
case starlark.Int:
234+
if side == starlark.Right {
235+
return nil, fmt.Errorf("unsupported operation")
236+
}
268237
i, ok := y.Int64()
269238
if !ok {
270239
return nil, fmt.Errorf("int value out of range (want signed 64-bit value)")
271240
}
272241
if int64(i) == 0 {
273242
return nil, fmt.Errorf("%s division by zero", d.Type())
274243
}
275-
return Duration(d / Duration(i)), nil
244+
return Duration(x.Nanoseconds() / i), nil
245+
case starlark.Float:
246+
f := float64(y)
247+
if f == 0 {
248+
return nil, fmt.Errorf("%s division by zero", d.Type())
249+
}
250+
return Duration(float64(x.Nanoseconds()) / f), nil
276251
}
277252

278253
case syntax.SLASHSLASH:
279-
switch y := yV.(type) {
254+
switch y := y.(type) {
280255
case Duration:
281256
if int64(y) == 0 {
282257
return nil, fmt.Errorf("%s division by zero", d.Type())
283258
}
284259
return starlark.MakeInt64(x.Nanoseconds() / time.Duration(y).Nanoseconds()), nil
285260
case starlark.Int:
286-
i, ok := yV.(starlark.Int).Int64()
261+
if side == starlark.Right {
262+
return nil, fmt.Errorf("unsupported operation")
263+
}
264+
i, ok := y.Int64()
287265
if !ok {
288266
return nil, fmt.Errorf("int value out of range (want signed 64-bit value)")
289267
}
@@ -294,7 +272,7 @@ func (d Duration) Binary(op syntax.Token, yV starlark.Value, _ starlark.Side) (s
294272
}
295273

296274
case syntax.STAR:
297-
switch y := yV.(type) {
275+
switch y := y.(type) {
298276
case starlark.Int:
299277
i, ok := y.Int64()
300278
if !ok {
@@ -307,17 +285,29 @@ func (d Duration) Binary(op syntax.Token, yV starlark.Value, _ starlark.Side) (s
307285
return nil, nil
308286
}
309287

310-
// Time is a starlark representation of a point in time.
288+
// Time is a starlark representation of a moment in time.
311289
type Time time.Time
312290

313291
func newTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
314292
var (
315293
year, month, day, hour, min, sec, nsec int
316294
loc string
317295
)
318-
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 {
296+
if err := starlark.UnpackArgs("time", args, kwargs,
297+
"year?", &year,
298+
"month?", &month,
299+
"day?", &day,
300+
"hour?", &hour,
301+
"minute?", &min,
302+
"second?", &sec,
303+
"nanosecond?", &nsec,
304+
"location?", &loc,
305+
); err != nil {
319306
return nil, err
320307
}
308+
if len(args) > 0 {
309+
return nil, fmt.Errorf("time: unexpected positional arguments")
310+
}
321311
location, err := time.LoadLocation(loc)
322312
if err != nil {
323313
return nil, err
@@ -330,7 +320,7 @@ func newTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple,
330320
func (t Time) String() string { return time.Time(t).String() }
331321

332322
// Type returns "time.time".
333-
func (t Time) Type() string { return ModuleName + ".time" }
323+
func (t Time) Type() string { return "time.time" }
334324

335325
// Freeze renders time immutable. required by starlark.Value interface
336326
// because Time is already immutable this is a no-op.
@@ -393,40 +383,36 @@ func (t Time) AttrNames() []string {
393383
func (t Time) CompareSameType(op syntax.Token, yV starlark.Value, depth int) (bool, error) {
394384
x := time.Time(t)
395385
y := time.Time(yV.(Time))
396-
cp := 0
386+
cmp := 0
397387
if x.Before(y) {
398-
cp = -1
388+
cmp = -1
399389
} else if x.After(y) {
400-
cp = 1
390+
cmp = 1
401391
}
402-
return threeway(op, cp), nil
392+
return threeway(op, cmp), nil
403393
}
404394

405395
// Binary implements binary operators, which satisfies the starlark.HasBinary
406396
// interface
407397
// time + duration = time
408398
// time - duration = time
409399
// time - time = duration
410-
func (t Time) Binary(op syntax.Token, yV starlark.Value, side starlark.Side) (starlark.Value, error) {
400+
func (t Time) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
411401
x := time.Time(t)
412402

413403
switch op {
414404
case syntax.PLUS:
415-
switch y := yV.(type) {
405+
switch y := y.(type) {
416406
case Duration:
417407
return Time(x.Add(time.Duration(y))), nil
418408
}
419409
case syntax.MINUS:
420-
switch y := yV.(type) {
410+
switch y := y.(type) {
421411
case Duration:
422412
return Time(x.Add(time.Duration(-y))), nil
423413
case Time:
424414
// time - time = duration
425-
if side == starlark.Left {
426-
return Duration(x.Sub(time.Time(y))), nil
427-
} else {
428-
return Duration(time.Time(y).Sub(x)), nil
429-
}
415+
return Duration(x.Sub(time.Time(y))), nil
430416
}
431417
}
432418

0 commit comments

Comments
 (0)