Skip to content

Commit

Permalink
[ysh breaking] 1 .. 5 range replaced with 1..<5 half open and 1..=5 c…
Browse files Browse the repository at this point in the history
…losed range (#2102)

This is issue #2096
  • Loading branch information
PossiblyAShrub authored Oct 25, 2024
1 parent 4757190 commit 6e5ce18
Show file tree
Hide file tree
Showing 30 changed files with 130 additions and 67 deletions.
2 changes: 1 addition & 1 deletion display/pp_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def _Value(self, val):
elif case(value_e.Range):
r = cast(value.Range, val)
type_name = self._Styled(self.type_style, UText(ValType(r)))
mdocs = [UText(str(r.lower)), UText(".."), UText(str(r.upper))]
mdocs = [UText(str(r.lower)), UText("..<"), UText(str(r.upper))]
return self._SurroundedAndPrefixed("(", type_name, " ",
self._Join(mdocs, "", " "),
")")
Expand Down
26 changes: 26 additions & 0 deletions doc/error-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,32 @@ standard boolean operators are written as `a and b`, `a or b` and `not a`.
This differs from [command mode](command-vs-expression-mode.html) which uses
shell-like `||` for "OR", `&&` for "AND" and `!` for "NOT".

### OILS-ERR-16

```
for x in (1 .. 5) {
^~
[ -c flag ]:1: Use ..< for half-open range, or ..= for closed range (OILS-ERR-16)
```

There are two ways to construct a [Range](ref/chap-expr-lang#range). The `..<`
operator is for half-open ranges and the `..=` operator is for closed ranges:

for i in (0 ..< 3) {
echo $i
}
=> 0
=> 1
=> 2

for i in (0 ..= 3) {
echo $i
}
=> 0
=> 1
=> 2
=> 3

## Runtime Errors - Traditional Shell

These errors may occur in shells like [bash]($xref) and [zsh]($xref).
Expand Down
14 changes: 9 additions & 5 deletions doc/ref/chap-expr-lang.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,21 +231,25 @@ the same name:

### range

A range is a sequence of numbers that can be iterated over:
A Range is a sequence of numbers that can be iterated over. The `..<` operator
constructs half-open ranges.

for i in (0 .. 3) {
for i in (0 ..< 3) {
echo $i
}
=> 0
=> 1
=> 2

As with slices, the last number isn't included. To iterate from 1 to n, you
can use this idiom:
The `..=` operator constructs closed ranges:

for i in (1 .. n+1) {
for i in (0 ..= 3) {
echo $i
}
=> 0
=> 1
=> 2
=> 3

### block-expr

Expand Down
2 changes: 1 addition & 1 deletion doc/ref/toc-ysh.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ X [External Lang] BEGIN END when (awk)
str-template ^"$a and $b" for Str::replace()
list-literal ['one', 'two', 3] :| unquoted words |
dict-literal {name: 'bob'} {a, b}
range 1 .. n+1
range 1 ..< n 1 ..= n
block-expr ^(echo $PWD)
expr-literal ^[1 + 2*3]
X expr-sub $[myobj]
Expand Down
4 changes: 2 additions & 2 deletions doc/ysh-tour.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ Ask for the loop index:
To iterate over a typed data, use parentheses around an **expression**. The
expression should evaluate to an integer `Range`, `List`, or `Dict`:

for i in (3 .. 5) { # range operator ..
for i in (3 ..< 5) { # range operator ..<
echo "i = $i"
}
# =>
Expand Down Expand Up @@ -740,7 +740,7 @@ Here's a pure function:

func myRepeat(s, n; special=false) { # positional; named params
var parts = []
for i in (0 .. n) {
for i in (0 ..< n) {
append $s (parts)
}
var result = join(parts)
Expand Down
5 changes: 3 additions & 2 deletions frontend/id_kind_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def AddKinds(spec):
# $'\z' Such bad codes are accepted when parse_backslash is on
# (default in OSH), so we have to lex them.
# (x == y) should used === or ~==
spec.AddKind('Unknown', ['Tok', 'Backslash', 'DEqual', 'DAmp', 'DPipe'])
spec.AddKind('Unknown', ['Tok', 'Backslash', 'DEqual', 'DAmp', 'DPipe', 'DDot'])

spec.AddKind('Eol', ['Tok']) # no more tokens on line (\0)

Expand Down Expand Up @@ -333,7 +333,8 @@ def AddKinds(spec):
'Float',
'Bang', # eggex !digit, ![a-z]
'Dot',
'DDot',
'DDotLessThan',
'DDotEqual',
'Colon', # mylist:pop()
'RArrow',
'RDArrow',
Expand Down
10 changes: 6 additions & 4 deletions frontend/lexer_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,10 +1103,12 @@ def R(pat, tok_type):
C('//', Id.Expr_DSlash), # For YSH integer division
C('~==', Id.Expr_TildeDEqual), # approximate equality

C('.', Id.Expr_Dot), # d.key is alias for d['key']
C('..', Id.Expr_DDot), # range 1..5
C('->', Id.Expr_RArrow), # s->startswith()
C('$', Id.Expr_Dollar), # legacy regex end: /d+ $/ (better written /d+ >/
C('.', Id.Expr_Dot), # d.key is alias for d['key']
C('..', Id.Unknown_DDot), # legacy half-open range 1..5
C('..<', Id.Expr_DDotLessThan), # half-open range 1..<5
C('..=', Id.Expr_DDotEqual), # closed range 1..5
C('->', Id.Expr_RArrow), # s->startswith()
C('$', Id.Expr_Dollar), # legacy regex end: /d+ $/ (better written /d+ >/

# Reserved this. Go uses it for channels, etc.
# I guess it conflicts with -4<-3, but that's OK -- spaces suffices.
Expand Down
8 changes: 4 additions & 4 deletions spec/ysh-bugs.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ pp test_ (pipe())
#### shvar then replace - bug #1986 context manager crash
shvar FOO=bar {
for x in (1 .. 500) {
for x in (1 ..< 500) {
var Q = "hello"
setvar Q = Q=>replace("hello","world")
}
Expand Down Expand Up @@ -239,20 +239,20 @@ case (WEIGHT) {
proc p {
var s = "hi"
for q in (1..50) {
for q in (1..<50) {
shvar Q="whatever" {
setvar s = "." ++ s
}
}
}
for i in (1..10) {
for i in (1..<10) {
p
}
if false {
echo 'testing for longer'
for i in (1 .. 1000) {
for i in (1 ..< 1000) {
p
}
}
Expand Down
2 changes: 1 addition & 1 deletion spec/ysh-builtins.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ echo $[type(f)]
echo $[type(len)]
echo $[type('foo'=>startsWith)]
echo $[type('foo'=>join)] # Type error happens later
echo $[type(1..3)]
echo $[type(1..<3)]
## STDOUT:
Int
Str
Expand Down
6 changes: 3 additions & 3 deletions spec/ysh-closures.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ proc task (; tasks, expr) {
func makeTasks() {
var tasks = []
var x = 'x'
for __hack__ in (0 .. 3) {
for __hack__ in (0 ..< 3) {
var i = __hack__
var j = i + 2
task (tasks, ^"$x: i = $i, j = $j")
Expand Down Expand Up @@ -82,7 +82,7 @@ proc task (; tasks; ; b) {
func makeTasks() {
var tasks = []
var x = 'x'
for __hack__ in (0 .. 3) {
for __hack__ in (0 ..< 3) {
var i = __hack__
var j = i + 2
task (tasks) { echo "$x: i = $i, j = $j" }
Expand All @@ -108,7 +108,7 @@ x: i = 2, j = 4
shopt --set ysh:upgrade

var procs = []
for i in (0 .. 3) {
for i in (0 ..< 3) {
proc __invoke__ (; self) {
echo "i = $[self.i]"
}
Expand Down
4 changes: 2 additions & 2 deletions spec/ysh-convert.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ echo "$[bool({})]"
echo "$[bool(null)]"
echo "$[bool(len)]"
echo "$[bool('foo'=>startsWith)]"
echo "$[bool(1..3)]"
echo "$[bool(1..<3)]"
## STDOUT:
true
false
Expand Down Expand Up @@ -180,7 +180,7 @@ foo
#### list() from range
shopt -s ysh:upgrade

var mylist = list(0..3)
var mylist = list(0..<3)
write @mylist
## STDOUT:
0
Expand Down
2 changes: 1 addition & 1 deletion spec/ysh-for.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ key age


#### For loop over range
var myrange = 0 .. 3
var myrange = 0 ..< 3
for i in (myrange) {
echo "i $i"
}
Expand Down
2 changes: 1 addition & 1 deletion spec/ysh-func.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ var cache = []
var maxSize = 4

func remove(l, i) {
for i in (i .. len(l) - 1) {
for i in (i ..< len(l) - 1) {
setvar l[i] = l[i + 1]
}

Expand Down
2 changes: 1 addition & 1 deletion spec/ysh-int-float.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ shopt -s ysh:upgrade
# 1e-324 == 0.0 in Python

var zeros = []
for i in (1 .. 324) {
for i in (1 ..< 324) {
call zeros->append('0')
}

Expand Down
4 changes: 2 additions & 2 deletions spec/ysh-json.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1168,10 +1168,10 @@ shopt -s ysh:upgrade
proc pairs(n) {
var m = int(n) # TODO: 1 .. n should auto-convert?
for i in (1 .. m) {
for i in (1 ..< m) {
write -n -- '['
}
for i in (1 .. m) {
for i in (1 ..< m) {
write -n -- ']'
}
}
Expand Down
10 changes: 5 additions & 5 deletions spec/ysh-list.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ echo -$x- # fails with type error
## END

#### List->extend()
var l = list(1..3)
var l = list(1..<3)
echo $[len(l)]
call l->extend(list(3..6))
call l->extend(list(3..<6))
echo $[len(l)]
## STDOUT:
2
Expand All @@ -151,9 +151,9 @@ echo $[len(l)]

#### List append()/extend() should return null
shopt -s ysh:all
var l = list(1..3)
var l = list(1..<3)

var result = l->extend(list(3..6))
var result = l->extend(list(3..<6))
assert [null === result]

setvar result = l->append(6)
Expand All @@ -166,7 +166,7 @@ pass

#### List pop()
shopt -s ysh:all
var l = list(1..5)
var l = list(1..<5)
assert [4 === l->pop()]
assert [3 === l->pop()]
assert [2 === l->pop()]
Expand Down
2 changes: 1 addition & 1 deletion spec/ysh-methods.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ pp test_ (c)
## END

#### List->reverse() from iterator
var x = list(0 .. 3)
var x = list(0 ..< 3)
call x->reverse()
write @x
## STDOUT:
Expand Down
8 changes: 4 additions & 4 deletions spec/ysh-printing.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
## END

#### Range
var x = 1..100
var x = 1..<100

pp value (x)

# TODO: show type here, like (Range 1 .. 100)
# TODO: show type here, like (Range 1 ..< 100)

pp value ({k: x})

Expand All @@ -49,8 +49,8 @@ pp test_ (x)
pp test_ ({k: x})

## STDOUT:
(Range 1 .. 100)
(Dict) {k: (Range 1 .. 100)}
(Range 1 ..< 100)
(Dict) {k: (Range 1 ..< 100)}

<Range>
(Dict) {"k":<Range>}
Expand Down
2 changes: 1 addition & 1 deletion spec/ysh-regex-api.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ shopt --set ysh:all

var mystr = '1abc2abc3abc'

for count in (-2..4) {
for count in (-2..<4) {
write $[mystr.replace('abc', "-", count=count)]
write $[mystr.replace('abc', ^"-", count=count)]
write $[mystr.replace(/ [a-z]+ /, "-", count=count)]
Expand Down
Loading

0 comments on commit 6e5ce18

Please sign in to comment.