Skip to content

Commit f6cced5

Browse files
committed
Change integer type into bigint
1 parent 1e3b45e commit f6cced5

21 files changed

+232
-156
lines changed

Cargo.lock

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

tests/snippets/builtin_bin.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
assert bin(-(2**24)) == '-0b1' + '0' * 24
77
assert bin(-(2**24-1)) == '-0b' + '1' * 24
88

9-
# TODO: uncomment these tests when arbitrarily sized ints are supported
10-
# assert bin(2**65) == '0b1' + '0' * 65
11-
# assert bin(2**65-1) == '0b' + '1' * 65
12-
# assert bin(-(2**65)) == '-0b1' + '0' * 65
13-
# assert bin(-(2**65-1)) == '-0b' + '1' * 65
9+
# TODO: change to 2**65 when we have support for pow in bigint
10+
a = 2**20 * 2**20 * 2**25
11+
assert bin(a) == '0b1' + '0' * 65
12+
assert bin(a-1) == '0b' + '1' * 65
13+
assert bin(-(a)) == '-0b1' + '0' * 65
14+
assert bin(-(a-1)) == '-0b' + '1' * 65

vm/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ authors = ["Shing Lyu <[email protected]>"]
66
[dependencies]
77
bitflags = "1.0.4"
88
num-complex = "0.2"
9+
num-bigint = "0.2"
10+
num-traits = "0.2"
911
log = "0.3"
1012
rustpython_parser = {path = "../parser"}
1113
serde = "1.0.66"

vm/src/builtins.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use super::pyobject::{
1414
PyObjectRef, PyResult, Scope, TypeProtocol,
1515
};
1616
use super::vm::VirtualMachine;
17+
use num_bigint::ToBigInt;
18+
use num_traits::{Signed, ToPrimitive};
1719

