Skip to content

Commit cc56f31

Browse files
committed
2 parents 8ac3c46 + 5c378d3 commit cc56f31

35 files changed

+702
-242
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/snippets/builtin_complex.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# __abs__
2+
3+
assert abs(complex(3, 4)) == 5
4+
assert abs(complex(3, -4)) == 5
5+
assert abs(complex(1.5, 2.5)) == 2.9154759474226504
6+
7+
# __eq__
8+
9+
assert complex(1, -1) == complex(1, -1)
10+
assert complex(1, 0) == 1
11+
assert not complex(1, 1) == 1
12+
assert complex(1, 0) == 1.0
13+
assert not complex(1, 1) == 1.0
14+
assert not complex(1, 0) == 1.5
15+
assert bool(complex(1, 0))
16+
assert not complex(1, 2) == complex(1, 1)
17+
# Currently broken - see issue #419
18+
# assert complex(1, 2) != 'foo'
19+
assert complex(1, 2).__eq__('foo') == NotImplemented
20+
21+
# __neg__
22+
23+
assert -complex(1, -1) == complex(-1, 1)
24+
assert -complex(0, 0) == complex(0, 0)

tests/snippets/builtin_dict.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
assert len({"a": "b"}) == 1
55
assert len({"a": "b", "b": 1}) == 2
66
assert len({"a": "b", "b": 1, "a" + "b": 2*2}) == 3
7+
8+
d = {}
9+
d['a'] = d
10+
assert repr(d) == "{'a': {...}}"

tests/snippets/builtin_range.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ def assert_raises(expr, exc_type):
3939
# index raises value error if needle is not an int
4040
assert_raises(lambda _: range(10).index('foo'), ValueError)
4141

42+
# count tests
43+
assert range(10).count(2) == 1
44+
assert range(10).count(11) == 0
45+
assert range(10).count(-1) == 0
46+
assert range(9, 12).count(10) == 1
47+
assert range(4, 10, 2).count(4) == 1
48+
assert range(4, 10, 2).count(7) == 0
49+
assert range(10).count("foo") == 0
50+
4251
# __bool__
4352
assert bool(range(1))
4453
assert bool(range(1, 2))
@@ -61,3 +70,4 @@ def assert_raises(expr, exc_type):
6170
# __reversed__
6271
assert list(reversed(range(5))) == [4, 3, 2, 1, 0]
6372
assert list(reversed(range(5, 0, -1))) == [1, 2, 3, 4, 5]
73+
assert list(reversed(range(1,10,5))) == [6, 1]

tests/snippets/floats.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,24 @@
1818
assert a + b == 2.5
1919
assert a - c == 0
2020
assert a / c == 1
21+
22+
assert a < 5
23+
assert a <= 5
24+
try:
25+
assert a < 'a'
26+
except TypeError:
27+
pass
28+
try:
29+
assert a <= 'a'
30+
except TypeError:
31+
pass
32+
assert a > 1
33+
assert a >= 1
34+
try:
35+
assert a > 'a'
36+
except TypeError:
37+
pass
38+
try:
39+
assert a >= 'a'
40+
except TypeError:
41+
pass

tests/snippets/int_float_equality.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# 10**308 cannot be represented exactly in f64, thus it is not equal to 1e308 float
2+
assert not (10**308 == 1e308)
3+
# but the 1e308 float can be converted to big int and then it still should be equal to itself
4+
assert int(1e308) == 1e308
5+
6+
# and the equalities should be the same when operands switch sides
7+
assert not (1e308 == 10**308)
8+
assert 1e308 == int(1e308)
9+
10+
# floats that cannot be converted to big ints shouldn’t crash the vm
11+
import math
12+
assert not (10**500 == math.inf)
13+
assert not (math.inf == 10**500)
14+
assert not (10**500 == math.nan)
15+
assert not (math.nan == 10**500)

tests/snippets/list.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,7 @@
3838
pass
3939
else:
4040
assert False, "IndexError was not raised"
41+
42+
recursive = []
43+
recursive.append(recursive)
44+
assert repr(recursive) == "[[...]]"
File renamed without changes.

