Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Convert new_X_error to use a macro
  • Loading branch information
ShaharNaveh committed Jun 22, 2025
commit 8d2ad450f750256d44c47549edf304609a7406fe
140 changes: 52 additions & 88 deletions vm/src/vm/vm_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@ use crate::{
vm::VirtualMachine,
};

macro_rules! define_exception_fn {
// With doc
(
$fn_name:ident, $attr:ident,
doc = $doc:literal
) => {
#[doc = $doc]
pub fn $fn_name(&self, msg: String) -> PyBaseExceptionRef {
let err = self.ctx.exceptions.$attr.to_owned();
self.new_exception_msg(err, msg)
}
};

// Without doc
(
$fn_name:ident, $attr:ident
) => {
pub fn $fn_name(&self, msg: String) -> PyBaseExceptionRef {
let err = self.ctx.exceptions.$attr.to_owned();
self.new_exception_msg(err, msg)
}
};
}

/// Collection of object creation helpers
impl VirtualMachine {
/// Create a new python object
Expand Down Expand Up @@ -125,16 +149,6 @@ impl VirtualMachine {
)
}

pub fn new_lookup_error(&self, msg: String) -> PyBaseExceptionRef {
let lookup_error = self.ctx.exceptions.lookup_error.to_owned();
self.new_exception_msg(lookup_error, msg)
}

pub fn new_attribute_error(&self, msg: String) -> PyBaseExceptionRef {
let attribute_error = self.ctx.exceptions.attribute_error.to_owned();
self.new_exception_msg(attribute_error, msg)
}

