-
Notifications
You must be signed in to change notification settings - Fork 96
Remove instrs_enum macro #322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
added a new macro under `crust.rs` for making an enum that automatically provides the variant names under a compile time generated array. question: whether or not this should be its own macro or add functionality to `enum_with_order`, because something one could consider "instrusive" is having an associated constant named COUNT out of nowhere (possibly shadows an enum variant, will result in type errors usize <-> enum)
|
note: we could refactor both the order slice and the name slices into associated constants instead of named constants in the parent module: this would drastically simplify our syntax: enum_with_order_and_names! {
#[derive(Clone, Copy)
#[repr(u8)]
- enum Instr in INSTR_ORDER, names in INSTR_NAME {
+ enum Instr {
...
}
}and we could access the associated constants like so: ...
- let curr: *const c_char = (*INSTR_NAMES)[i];
+ let curr: *const c_char = (*Instr::NAMES)[i];
...
- return Some((*INSTR_ORDER)[i]);
+ return Some((*Instr::ORDER)[i]); |
If we keep following rust's naming conventions (CamelCase for enum variants and SCREAMING_CASE for constants), this should be an issue. |
|
instruction names currently don't follow the CamelCase naming convention but rather SCREAMING_CASE, so they could possibly collide if an instruction named |
|
what about making them constant methods ? impl $name {
const fn order() -> *const [$name] { &[$($name::$items,)*] }
const fn names() -> *const [*const c_char] { &[$(c!(stringify!($items)),)*] }
const fn count() -> usize { $name::names().len() }
} |
that could work, but we then give up the method names |
|
🏳 |
…it enum discriminant support
|
i implemented said simplifications, but this last commit mostly exists for "check out this battle i fought with the compiler", because in order to implement explicit enum discriminants: enum_with_order! {
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
enum AddrMode {
- IMM,
+ IMM = 0,
ZP,i had to reimplement enum variant resolving logic in const. it works as expected, and if it doesn't, only panics at compiletime. i don't expect this commit specifically to get merged, as it introduces 220+ lines of code that should've been handled by rust instead of us. |
|
also, if you were wondering, expansion looks like this: // Recursive expansion of enum_with_order! macro
// ==============================================
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum AddrMode {
IMM = 0,
ZP,
ZP_X,
ZP_Y,
ABS,
ABS_X,
ABS_Y,
IND_X,
IND_Y,
ACC,
REL,
IND,
IMPL,
}
impl AddrMode {
const __ORDER_AND_NAMES_SLICES: (*const [AddrMode], *const [*const c_char]) = {
#[allow(unused_imports)]
use crate::c;
use crate::fighting_consteval::*;
const fn _assert_copy<T: Copy>() {}
const _: () = _assert_copy::<AddrMode>();
const DECLS_AMOUNT: usize = UNORDERED_DECLS.len();
const UNORDERED_DECLS: *const [(AddrMode, *const c_char)] = {
&[
(AddrMode::IMM, "IMM\u{0}".as_ptr() as *const c_char),
(AddrMode::ZP, "ZP\u{0}".as_ptr() as *const c_char),
(AddrMode::ZP_X, "ZP_X\u{0}".as_ptr() as *const c_char),
(AddrMode::ZP_Y, "ZP_Y\u{0}".as_ptr() as *const c_char),
(AddrMode::ABS, "ABS\u{0}".as_ptr() as *const c_char),
(AddrMode::ABS_X, "ABS_X\u{0}".as_ptr() as *const c_char),
(AddrMode::ABS_Y, "ABS_Y\u{0}".as_ptr() as *const c_char),
(AddrMode::IND_X, "IND_X\u{0}".as_ptr() as *const c_char),
(AddrMode::IND_Y, "IND_Y\u{0}".as_ptr() as *const c_char),
(AddrMode::ACC, "ACC\u{0}".as_ptr() as *const c_char),
(AddrMode::REL, "REL\u{0}".as_ptr() as *const c_char),
(AddrMode::IND, "IND\u{0}".as_ptr() as *const c_char),
(AddrMode::IMPL, "IMPL\u{0}".as_ptr() as *const c_char),
]
};
const AMOUNT_SPECIFIED: usize = SPECIFIED_DISCRIMINANTS.len();
const SPECIFIED_DISCRIMINANTS: *const [(AddrMode, *const c_char, u128)] =
{ &[(AddrMode::IMM, "IMM\u{0}".as_ptr() as *const c_char, 0)] };
const RES: ([AddrMode; DECLS_AMOUNT], [*const c_char; DECLS_AMOUNT]) = unsafe {
#[allow(unused_imports)]
use OrderDeclsError::*;
match const {
order_decls_properly::<AddrMode, DECLS_AMOUNT, AMOUNT_SPECIFIED>(
&*mkarray::<_, DECLS_AMOUNT>(UNORDERED_DECLS),
&*mkarray::<_, AMOUNT_SPECIFIED>(SPECIFIED_DISCRIMINANTS),
)
} {
Ok(v) => v,
Err(OrderDeclsError::RanOutOfDecls) => {
core::panicking::panic_fmt(core::const_format_args!("enum_with_order: failed to order enum variants properly.\n\tthis is likely due to discriminant requirements leaving holes in the resulting ORDER_SLICE, which is not supported"));
}
Err(OrderDeclsError::FinalSliceMissingEntries) => {
core::panicking::panic_fmt(core::const_format_args!("enum_with_order: critical sanity check failed at compile time. this is a bug.\n\tthere were entries in your declaration that did not end up in the resulting `Self::ORDER_SLICE`"));
}
}
};
(&RES.0, &RES.1)
};
pub const ORDER_SLICE: *const [AddrMode] = AddrMode::__ORDER_AND_NAMES_SLICES.0;
pub const NAMES_SLICE: *const [*const c_char] = AddrMode::__ORDER_AND_NAMES_SLICES.1;
pub const VARIANT_COUNT: usize = unsafe { (&*AddrMode::ORDER_SLICE).len() };
} |
in order to remove instrs_enum macro, i decided to expand
enum_with_orderwith a compiletime generated array of variant names. this allows the implementation ofinstr_from_stringoutside of a macro.however, i didn't want to make any breaking changes to the repo, so i made a new macro instead.
we could remove this new macro and incorporate the changes to the
enum_with_ordermacro, which would add into its syntax:enum MyEnum in MY_ENUM_ORDER, names in MY_ENUM_NAMES.i also added support for multiple attribute macros because
Instrsusedrepr(u8)andderivesimultaneously.hopefully this was in the Crust way of doing things!