tests/snippets/membership.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313
# TODO: uncomment this when bytes are implemented
1414
# assert b"foo" in b"foobar"
1515
# assert b"whatever" not in b"foobar"
16+
assert b"1" < b"2"
17+
assert b"1" <= b"2"
18+
assert b"5" <= b"5"
19+
assert b"4" > b"2"
20+
assert not b"1" >= b"2"
21+
assert b"10" >= b"10"
22+
try:
23+
bytes() > 2
24+
except TypeError:
25+
pass
26+
else:
27+
assert False, "TypeError not raised"
1628

1729
# test tuple
1830
assert 1 in (1, 2)

tests/snippets/os_static.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/snippets/set.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,19 @@
2424
assert set([1,2]) < set([1,2,3])
2525
assert not set([1,2]) < set([1,2])
2626
assert not set([1,3]) < set([1,2])
27+
28+
29+
class Hashable(object):
30+
def __init__(self, obj):
31+
self.obj = obj
32+
33+
def __repr__(self):
34+
return repr(self.obj)
35+
36+
def __hash__(self):
37+
return id(self)
38+
39+
40+
recursive = set()
41+
recursive.add(Hashable(recursive))
42+
assert repr(recursive) == "{set(...)}"
File renamed without changes.

tests/snippets/os_open.py renamed to tests/snippets/stdlib_os.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@
88
assert False
99
except FileNotFoundError:
1010
pass
11+
12+
13+
assert os.O_RDONLY == 0
14+
assert os.O_WRONLY == 1
15+
assert os.O_RDWR == 2

tests/snippets/strings.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,10 @@
7878
assert "{0} {1}".format(2,3) == "2 3"
7979
assert "--{:s>4}--".format(1) == "--sss1--"
8080
assert "{keyword} {0}".format(1, keyword=2) == "2 1"
81+
82+
assert 'a' < 'b'
83+
assert 'a' <= 'b'
84+
assert 'a' <= 'a'
85+
assert 'z' > 'b'
86+
assert 'z' >= 'b'
87+
assert 'a' >= 'a'

tests/snippets/test_sets.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
empty_set = set()
3+
non_empty_set = set([1,2,3])
4+
set_from_literal = {1,2,3}
5+
6+
assert 1 in non_empty_set
7+
assert 4 not in non_empty_set
8+
9+
assert 1 in set_from_literal
10+
assert 4 not in set_from_literal
11+
12+
# TODO: Assert that empty aruguments raises exception.
13+
non_empty_set.add('a')
14+
assert 'a' in non_empty_set
15+
16+
# TODO: Assert that empty arguments, or item not in set raises exception.
17+
non_empty_set.remove(1)
18+
assert 1 not in non_empty_set
19+
20+
# TODO: Assert that adding the same thing to a set once it's already there doesn't do anything.

tests/snippets/tuple.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@
1919

2020
b = (1,2,3)
2121
assert b.index(2) == 1
22+
23+
recursive_list = []
24+
recursive = (recursive_list,)
25+
recursive_list.append(recursive)
26+
assert repr(recursive) == "([(...)],)"

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ regex = "1"
2020
statrs = "0.10.0"
2121
caseless = "0.2.1"
2222
unicode-segmentation = "1.2.1"
23+
lazy_static = "^1.0.1"

vm/src/builtins.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,9 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
718718
ctx.set_attr(&py_mod, "type", ctx.type_type());
719719
ctx.set_attr(&py_mod, "zip", ctx.zip_type());
720720

