Commit c6177dfd authored by scoder's avatar scoder Committed by GitHub

Merge pull request #2583 from cjgibson/2508-slicing-fixes

Support two-element slicing with literal None
parents b1960185 459e108f
...@@ -4794,10 +4794,50 @@ class SliceIndexNode(ExprNode): ...@@ -4794,10 +4794,50 @@ class SliceIndexNode(ExprNode):
step=none_node step=none_node
).analyse_types(env) ).analyse_types(env)
else: else:
from .UtilNodes import EvalWithTempExprNode, ResultRefNode
c_int = PyrexTypes.c_py_ssize_t_type c_int = PyrexTypes.c_py_ssize_t_type
if self.start: if self.start:
if self.start.type.is_pyobject:
start_ref = ResultRefNode(self.start)
start_expr = CondExprNode(
self.start.pos,
true_val = IntNode(
self.start.pos,
value = '0',
constant_result = 0
),
false_val = start_ref,
test = PrimaryCmpNode(
self.start.pos,
operand1 = start_ref,
operator = 'is',
operand2 = NoneNode(self.start.pos),
)
)
start_expr = start_expr.analyse_types(env)
start_expr = start_expr.coerce_to(c_int, env)
self.start = EvalWithTempExprNode(start_ref, start_expr)
self.start = self.start.coerce_to(c_int, env) self.start = self.start.coerce_to(c_int, env)
if self.stop: if self.stop:
if self.stop.type.is_pyobject:
stop_ref = ResultRefNode(self.stop)
stop_expr = CondExprNode(
self.stop.pos,
true_val = IntNode(
self.stop.pos,
value = 'PY_SSIZE_T_MAX'
),
false_val = stop_ref,
test = PrimaryCmpNode(
self.stop.pos,
operand1 = stop_ref,
operator = 'is',
operand2 = NoneNode(self.stop.pos),
)
)
stop_expr = stop_expr.analyse_types(env)
stop_expr = stop_expr.coerce_to(c_int, env)
self.stop = EvalWithTempExprNode(stop_ref, stop_expr)
self.stop = self.stop.coerce_to(c_int, env) self.stop = self.stop.coerce_to(c_int, env)
self.is_temp = 1 self.is_temp = 1
return self return self
......
# mode: run # mode: run
# tag: slicing # tag: list, slice, slicing
def test_full(seq): def test_full(seq):
""" """
...@@ -18,21 +18,24 @@ def test_full(seq): ...@@ -18,21 +18,24 @@ def test_full(seq):
def test_start(seq, start): def test_start(seq, start):
""" """
>>> test_start([1,2,3,4], 2) >>> l = [1,2,3,4]
>>> test_start(l, 2)
[3, 4] [3, 4]
>>> test_start([1,2,3,4], 3) >>> test_start(l, 3)
[4] [4]
>>> test_start([1,2,3,4], 4) >>> test_start(l, 4)
[] []
>>> test_start([1,2,3,4], 8) >>> test_start(l, 8)
[] []
>>> test_start([1,2,3,4], -3) >>> test_start(l, -3)
[2, 3, 4] [2, 3, 4]
>>> test_start([1,2,3,4], -4) >>> test_start(l, -4)
[1, 2, 3, 4]
>>> test_start(l, -8)
[1, 2, 3, 4] [1, 2, 3, 4]
>>> test_start([1,2,3,4], -8) >>> test_start(l, 0)
[1, 2, 3, 4] [1, 2, 3, 4]
>>> test_start([1,2,3,4], 0) >>> test_start(l, None)
[1, 2, 3, 4] [1, 2, 3, 4]
>>> try: test_start(42, 2, 3) >>> try: test_start(42, 2, 3)
... except TypeError: pass ... except TypeError: pass
...@@ -42,24 +45,52 @@ def test_start(seq, start): ...@@ -42,24 +45,52 @@ def test_start(seq, start):
def test_stop(seq, stop): def test_stop(seq, stop):
""" """
>>> test_stop([1,2,3,4], 3) >>> l = [1,2,3,4]
>>> test_stop(l, 3)
[1, 2, 3] [1, 2, 3]
>>> test_stop([1,2,3,4], -1) >>> test_stop(l, -1)
[1, 2, 3] [1, 2, 3]
>>> test_stop([1,2,3,4], -3) >>> test_stop(l, -3)
[1] [1]
>>> test_stop([1,2,3,4], -4) >>> test_stop(l, -4)
[] []
>>> test_stop([1,2,3,4], -8) >>> test_stop(l, -8)
[] []
>>> test_stop([1,2,3,4], 0) >>> test_stop(l, 0)
[] []
>>> test_stop(l, None)
[1, 2, 3, 4]
>>> try: test_stop(42, 3) >>> try: test_stop(42, 3)
... except TypeError: pass ... except TypeError: pass
""" """
obj = seq[:stop] obj = seq[:stop]
return obj return obj
def test_step(seq, step):
"""
>>> l = [1,2,3,4]
>>> test_step(l, -1)
[4, 3, 2, 1]
>>> test_step(l, 1)
[1, 2, 3, 4]
>>> test_step(l, 2)
[1, 3]
>>> test_step(l, 3)
[1, 4]
>>> test_step(l, -3)
[4, 1]
>>> test_step(l, None)
[1, 2, 3, 4]
>>> try: test_step(l, 0)
... except ValueError: pass
...
>>> try: test_step(42, 0)
... except TypeError: pass
...
"""
obj = seq[::step]
return obj
def test_start_and_stop(seq, start, stop): def test_start_and_stop(seq, start, stop):
""" """
>>> l = [1,2,3,4] >>> l = [1,2,3,4]
...@@ -67,12 +98,38 @@ def test_start_and_stop(seq, start, stop): ...@@ -67,12 +98,38 @@ def test_start_and_stop(seq, start, stop):
[3] [3]
>>> test_start_and_stop(l, -3, -1) >>> test_start_and_stop(l, -3, -1)
[2, 3] [2, 3]
>>> test_start_and_stop(l, None, None)
[1, 2, 3, 4]
>>> try: test_start_and_stop(42, 2, 3) >>> try: test_start_and_stop(42, 2, 3)
... except TypeError: pass ... except TypeError: pass
""" """
obj = seq[start:stop] obj = seq[start:stop]
return obj return obj
def test_start_stop_and_step(seq, start, stop, step):
"""
>>> l = [1,2,3,4,5]
>>> test_start_stop_and_step(l, 0, 5, 1)
[1, 2, 3, 4, 5]
>>> test_start_stop_and_step(l, 5, -1, -1)
[]
>>> test_start_stop_and_step(l, 5, None, -1)
[5, 4, 3, 2, 1]
>>> test_start_stop_and_step(l, 2, 5, 2)
[3, 5]
>>> test_start_stop_and_step(l, -100, 100, 1)
[1, 2, 3, 4, 5]
>>> test_start_stop_and_step(l, None, None, None)
[1, 2, 3, 4, 5]
>>> try: test_start_stop_and_step(l, None, None, 0)
... except ValueError: pass
...
>>> try: test_start_stop_and_step(42, 1, 2, 3)
... except TypeError: pass
"""
obj = seq[start:stop:step]
return obj
class A(object): class A(object):
pass pass
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment