Skip to content

Commit 1fe7b07

Browse files
committed
added booleans
1 parent 0fd7435 commit 1fe7b07

20 files changed

+435
-104
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ mopa = "0.2.2"
1111
ahash = "0.8.11"
1212

1313
[profile.release]
14-
#debug = true
14+
debug = true
1515

flamegraph.svg

Lines changed: 2 additions & 2 deletions
Loading

src/builtins.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pub mod function_utils;
66
pub mod globals;
77
pub mod pyfloat;
88
pub mod structure;
9-
pub mod functions;
9+
pub mod functions;
10+
pub mod pybool;

src/builtins/function_utils.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ use std::rc::Rc;
33
use crate::builtins::object::expect_class;
44
use crate::builtins::structure::magic_methods::PyMagicMethod;
55
use crate::builtins::structure::pyclass::PyClass;
6-
use crate::builtins::structure::pyobject::{FuncReturnType, PyImmutableObject, PyInternalFunction, PyMutableObject, PyObject};
6+
use crate::builtins::structure::pyobject::{FuncReturnType, PyInternalFunction, PyInternalObject, PyMutableObject, PyObject};
77
use crate::pyarena::PyArena;
88

99
pub fn call_function(func: PyObject, args: &[PyObject], arena: &mut PyArena) -> FuncReturnType {
1010
match func {
11-
PyObject::Immutable(inner) => {
12-
match &*inner {
13-
PyImmutableObject::InternalSlot(func) => eval_internal_func(func.clone(), args, arena),
14-
PyImmutableObject::InternalClass(pyclass) => eval_obj_init(pyclass.clone(), args, arena),
15-
_ => {panic!("Immutable object is not a function")}
11+
PyObject::Internal(inner) => {
12+
match inner {
13+
PyInternalObject::InternalFunction(func) => eval_internal_func(func, args, arena),
14+
PyInternalObject::InternalClass(pyclass) => eval_obj_init(pyclass, args, arena)
1615
}
1716
}
1817
PyObject::Mutable(inner) => {
@@ -21,17 +20,16 @@ pub fn call_function(func: PyObject, args: &[PyObject], arena: &mut PyArena) ->
2120
_ => {panic!("Mutable object is not a function")}
2221
}
2322
}
24-
PyObject::IteratorFlag(_) => {panic!("IteratorFlag is not a function")}
23+
other => {panic!("{:?} is not a function", other)}
2524
}
2625
}
2726

2827
pub fn call_function_1_arg_min(func: PyObject, first_arg: &PyObject, args: &[PyObject], arena: &mut PyArena) -> FuncReturnType {
2928
match func {
30-
PyObject::Immutable(inner) => {
31-
match &*inner {
32-
PyImmutableObject::InternalSlot(func) => eval_internal_func_1_arg_min(func.clone(), first_arg, args, arena),
33-
PyImmutableObject::InternalClass(_pyclass) => panic!("This function should not be used to initialize a class"),
34-
_ => {panic!("Immutable object is not a function")}
29+
PyObject::Internal(inner) => {
30+
match inner {
31+
PyInternalObject::InternalFunction(func) => eval_internal_func_1_arg_min(func, first_arg, args, arena),
32+
PyInternalObject::InternalClass(_pyclass) => panic!("This function should not be used to initialize a class")
3533
}
3634
}
3735
PyObject::Mutable(inner) => {
@@ -40,7 +38,7 @@ pub fn call_function_1_arg_min(func: PyObject, first_arg: &PyObject, args: &[PyO
4038
_ => {panic!("Mutable object is not a function")}
4139
}
4240
}
43-
PyObject::IteratorFlag(_) => {panic!("IteratorFlag is not a function")}
41+
other => {panic!("{:?} is not a function", other)}
4442
}
4543
}
4644

src/builtins/functions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod print;
2-
pub mod math_op;
2+
pub mod math_op;
3+
pub mod compare;

src/builtins/functions/compare.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use crate::builtins::function_utils::call_function_1_arg_min;
2+
use crate::builtins::structure::magic_methods::PyMagicMethod;
3+
use crate::builtins::structure::pyobject::{FuncReturnType, PyObject};
4+
use crate::parser::Comparitor;
5+
use crate::pyarena::PyArena;
6+
7+
pub fn compare_op(left: &PyObject, right: &PyObject, comp: &Comparitor, arena: &mut PyArena) -> FuncReturnType {
8+
match comp {
9+
Comparitor::Equal => left_hand_compare_op(&PyMagicMethod::Eq, left, right, arena),
10+
Comparitor::NotEqual => left_hand_compare_op(&PyMagicMethod::Ne, left, right, arena),
11+
Comparitor::LessThan => left_hand_compare_op(&PyMagicMethod::Lt, left, right, arena),
12+
Comparitor::LessThanOrEqual => left_hand_compare_op(&PyMagicMethod::Le, left, right, arena),
13+
Comparitor::GreaterThan => left_hand_compare_op(&PyMagicMethod::Gt, left, right, arena),
14+
Comparitor::GreaterThanOrEqual => left_hand_compare_op(&PyMagicMethod::Ge, left, right, arena),
15+
16+
Comparitor::Is => {todo!()}
17+
Comparitor::IsNot => {todo!()}
18+
Comparitor::In => {todo!()}
19+
Comparitor::NotIn => {todo!()}
20+
}
21+
}
22+
23+
fn left_hand_compare_op(op: &PyMagicMethod, left: &PyObject, right: &PyObject, arena: &mut PyArena) -> FuncReturnType {
24+
let left_compare_func = left.get_magic_method(op, arena);
25+
26+
if let Some(left_compare_func) = left_compare_func {
27+
let left_compare = call_function_1_arg_min(left_compare_func, left, &[right.clone()], arena);
28+
29+
return match left_compare {
30+
Ok(result) => Ok(result),
31+
Err(err) => {
32+
if err.is_same_type(&arena.exceptions.not_implemented_error) {
33+
return right_hand_compare_op(op, left, right, arena)
34+
}
35+
Err(err)
36+
},
37+
};
38+
}
39+
40+
right_hand_compare_op(op, left, right, arena)
41+
}
42+
43+
fn right_hand_compare_op(op: &PyMagicMethod, left: &PyObject, right: &PyObject, arena: &mut PyArena) -> FuncReturnType {
44+
let right_op = flip_to_right_hand_op(op);
45+
let right_compare_func = right.get_magic_method(right_op, arena);
46+
47+
if let Some(right_compare_func) = right_compare_func {
48+
let right_compare = call_function_1_arg_min(right_compare_func, right, &[left.clone()], arena);
49+
50+
return match right_compare {
51+
Ok(result) => Ok(result),
52+
Err(err) => {
53+
if err.is_same_type(&arena.exceptions.not_implemented_error) {
54+
let message = format!("'{}' not supported between instances of '{}' and '{}'", op, left.clone_class(arena).get_name(), right.clone_class(arena).get_name());
55+
return Err(arena.exceptions.type_error.instantiate(message));
56+
}
57+
Err(err)
58+
},
59+
};
60+
}
61+
62+
let message = format!("'{}' not supported between instances of '{}' and '{}'", op, left.clone_class(arena).get_name(), right.clone_class(arena).get_name());
63+
Err(arena.exceptions.type_error.instantiate(message))
64+
}
65+
66+
fn flip_to_right_hand_op(op: &PyMagicMethod) -> &PyMagicMethod {
67+
match op {
68+
PyMagicMethod::Eq => {&PyMagicMethod::Eq}
69+
PyMagicMethod::Ne => {&PyMagicMethod::Ne}
70+
PyMagicMethod::Lt => {&PyMagicMethod::Gt}
71+
PyMagicMethod::Le => {&PyMagicMethod::Ge}
72+
PyMagicMethod::Gt => {&PyMagicMethod::Lt}
73+
PyMagicMethod::Ge => {&PyMagicMethod::Le}
74+
e => {panic!("{} is not a handed compare operation", e)}
75+
}
76+
}

src/builtins/functions/print.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ use crate::pyarena::PyArena;
44

55
pub fn py_print(arena: &mut PyArena, args: &[PyObject]) -> FuncReturnType {
66
let sep = " ";
7-
let mut strs = Vec::new();
87

9-
for arg in args {
10-
strs.push(py_str_tmp(arg, arena)?.expect_immutable().expect_string());
11-
}
8+
let str_fold = args.iter().try_fold(Vec::new(), |mut acc, arg| {
9+
acc.push(py_str_tmp(arg, arena)?.expect_immutable().expect_string());
10+
Ok(acc)
11+
})?;
1212

13-
let result = strs.join(sep);
13+
let result = str_fold.join(sep);
1414

1515
println!("{}", result);
1616

src/builtins/globals.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::rc::Rc;
33
use ahash::AHashMap;
44
use crate::builtins::object::{get_object_class};
55
use crate::builtins::functions::print::{py_print};
6+
use crate::builtins::pybool::get_bool_class;
67
use crate::builtins::pyfloat::get_float_class;
78
use crate::builtins::pyint::{get_int_class};
89
use crate::builtins::range::{get_range_class, get_range_iterator_class};
@@ -13,6 +14,7 @@ use crate::builtins::structure::pyobject::{ManyArgFuncType, PyInternalFunction,
1314
pub struct Globals {
1415
pub object_class: Rc<PyClass>,
1516
pub int_class: Rc<PyClass>,
17+
pub bool_class: Rc<PyClass>,
1618
pub float_class: Rc<PyClass>,
1719
pub range_class: Rc<PyClass>,
1820
pub range_iterator_class: Rc<PyClass>,
@@ -22,15 +24,18 @@ pub struct Globals {
2224
impl Globals {
2325
pub(crate) fn new() -> Globals {
2426
let object_class = Rc::new(get_object_class());
25-
let int_class = Rc::new(get_int_class(object_class.clone()));
2627
let float_class = Rc::new(get_float_class(object_class.clone()));
28+
29+
let int_class = Rc::new(get_int_class(object_class.clone()));
30+
let bool_class = Rc::new(get_bool_class(int_class.clone()));
2731

2832
let range_class = Rc::new(get_range_class(object_class.clone()));
2933
let range_iterator_class = Rc::new(get_range_iterator_class(object_class.clone()));
3034

3135
Globals {
3236
object_class,
3337
int_class,
38+
bool_class,
3439
float_class,
3540
range_class,
3641
range_iterator_class,
@@ -42,6 +47,7 @@ impl Globals {
4247
vec![
4348
("object".to_string(), Cell::new(PyObject::new_internal_class(self.object_class.clone()))),
4449
("int".to_string(), Cell::new(PyObject::new_internal_class(self.int_class.clone()))),
50+
("bool".to_string(), Cell::new(PyObject::new_internal_class(self.bool_class.clone()))),
4551
("float".to_string(), Cell::new(PyObject::new_internal_class(self.float_class.clone()))),
4652
("range".to_string(), Cell::new(PyObject::new_internal_class(self.range_class.clone()))),
4753
("print".to_string(), Cell::new(PyObject::new_internal_func(self.print_func.clone()))),

src/builtins/object.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1+
#![allow(non_snake_case)]
12
use std::rc::Rc;
23
use ahash::AHashMap;
34
use crate::builtins::function_utils::call_function;
45
use crate::builtins::structure::magic_methods::{py_magic_methods_defaults, PyMagicMethod, PyMagicMethods};
56
use crate::builtins::structure::pyclass::PyClass;
67
use crate::builtins::structure::pyinstance::PyInstance;
7-
use crate::builtins::structure::pyobject::{InitFuncType, EmptyFuncReturnType, FuncReturnType, NewFuncType, UnaryFuncType, PyObject, PyMutableObject, PyImmutableObject};
8+
use crate::builtins::structure::pyobject::{InitFuncType, EmptyFuncReturnType, FuncReturnType, NewFuncType, UnaryFuncType, PyObject, PyMutableObject, PyImmutableObject, PyInternalObject};
89
use crate::builtins::structure::pyobject::PyInternalFunction::{InitFunc, NewFunc, UnaryFunc};
910
use crate::pyarena::PyArena;
1011

1112

1213
pub fn expect_class(pyobj: &PyObject) -> Rc<PyClass> {
13-
match **pyobj.expect_immutable() {
14-
PyImmutableObject::InternalClass(ref class) => class.clone(),
14+
match pyobj.expect_internal() {
15+
PyInternalObject::InternalClass(class) => class.clone(),
1516
_ => panic!("Expected class"),
1617
}
1718
}

src/builtins/pybool.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#![allow(non_snake_case)]
2+
use std::rc::Rc;
3+
use ahash::AHashMap;
4+
use crate::builtins::function_utils::call_function_1_arg_min;
5+
use crate::builtins::structure::magic_methods::{py_magic_methods_defaults, PyMagicMethod, PyMagicMethods};
6+
use crate::builtins::structure::pyclass::PyClass;
7+
use crate::builtins::structure::pyexception::PyException;
8+
use crate::builtins::structure::pyobject::{FuncReturnType, NewFuncType, PyImmutableObject, PyObject, UnaryFuncType};
9+
use crate::builtins::structure::pyobject::PyInternalFunction::{NewFunc, UnaryFunc};
10+
use crate::pyarena::PyArena;
11+
12+
13+
pub fn expect_bool(pyobj: &PyObject, arena: &mut PyArena) -> Result<bool, PyException> {
14+
match **pyobj.expect_immutable() {
15+
PyImmutableObject::Bool(ref value) => {Ok(*value)}
16+
ref value => {
17+
let message = format!("'{}' object cannot be interpreted as a boolean", value.get_class(arena).get_name());
18+
Err(arena.exceptions.type_error.instantiate(message))
19+
},
20+
}
21+
}
22+
23+
24+
pub fn bool__new__(arena: &mut PyArena, _pyclass: Rc<PyClass>, pyargs: &[PyObject]) -> FuncReturnType { // error handling
25+
let value = pyargs.first().unwrap();
26+
let bool_magic_method = value.expect_immutable().get_magic_method(&PyMagicMethod::Bool, arena);
27+
let bool_magic_method = bool_magic_method.unwrap_or_else(|| panic!("Object has no __str__ method"));
28+
let py_bool_value = call_function_1_arg_min(bool_magic_method, value, &[], arena)?;
29+
30+
let _bool_value = expect_bool(&py_bool_value, arena)?;
31+
32+
Ok(py_bool_value)
33+
}
34+
35+
36+
pub fn bool__repr__(arena: &mut PyArena, pyself: &PyObject) -> FuncReturnType {
37+
let value = expect_bool(&pyself, arena)?;
38+
Ok(PyObject::new_string(if value { "True".to_string() } else {"False".to_string()}))
39+
}
40+
41+
pub fn bool__bool__(arena: &mut PyArena, pyself: &PyObject) -> FuncReturnType {
42+
let value = expect_bool(&pyself, arena)?;
43+
Ok(PyObject::new_bool(value))
44+
}
45+
46+
pub fn bool__int__(arena: &mut PyArena, pyself: &PyObject) -> FuncReturnType {
47+
let value = expect_bool(&pyself, arena)?;
48+
Ok(PyObject::new_int(value as i64))
49+
}
50+
51+
52+
53+
pub fn get_bool_class(int_class: Rc<PyClass>) -> PyClass {
54+
PyClass::Internal {
55+
name: "bool".to_string(),
56+
super_classes: vec![int_class],
57+
attributes: AHashMap::new(),
58+
magic_methods: PyMagicMethods {
59+
__new__: Some(Rc::new(NewFunc(&(bool__new__ as NewFuncType)))),
60+
61+
__repr__: Some(Rc::new(UnaryFunc(&(bool__repr__ as UnaryFuncType)))),
62+
63+
__bool__: Some(Rc::new(UnaryFunc(&(bool__bool__ as UnaryFuncType)))),
64+
__int__: Some(Rc::new(UnaryFunc(&(bool__int__ as UnaryFuncType)))),
65+
66+
..py_magic_methods_defaults()
67+
}
68+
}.create()
69+
}
70+

0 commit comments

Comments
 (0)