pub fn new_no_attribute_error(&self, obj: PyObjectRef, name: PyStrRef) -> PyBaseExceptionRef {
let msg = format!(
"'{}' object has no attribute '{}'",
Expand All @@ -149,11 +163,6 @@ impl VirtualMachine {
attribute_error
}

pub fn new_type_error(&self, msg: String) -> PyBaseExceptionRef {
let type_error = self.ctx.exceptions.type_error.to_owned();
self.new_exception_msg(type_error, msg)
}

pub fn new_name_error(&self, msg: String, name: PyStrRef) -> PyBaseExceptionRef {
let name_error_type = self.ctx.exceptions.name_error.to_owned();
let name_error = self.new_exception_msg(name_error_type, msg);
Expand Down Expand Up @@ -199,11 +208,6 @@ impl VirtualMachine {
))
}

pub fn new_os_error(&self, msg: String) -> PyBaseExceptionRef {
let os_error = self.ctx.exceptions.os_error.to_owned();
self.new_exception_msg(os_error, msg)
}

pub fn new_errno_error(&self, errno: i32, msg: String) -> PyBaseExceptionRef {
let vm = self;
let exc_type =
Expand All @@ -213,17 +217,6 @@ impl VirtualMachine {
vm.new_exception(exc_type.to_owned(), vec![errno_obj, vm.new_pyobj(msg)])
}

pub fn new_system_error(&self, msg: String) -> PyBaseExceptionRef {
let sys_error = self.ctx.exceptions.system_error.to_owned();
self.new_exception_msg(sys_error, msg)
}

// TODO: remove & replace with new_unicode_decode_error_real
pub fn new_unicode_decode_error(&self, msg: String) -> PyBaseExceptionRef {
let unicode_decode_error = self.ctx.exceptions.unicode_decode_error.to_owned();
self.new_exception_msg(unicode_decode_error, msg)
}

pub fn new_unicode_decode_error_real(
&self,
encoding: PyStrRef,
Expand Down Expand Up @@ -254,12 +247,6 @@ impl VirtualMachine {
exc
}

// TODO: remove & replace with new_unicode_encode_error_real
pub fn new_unicode_encode_error(&self, msg: String) -> PyBaseExceptionRef {
let unicode_encode_error = self.ctx.exceptions.unicode_encode_error.to_owned();
self.new_exception_msg(unicode_encode_error, msg)
}

pub fn new_unicode_encode_error_real(
&self,
encoding: PyStrRef,
Expand Down Expand Up @@ -290,49 +277,12 @@ impl VirtualMachine {
exc
}

/// Create a new python ValueError object. Useful for raising errors from
/// python functions implemented in rust.
pub fn new_value_error(&self, msg: String) -> PyBaseExceptionRef {
let value_error = self.ctx.exceptions.value_error.to_owned();
self.new_exception_msg(value_error, msg)
}

pub fn new_buffer_error(&self, msg: String) -> PyBaseExceptionRef {
let buffer_error = self.ctx.exceptions.buffer_error.to_owned();
self.new_exception_msg(buffer_error, msg)
}

// TODO: don't take ownership should make the success path faster
pub fn new_key_error(&self, obj: PyObjectRef) -> PyBaseExceptionRef {
let key_error = self.ctx.exceptions.key_error.to_owned();
self.new_exception(key_error, vec![obj])
}

pub fn new_index_error(&self, msg: String) -> PyBaseExceptionRef {
let index_error = self.ctx.exceptions.index_error.to_owned();
self.new_exception_msg(index_error, msg)
}

pub fn new_not_implemented_error(&self, msg: String) -> PyBaseExceptionRef {
let not_implemented_error = self.ctx.exceptions.not_implemented_error.to_owned();
self.new_exception_msg(not_implemented_error, msg)
}

pub fn new_recursion_error(&self, msg: String) -> PyBaseExceptionRef {
let recursion_error = self.ctx.exceptions.recursion_error.to_owned();
self.new_exception_msg(recursion_error, msg)
}

pub fn new_zero_division_error(&self, msg: String) -> PyBaseExceptionRef {
let zero_division_error = self.ctx.exceptions.zero_division_error.to_owned();
self.new_exception_msg(zero_division_error, msg)
}

pub fn new_overflow_error(&self, msg: String) -> PyBaseExceptionRef {
let overflow_error = self.ctx.exceptions.overflow_error.to_owned();
self.new_exception_msg(overflow_error, msg)
}

#[cfg(any(feature = "parser", feature = "compiler"))]
pub fn new_syntax_error_maybe_incomplete(
&self,
Expand Down Expand Up @@ -531,16 +481,6 @@ impl VirtualMachine {
exc
}

pub fn new_runtime_error(&self, msg: String) -> PyBaseExceptionRef {
let runtime_error = self.ctx.exceptions.runtime_error.to_owned();
self.new_exception_msg(runtime_error, msg)
}

pub fn new_memory_error(&self, msg: String) -> PyBaseExceptionRef {
let memory_error_type = self.ctx.exceptions.memory_error.to_owned();
self.new_exception_msg(memory_error_type, msg)
}

pub fn new_stop_iteration(&self, value: Option<PyObjectRef>) -> PyBaseExceptionRef {
let dict = self.ctx.new_dict();
let args = if let Some(value) = value {
Expand Down Expand Up @@ -607,8 +547,32 @@ impl VirtualMachine {
)
}

pub fn new_eof_error(&self, msg: String) -> PyBaseExceptionRef {
let eof_error = self.ctx.exceptions.eof_error.to_owned();
self.new_exception_msg(eof_error, msg)
}
define_exception_fn!(new_lookup_error, lookup_error);
define_exception_fn!(new_eof_error, eof_error);
define_exception_fn!(new_attribute_error, attribute_error);
define_exception_fn!(new_type_error, type_error);
define_exception_fn!(new_os_error, os_error);
define_exception_fn!(new_system_error, system_error);

// TODO: remove & replace with new_unicode_decode_error_real
define_exception_fn!(new_unicode_decode_error, unicode_decode_error);

// TODO: remove & replace with new_unicode_encode_error_real
define_exception_fn!(new_unicode_encode_error, unicode_encode_error);

define_exception_fn!(
new_value_error,
value_error,
doc = "Create a new python ValueError object.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought of have this doc as part of the macro and only put the python exception name to template.
so it can look like:

define_exception_fn!(new_value_error, value_error, ValueError);
define_exception_fn!(new_index_error, index_error, IndexEror);

I can do it in a separate PR if you think that it would be beneficial

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree to auto-generate docs

Useful for raising errors from python functions implemented in rust."
);

define_exception_fn!(new_buffer_error, buffer_error);
define_exception_fn!(new_index_error, index_error);
define_exception_fn!(new_not_implemented_error, not_implemented_error);
define_exception_fn!(new_recursion_error, recursion_error);
define_exception_fn!(new_zero_division_error, zero_division_error);
define_exception_fn!(new_overflow_error, overflow_error);
define_exception_fn!(new_runtime_error, runtime_error);
define_exception_fn!(new_memory_error, memory_error);
}
Loading