1820
fn get_locals(vm: &mut VirtualMachine) -> PyObjectRef {
1921
let d = vm.new_dict();
@@ -80,9 +82,10 @@ fn builtin_bin(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
8082
arg_check!(vm, args, required = [(number, Some(vm.ctx.int_type()))]);
8183

8284
let n = objint::get_value(number);
83-
let s = match n.signum() {
84-
-1 => format!("-0b{:b}", n.abs()),
85-
_ => format!("0b{:b}", n),
85+
let s = if n.is_negative() {
86+
format!("-0b{:b}", n.abs())
87+
} else {
88+
format!("0b{:b}", n)
8689
};
8790

8891
Ok(vm.new_str(s))
@@ -97,15 +100,7 @@ fn builtin_bin(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
97100
fn builtin_chr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
98101
arg_check!(vm, args, required = [(i, Some(vm.ctx.int_type()))]);
99102

100-
let code_point_obj = i.borrow();
101-
102-
let code_point = *match code_point_obj.kind {
103-
PyObjectKind::Integer { ref value } => value,
104-
ref kind => panic!(
105-
"argument checking failure: chr not supported for {:?}",
106-
kind
107-
),
108-
} as u32;
103+
let code_point = objint::get_value(i).to_u32().unwrap();
109104

110105
let txt = match char::from_u32(code_point) {
111106
Some(value) => value.to_string(),
@@ -261,9 +256,10 @@ fn builtin_hex(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
261256
arg_check!(vm, args, required = [(number, Some(vm.ctx.int_type()))]);
262257

263258
let n = objint::get_value(number);
264-
let s = match n.signum() {
265-
-1 => format!("-0x{:x}", n.abs()),
266-
_ => format!("0x{:x}", n),
259+
let s = if n.is_negative() {
260+
format!("-0x{:x}", n.abs())
261+
} else {
262+
format!("0x{:x}", n)
267263
};
268264

269265
Ok(vm.new_str(s))
@@ -272,7 +268,7 @@ fn builtin_hex(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
272268
fn builtin_id(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
273269
arg_check!(vm, args, required = [(obj, None)]);
274270

275-
Ok(vm.context().new_int(obj.get_id() as i32))
271+
Ok(vm.context().new_int(obj.get_id().to_bigint().unwrap()))
276272
}
277273

278274
// builtin_input
@@ -304,8 +300,12 @@ fn builtin_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
304300
fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
305301
arg_check!(vm, args, required = [(obj, None)]);
306302
match obj.borrow().kind {
307-
PyObjectKind::Dict { ref elements } => Ok(vm.context().new_int(elements.len() as i32)),
308-
PyObjectKind::Tuple { ref elements } => Ok(vm.context().new_int(elements.len() as i32)),
303+
PyObjectKind::Dict { ref elements } => {
304+
Ok(vm.context().new_int(elements.len().to_bigint().unwrap()))
305+
}
306+
PyObjectKind::Tuple { ref elements } => {
307+
Ok(vm.context().new_int(elements.len().to_bigint().unwrap()))
308+
}
309309
_ => {
310310
let len_method_name = "__len__".to_string();
311311
match vm.get_attribute(obj.clone(), &len_method_name) {
@@ -427,7 +427,9 @@ fn builtin_ord(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
427427
));
428428
}
429429
match string.chars().next() {
430-
Some(character) => Ok(vm.context().new_int(character as i32)),
430+
Some(character) => Ok(vm
431+
.context()
432+
.new_int((character as i32).to_bigint().unwrap())),
431433
None => Err(vm.new_type_error(
432434
"ord() could not guess the integer representing this character".to_string(),
433435
)),
@@ -486,8 +488,9 @@ fn builtin_range(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
486488
arg_check!(vm, args, required = [(range, Some(vm.ctx.int_type()))]);
487489
match range.borrow().kind {
488490
PyObjectKind::Integer { ref value } => {
489-
let range_elements: Vec<PyObjectRef> =
490-
(0..*value).map(|num| vm.context().new_int(num)).collect();
491+
let range_elements: Vec<PyObjectRef> = (0..value.to_i32().unwrap())
492+
.map(|num| vm.context().new_int(num.to_bigint().unwrap()))
493+
.collect();
491494
Ok(vm.context().new_list(range_elements))
492495
}
493496
_ => panic!("argument checking failure: first argument to range must be an integer"),

vm/src/frame.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use super::pyobject::{
1919
PyObjectKind, PyObjectRef, PyResult, ToRust, TypeProtocol,
2020
};
2121
use super::vm::VirtualMachine;
22+
use num_bigint::ToBigInt;
23+
use num_traits::ToPrimitive;
2224

2325
#[derive(Clone, Debug)]
2426
enum Block {
@@ -127,7 +129,7 @@ impl Frame {
127129
trace!("Adding to traceback: {:?} {:?}", traceback, lineno);
128130
let pos = vm.ctx.new_tuple(vec![
129131
vm.ctx.new_str(filename.clone()),
130-
vm.ctx.new_int(lineno.get_row() as i32),
132+
vm.ctx.new_int(lineno.get_row().to_bigint().unwrap()),
131133
vm.ctx.new_str(run_obj_name.clone()),
132134
]);
133135
objlist::list_append(
@@ -283,7 +285,7 @@ impl Frame {
283285
let mut out: Vec<Option<i32>> = elements
284286
.into_iter()
285287
.map(|x| match x.borrow().kind {
286-
PyObjectKind::Integer { value } => Some(value),
288+
PyObjectKind::Integer { ref value } => Some(value.to_i32().unwrap()),
287289
PyObjectKind::None => None,
288290
_ => panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x),
289291
})
@@ -929,7 +931,7 @@ impl Frame {
929931
// TODO:
930932
// self.invoke('__neg__'
931933
match a.borrow().kind {
932-
PyObjectKind::Integer { value: ref value1 } => vm.ctx.new_int(-*value1),
934+
PyObjectKind::Integer { value: ref value1 } => vm.ctx.new_int(-value1),
933935
PyObjectKind::Float { value: ref value1 } => vm.ctx.new_float(-*value1),
934936
_ => panic!("Not impl {:?}", a),
935937
}
@@ -1072,7 +1074,7 @@ impl Frame {
10721074

10731075
fn unwrap_constant(&self, vm: &VirtualMachine, value: &bytecode::Constant) -> PyObjectRef {
10741076
match *value {
1075-
bytecode::Constant::Integer { ref value } => vm.ctx.new_int(*value),
1077+
bytecode::Constant::Integer { ref value } => vm.ctx.new_int(value.to_bigint().unwrap()),
10761078
bytecode::Constant::Float { ref value } => vm.ctx.new_float(*value),
10771079
bytecode::Constant::Complex { ref value } => vm.ctx.new_complex(*value),
10781080
bytecode::Constant::String { ref value } => vm.new_str(value.clone()),

vm/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ extern crate bitflags;
33
#[macro_use]
44
extern crate log;
55
// extern crate env_logger;
6+
extern crate num_bigint;
67
extern crate num_complex;
8+
extern crate num_traits;
79
extern crate serde;
810
extern crate serde_json;
911

vm/src/obj/objbool.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use super::super::pyobject::{
33
};
44
use super::super::vm::VirtualMachine;
55
use super::objtype;
6+
use num_traits::Zero;
67

78
pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObjectRef> {
89
let result = match obj.borrow().kind {
9-
PyObjectKind::Integer { value } => value != 0,
10+
PyObjectKind::Integer { ref value } => !value.is_zero(),
1011
PyObjectKind::Float { value } => value != 0.0,
1112
PyObjectKind::List { ref elements } => !elements.is_empty(),
1213
PyObjectKind::Tuple { ref elements } => !elements.is_empty(),
@@ -15,13 +16,12 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
1516
PyObjectKind::None { .. } => false,
1617
_ => {
1718
if let Ok(f) = objtype::get_attribute(vm, obj.clone(), &String::from("__bool__")) {
18-
match vm.invoke(f, PyFuncArgs::default()) {
19-
Ok(result) => match result.borrow().kind {
20-
PyObjectKind::Integer { value } => value != 0,
21-
_ => return Err(vm.new_type_error(String::from("TypeError"))),
22-
},
23-
Err(err) => return Err(err),
24-
}
19+
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
20+
let v = match bool_res.borrow().kind {
21+
PyObjectKind::Integer { ref value } => !value.is_zero(),
22+
_ => return Err(vm.new_type_error(String::from("TypeError"))),
23+
};
24+
v
2525
} else {
2626
true
2727
}
@@ -48,7 +48,7 @@ pub fn not(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyResult {
4848
// Retrieve inner int value:
4949
pub fn get_value(obj: &PyObjectRef) -> bool {
5050
if let PyObjectKind::Integer { value } = &obj.borrow().kind {
51-
*value != 0
51+
!value.is_zero()
5252
} else {
5353
panic!("Inner error getting inner boolean");
5454
}

vm/src/obj/objbytes.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::super::vm::VirtualMachine;
55
use super::objint;
66
use super::objlist;
77
use super::objtype;
8+
use num_traits::ToPrimitive;
89
// Binary data support
910

1011
// Fill bytes class methods:
@@ -25,11 +26,8 @@ fn bytes_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
2526
let val = if objtype::isinstance(arg, &vm.ctx.list_type()) {
2627
let mut data_bytes = vec![];
2728
for elem in objlist::get_elements(arg) {
28-
let v = match objint::to_int(vm, &elem, 10) {
29-
Ok(int_ref) => int_ref,
30-
Err(err) => return Err(err),
31-
};
32-
data_bytes.push(v as u8);
29+
let v = objint::to_int(vm, &elem, 10)?;
30+
data_bytes.push(v.to_u8().unwrap());
3331
}
3432
data_bytes
3533
} else {

vm/src/obj/objdict.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::super::pyobject::{
55
use super::super::vm::VirtualMachine;
66
use super::objstr;
77
use super::objtype;
8+
use num_bigint::ToBigInt;
89
use std::collections::HashMap;
910

1011
pub fn _set_item(
@@ -41,7 +42,7 @@ fn dict_new(_vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
4142
fn dict_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
4243
arg_check!(vm, args, required = [(o, Some(vm.ctx.dict_type()))]);
4344
let elements = get_elements(o);
44-
Ok(vm.ctx.new_int(elements.len() as i32))
45+
Ok(vm.ctx.new_int(elements.len().to_bigint().unwrap()))
4546
}
4647

4748
fn dict_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/obj/objfloat.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::super::pyobject::{
44
use super::super::vm::VirtualMachine;
55
use super::objint;
66
use super::objtype;
7+
use num_traits::ToPrimitive;
78

89
fn float_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
910
arg_check!(vm, args, required = [(float, Some(vm.ctx.float_type()))]);
@@ -21,7 +22,7 @@ fn float_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
2122
let val = if objtype::isinstance(arg, &vm.ctx.float_type()) {
2223
get_value(arg)
2324
} else if objtype::isinstance(arg, &vm.ctx.int_type()) {
24-
objint::get_value(arg) as f64
25+
objint::get_value(arg).to_f64().unwrap()
2526
} else {
2627
return Err(vm.new_type_error("Cannot construct int".to_string()));
2728
};
@@ -42,7 +43,7 @@ pub fn make_float(vm: &mut VirtualMachine, obj: &PyObjectRef) -> Result<f64, PyO
4243
if objtype::isinstance(obj, &vm.ctx.float_type()) {
4344
Ok(get_value(obj))
4445
} else if objtype::isinstance(obj, &vm.ctx.int_type()) {
45-
Ok(objint::get_value(obj) as f64)
46+
Ok(objint::get_value(obj).to_f64().unwrap())
4647
} else {
4748
Err(vm.new_type_error(format!("Cannot cast {:?} to float", obj)))
4849
}
@@ -63,7 +64,7 @@ fn float_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
6364
let other = get_value(other);
6465
zelf == other
6566
} else if objtype::isinstance(other, &vm.ctx.int_type()) {
66-
let other = objint::get_value(other) as f64;
67+
let other = objint::get_value(other).to_f64().unwrap();
6768
zelf == other
6869
} else {
6970
false
@@ -147,7 +148,9 @@ fn float_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
147148
if objtype::isinstance(i2, &vm.ctx.float_type()) {
148149
Ok(vm.ctx.new_float(v1 + get_value(i2)))
149150
} else if objtype::isinstance(i2, &vm.ctx.int_type()) {
150-
Ok(vm.ctx.new_float(v1 + objint::get_value(i2) as f64))
151+
Ok(vm
152+
.ctx
153+
.new_float(v1 + objint::get_value(i2).to_f64().unwrap()))
151154
} else {
152155
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
153156
}
@@ -181,7 +184,7 @@ fn float_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
181184
} else if objtype::isinstance(i2, &vm.ctx.int_type()) {
182185
Ok(vm
183186
.ctx
184-
.new_float((get_value(i) / objint::get_value(i2) as f64).floor()))
187+
.new_float((get_value(i) / objint::get_value(i2).to_f64().unwrap()).floor()))
185188
} else {
186189
Err(vm.new_type_error(format!("Cannot floordiv {:?} and {:?}", i, i2)))
187190
}
@@ -197,7 +200,9 @@ fn float_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
197200
if objtype::isinstance(i2, &vm.ctx.float_type()) {
198201
Ok(vm.ctx.new_float(v1 - get_value(i2)))
199202
} else if objtype::isinstance(i2, &vm.ctx.int_type()) {
200-
Ok(vm.ctx.new_float(v1 - objint::get_value(i2) as f64))
203+
Ok(vm
204+
.ctx
205+
.new_float(v1 - objint::get_value(i2).to_f64().unwrap()))
201206
} else {
202207
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
203208
}
@@ -214,7 +219,7 @@ fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
214219
} else if objtype::isinstance(i2, &vm.ctx.int_type()) {
215220
Ok(vm
216221
.ctx
217-
.new_float(get_value(i) % objint::get_value(i2) as f64))
222+
.new_float(get_value(i) % objint::get_value(i2).to_f64().unwrap()))
218223
} else {
219224
Err(vm.new_type_error(format!("Cannot mod {:?} and {:?}", i, i2)))
220225
}
@@ -232,7 +237,7 @@ fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
232237
let result = v1.powf(get_value(i2));
233238
Ok(vm.ctx.new_float(result))
234239
} else if objtype::isinstance(i2, &vm.ctx.int_type()) {
235-
let result = v1.powf(objint::get_value(i2) as f64);
240+
let result = v1.powf(objint::get_value(i2).to_f64().unwrap());
236241
Ok(vm.ctx.new_float(result))
237242
} else {
238243
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))

0 commit comments

Comments
 (0)