Skip to content

Commit fe7b0d4

Browse files
committed
Small improvements to parser
1 parent a7ab8a8 commit fe7b0d4

File tree

16 files changed

+798
-1557
lines changed

16 files changed

+798
-1557
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ version = "0.1.0"
66
edition = "2021"
77

88
[dependencies]
9-
peg = "0.8.5"
109
strum = "0.26.3"
1110
strum_macros = "0.26.4"
1211
mopa = "0.2.2"
1312
ahash = "0.8.11"
14-
rustpython-parser = "0.4.0"
13+
#rustpython-parser = "0.4.0"
14+
rustpython-parser = {git = "https://github.com/mxgordon/RustyPython-parser.git", features = ["lalrpop"]}
1515
malachite = "0.6.1"
1616

1717
[profile.release]
@@ -25,5 +25,6 @@ codegen-units = 1
2525
debug = true
2626
lto = "off"
2727

28-
[features]
29-
trace = ["peg/trace"]
28+
[profile.profiling]
29+
inherits = "release"
30+
debug = true

benchmarker.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,15 @@ def benchmark_rs(test):
8383
else:
8484
print(f"{py_time/rusty_time :.2f}x faster than CPython")
8585

86-
print(f"{rs_time/rusty_time :.2f}x faster than RustPython")
86+
print(f"{rs_time/rusty_time :.2f}x faster than RustPython")
87+
88+
89+
"""
90+
5.83x slower than CPython
91+
1.29x faster than RustPython
92+
93+
4.62x slower than CPython
94+
2.16x faster than RustPython
95+
96+
97+
"""

flamegraph.svg

Lines changed: 2 additions & 2 deletions
Loading

profile.json.gz

12.9 KB
Binary file not shown.

src/builtins/statics.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use malachite::base::num::conversion::traits::SaturatingFrom;
2+
use malachite::Integer;
13
use crate::builtins::structure::pyobject::PyObject;
24

35
#[derive(Debug)]
@@ -6,6 +8,8 @@ pub struct Statics {
68
false_: PyObject,
79

810
none_: PyObject,
11+
12+
ints: [PyObject; 262],
913

1014
not_implemented: PyObject,
1115
}
@@ -17,6 +21,8 @@ impl Statics {
1721
false_: PyObject::create_new_bool(false),
1822

1923
none_: PyObject::create_new_none(),
24+
25+
ints: PyObject::create_cached_ints(-5, 256).try_into().expect("Int array wasn't sized corrected"),
2026

2127
not_implemented: PyObject::create_new_not_implemented(),
2228
}
@@ -37,4 +43,20 @@ impl Statics {
3743
pub fn not_implemented(&self) -> &PyObject {
3844
&self.not_implemented
3945
}
46+
47+
pub fn get_int(&self, value: Integer) -> PyObject {
48+
if (-5..=256).contains(&value) {
49+
return self.ints[(i32::saturating_from(&value) + 5) as usize].clone();
50+
}
51+
52+
PyObject::new_int_uncached(value)
53+
}
54+
55+
pub fn get_int_borrow(&self, value: &Integer) -> PyObject {
56+
if -5 <= *value && *value <= 256 {
57+
return self.ints[(i32::saturating_from(value) + 5) as usize].clone();
58+
}
59+
60+
PyObject::new_int_uncached(value.clone())
61+
}
4062
}

src/builtins/structure/pyobject.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ impl PyObject {
3333
Self::new_immutable(PyImmutableObject::Str(value))
3434
}
3535

36-
pub fn new_int(value: Integer) -> Self {
37-
Self::new_immutable(PyImmutableObject::Int(value))
38-
}
3936
pub fn new_float(value: f64) -> Self {
4037
Self::new_immutable(PyImmutableObject::Float(value))
4138
}
@@ -80,6 +77,20 @@ impl PyObject {
8077
Self::new_immutable(PyImmutableObject::Bool(value))
8178
}
8279

80+
pub fn new_int_uncached(value: Integer) -> Self {
81+
Self::new_immutable(PyImmutableObject::Int(value))
82+
}
83+
84+
pub fn create_cached_ints(lower_value: i32, upper_value: i32) -> Vec<PyObject> {
85+
let mut ints = Vec::new();
86+
87+
for i in lower_value..(upper_value + 1) {
88+
ints.push(Self::new_int_uncached(Integer::from(i)));
89+
}
90+
91+
ints
92+
}
93+
8394
// pub fn stop_iteration() -> Self { // TODO prob should be moved out of the pyobject class (currently in here for legacy reasons)
8495
// PyObject::IteratorFlag(PyIteratorFlag::StopIteration)
8596
// }