721+
// Constants
722+
ctx.set_attr(&py_mod, "NotImplemented", ctx.not_implemented.clone());
723+
721724
// Exceptions:
722725
ctx.set_attr(
723726
&py_mod,

vm/src/frame.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,10 @@ impl Frame {
226226
}
227227
bytecode::Instruction::BuildSet { size, unpack } => {
228228
let elements = self.get_elements(vm, *size, *unpack)?;
229-
let py_obj = vm.ctx.new_set(elements);
229+
let py_obj = vm.ctx.new_set();
230+
for item in elements {
231+
vm.call_method(&py_obj, "add", vec![item])?;
232+
}
230233
self.push_value(py_obj);
231234
Ok(None)
232235
}
@@ -1085,7 +1088,7 @@ impl fmt::Debug for Frame {
10851088
let stack_str = self
10861089
.stack
10871090
.iter()
1088-
.map(|elem| format!("\n > {}", elem.borrow().str()))
1091+
.map(|elem| format!("\n > {:?}", elem.borrow()))
10891092
.collect::<Vec<_>>()
10901093
.join("");
10911094
let block_str = self
@@ -1099,9 +1102,7 @@ impl fmt::Debug for Frame {
10991102
PyObjectPayload::Dict { ref elements } => {
11001103
objdict::get_key_value_pairs_from_content(elements)
11011104
.iter()
1102-
.map(|elem| {
1103-
format!("\n {} = {}", elem.0.borrow().str(), elem.1.borrow().str())
1104-
})
1105+
.map(|elem| format!("\n {:?} = {:?}", elem.0.borrow(), elem.1.borrow()))
11051106
.collect::<Vec<_>>()
11061107
.join("")
11071108
}

vm/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#[macro_use]
99
extern crate bitflags;
1010
#[macro_use]
11+
extern crate lazy_static;
12+
#[macro_use]
1113
extern crate log;
1214
// extern crate env_logger;
1315
extern crate num_bigint;

vm/src/obj/objbytes.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ pub fn init(context: &PyContext) {
2727
- an integer";
2828

2929
context.set_attr(bytes_type, "__eq__", context.new_rustfunc(bytes_eq));
30+
context.set_attr(bytes_type, "__lt__", context.new_rustfunc(bytes_lt));
31+
context.set_attr(bytes_type, "__le__", context.new_rustfunc(bytes_le));
32+
context.set_attr(bytes_type, "__gt__", context.new_rustfunc(bytes_gt));
33+
context.set_attr(bytes_type, "__ge__", context.new_rustfunc(bytes_ge));
3034
context.set_attr(bytes_type, "__hash__", context.new_rustfunc(bytes_hash));
3135
context.set_attr(bytes_type, "__new__", context.new_rustfunc(bytes_new));
3236
context.set_attr(bytes_type, "__repr__", context.new_rustfunc(bytes_repr));
@@ -82,6 +86,82 @@ fn bytes_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
8286
Ok(vm.ctx.new_bool(result))
8387
}
8488

89+
fn bytes_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
90+
arg_check!(
91+
vm,
92+
args,
93+
required = [(a, Some(vm.ctx.bytes_type())), (b, None)]
94+
);
95+
96+
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
97+
get_value(a).to_vec() >= get_value(b).to_vec()
98+
} else {
99+
return Err(vm.new_type_error(format!(
100+
"Cannot compare {} and {} using '>'",
101+
a.borrow(),
102+
b.borrow()
103+
)));
104+
};
105+
Ok(vm.ctx.new_bool(result))
106+
}
107+
108+
fn bytes_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
109+
arg_check!(
110+
vm,
111+
args,
112+
required = [(a, Some(vm.ctx.bytes_type())), (b, None)]
113+
);
114+
115+
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
116+
get_value(a).to_vec() > get_value(b).to_vec()
117+
} else {
118+
return Err(vm.new_type_error(format!(
119+
"Cannot compare {} and {} using '>='",
120+
a.borrow(),
121+
b.borrow()
122+
)));
123+
};
124+
Ok(vm.ctx.new_bool(result))
125+
}
126+
127+
fn bytes_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
128+
arg_check!(
129+
vm,
130+
args,
131+
required = [(a, Some(vm.ctx.bytes_type())), (b, None)]
132+
);
133+
134+
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
135+
get_value(a).to_vec() <= get_value(b).to_vec()
136+
} else {
137+
return Err(vm.new_type_error(format!(
138+
"Cannot compare {} and {} using '<'",
139+
a.borrow(),
140+
b.borrow()
141+
)));
142+
};
143+
Ok(vm.ctx.new_bool(result))
144+
}
145+
146+
fn bytes_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
147+
arg_check!(
148+
vm,
149+
args,
150+
required = [(a, Some(vm.ctx.bytes_type())), (b, None)]
151+
);
152+
153+
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
154+
get_value(a).to_vec() < get_value(b).to_vec()
155+
} else {
156+
return Err(vm.new_type_error(format!(
157+
"Cannot compare {} and {} using '<='",
158+
a.borrow(),
159+
b.borrow()
160+
)));
161+
};
162+
Ok(vm.ctx.new_bool(result))
163+
}
164+
85165
fn bytes_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
86166
arg_check!(vm, args, required = [(a, Some(vm.ctx.bytes_type()))]);
87167

0 commit comments

Comments
 (0)