src/builtins/types/pybool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub fn bool__bool__(arena: &mut PyArena, pyself: &PyObject) -> FuncReturnType {
8787

8888
pub fn bool__int__(arena: &mut PyArena, pyself: &PyObject) -> FuncReturnType {
8989
let value = expect_bool(&pyself, arena)?;
90-
Ok(PyObject::new_int(Integer::from(value)))
90+
Ok(arena.statics.get_int(Integer::from(value)))
9191
}
9292

9393

src/builtins/types/pyint.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,31 +91,31 @@ pub fn int__new__(arena: &mut PyArena, _pyclass: Rc<PyClass>, pyargs: &[PyObject
9191
new_value = Integer::from(0);
9292
}
9393

94-
Ok(PyObject::new_int(new_value)) // I don't know how to do inheritance with this
94+
Ok(arena.statics.get_int(new_value)) // I don't know how to do inheritance with this
9595
}
9696

9797
pub fn int__add__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> FuncReturnType {
9898
let (self_value, other_value) = parse_int_op_func_params(pyself, other, arena)?;
9999

100-
Ok(PyObject::new_int(self_value + other_value))
100+
Ok(arena.statics.get_int(self_value + other_value))
101101
}
102102

103103
pub fn int__sub__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> FuncReturnType {
104104
let (self_value, other_value) = parse_int_op_func_params(pyself, other, arena)?;
105105

106-
Ok(PyObject::new_int(self_value - other_value))
106+
Ok(arena.statics.get_int(self_value - other_value))
107107
}
108108

109109
pub fn int__rsub__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> FuncReturnType {
110110
let (self_value, other_value) = parse_int_op_func_params(pyself, other, arena)?;
111111

112-
Ok(PyObject::new_int(other_value - self_value))
112+
Ok(arena.statics.get_int(other_value - self_value))
113113
}
114114

115115
pub fn int__mul__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> FuncReturnType {
116116
let (self_value, other_value) = parse_int_op_func_params(pyself, other, arena)?;
117117

118-
Ok(PyObject::new_int(self_value * other_value))
118+
Ok(arena.statics.get_int(self_value * other_value))
119119
}
120120

121121
pub fn int__truediv__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> FuncReturnType {
@@ -137,7 +137,7 @@ pub fn int__pow__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> F
137137
return Ok(PyObject::new_float(self_value.to_f64().powf(other_value.to_f64())));
138138
}
139139

140-
Ok(PyObject::new_int(self_value.pow(u64::saturating_from(&other_value)))) // Caps exponent at the u64 limit
140+
Ok(arena.statics.get_int(self_value.pow(u64::saturating_from(&other_value)))) // Caps exponent at the u64 limit
141141
}
142142

143143
pub fn int__rpow__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) -> FuncReturnType {
@@ -147,7 +147,7 @@ pub fn int__rpow__(arena: &mut PyArena, pyself: &PyObject, other: &PyObject) ->
147147
return Ok(PyObject::new_float(other_value.to_f64().powf(self_value.to_f64())));
148148
}
149149

150-
Ok(PyObject::new_int(other_value.pow(u64::saturating_from(&self_value)))) // Caps exponent at the u64 limit
150+
Ok(arena.statics.get_int(other_value.pow(u64::saturating_from(&self_value)))) // Caps exponent at the u64 limit
151151
}
152152

153153
pub fn int__repr__(arena: &mut PyArena, pyself: &PyObject) -> FuncReturnType {

src/builtins/types/range.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ impl PyInstanceInternal for RangeInstance {
3030
None
3131
}
3232

33-
fn get_field(&self, key: &str, _pyarena: &mut PyArena) -> Option<PyObject> {
33+
fn get_field(&self, key: &str, arena: &mut PyArena) -> Option<PyObject> {
3434
match key {
35-
"start" => Some(PyObject::new_int(self.start.clone())), // TODO remove clone because every time field is accessed it'll created a new pyobject
36-
"stop" => Some(PyObject::new_int(self.stop.clone())),
37-
"step" => Some(PyObject::new_int(self.step.clone())),
35+
"start" => Some(arena.statics.get_int_borrow(&self.start)), // TODO remove clone because every time field is accessed it'll created a new pyobject
36+
"stop" => Some(arena.statics.get_int_borrow(&self.stop)),
37+
"step" => Some(arena.statics.get_int_borrow(&self.step)),
3838
_ => None
3939
}
4040
}

0 commit comments

Comments
 (0)