diff --git a/pros/Cargo.toml b/pros/Cargo.toml index fee3b133..b451454a 100644 --- a/pros/Cargo.toml +++ b/pros/Cargo.toml @@ -23,7 +23,6 @@ futures = { version = "0.3.28", default-features = false, features = ["alloc"] } slab = { version = "0.4.9", default-features = false } hashbrown = { version = "0.14.1", default-features = true } async-trait = "0.1.73" -cfg-if = "1.0.0" async-task = { version = "4.5.0", default-features = false } waker-fn = "1.1.1" diff --git a/pros/examples/accessories.rs b/pros/examples/accessories.rs index 6ddf6579..42108d80 100644 --- a/pros/examples/accessories.rs +++ b/pros/examples/accessories.rs @@ -7,7 +7,7 @@ use pros::prelude::*; #[derive(Debug, Default)] struct ExampleRobot; #[async_trait] -impl Robot for ExampleRobot { +impl AsyncRobot for ExampleRobot { async fn opcontrol(&mut self) -> pros::Result { let handle = pros::async_runtime::spawn(async { for _ in 0..5 { @@ -54,7 +54,7 @@ impl Robot for ExampleRobot { } } } -robot!(ExampleRobot); +async_robot!(ExampleRobot); fn left_button_callback() { println!("Left button pressed!"); diff --git a/pros/examples/basic.rs b/pros/examples/basic.rs index 85b5116a..e30f6d21 100644 --- a/pros/examples/basic.rs +++ b/pros/examples/basic.rs @@ -6,11 +6,11 @@ use pros::prelude::*; #[derive(Default)] pub struct Robot; #[async_trait] -impl pros::Robot for Robot { +impl AsyncRobot for Robot { async fn opcontrol(&mut self) -> pros::Result { println!("basic exasmple"); Ok(()) } } -robot!(Robot); \ No newline at end of file +async_robot!(Robot); \ No newline at end of file diff --git a/pros/src/async_runtime/executor.rs b/pros/src/async_runtime/executor.rs index b45343ba..3df183fa 100644 --- a/pros/src/async_runtime/executor.rs +++ b/pros/src/async_runtime/executor.rs @@ -1,9 +1,9 @@ use core::{ - cell::{Cell, RefCell}, + cell::RefCell, future::Future, - pin::{pin, Pin}, + pin::Pin, sync::atomic::{AtomicBool, Ordering}, - task::{Context, Poll, Waker}, + task::{Context, Poll}, }; use alloc::{collections::VecDeque, sync::Arc}; diff --git a/pros/src/async_runtime/reactor.rs b/pros/src/async_runtime/reactor.rs index f2f07f45..1be29738 100644 --- a/pros/src/async_runtime/reactor.rs +++ b/pros/src/async_runtime/reactor.rs @@ -1,6 +1,6 @@ -use core::{cell::RefCell, cmp::Reverse, task::Waker}; +use core::task::Waker; -use alloc::{collections::BTreeMap, vec::Vec}; +use alloc::collections::BTreeMap; pub struct Sleepers { sleepers: BTreeMap, diff --git a/pros/src/lib.rs b/pros/src/lib.rs index a3cf2b59..8b6c0307 100644 --- a/pros/src/lib.rs +++ b/pros/src/lib.rs @@ -39,7 +39,7 @@ pub type Result = core::result::Result Result { Ok(()) } @@ -54,16 +54,83 @@ pub trait Robot { } } +pub trait SyncRobot { + fn opcontrol(&mut self) -> Result { + Ok(()) + } + fn auto(&mut self) -> Result { + Ok(()) + } + fn disabled(&mut self) -> Result { + Ok(()) + } + fn comp_init(&mut self) -> Result { + Ok(()) + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __gen_sync_exports { + ($rbt:ty) => { + pub static mut ROBOT: Option<$rbt> = None; + + #[doc(hidden)] + #[no_mangle] + extern "C" fn opcontrol() { + <$rbt as $crate::SyncRobot>::opcontrol(unsafe { + ROBOT + .as_mut() + .expect("Expected initialize to run before opcontrol") + }) + .unwrap(); + } + + #[doc(hidden)] + #[no_mangle] + extern "C" fn autonomous() { + <$rbt as $crate::SyncRobot>::auto(unsafe { + ROBOT + .as_mut() + .expect("Expected initialize to run before opcontrol") + }) + .unwrap(); + } + + #[doc(hidden)] + #[no_mangle] + extern "C" fn disabled() { + <$rbt as $crate::SyncRobot>::disabled(unsafe { + ROBOT + .as_mut() + .expect("Expected initialize to run before opcontrol") + }) + .unwrap(); + } + + #[doc(hidden)] + #[no_mangle] + extern "C" fn competition_initialize() { + <$rbt as $crate::SyncRobot>::comp_init(unsafe { + ROBOT + .as_mut() + .expect("Expected initialize to run before opcontrol") + }) + .unwrap(); + } + }; +} + #[doc(hidden)] #[macro_export] -macro_rules! __gen_exports { +macro_rules! __gen_async_exports { ($rbt:ty) => { pub static mut ROBOT: Option<$rbt> = None; #[doc(hidden)] #[no_mangle] extern "C" fn opcontrol() { - $crate::async_runtime::block_on(<$rbt as $crate::Robot>::opcontrol(unsafe { + $crate::async_runtime::block_on(<$rbt as $crate::AsyncRobot>::opcontrol(unsafe { ROBOT .as_mut() .expect("Expected initialize to run before opcontrol") @@ -74,7 +141,7 @@ macro_rules! __gen_exports { #[doc(hidden)] #[no_mangle] extern "C" fn autonomous() { - $crate::async_runtime::block_on(<$rbt as $crate::Robot>::opcontrol(unsafe { + $crate::async_runtime::block_on(<$rbt as $crate::AsyncRobot>::opcontrol(unsafe { ROBOT .as_mut() .expect("Expected initialize to run before auto") @@ -85,7 +152,7 @@ macro_rules! __gen_exports { #[doc(hidden)] #[no_mangle] extern "C" fn disabled() { - $crate::async_runtime::block_on(<$rbt as $crate::Robot>::opcontrol(unsafe { + $crate::async_runtime::block_on(<$rbt as $crate::AsyncRobot>::opcontrol(unsafe { ROBOT .as_mut() .expect("Expected initialize to run before disabled") @@ -96,7 +163,7 @@ macro_rules! __gen_exports { #[doc(hidden)] #[no_mangle] extern "C" fn competition_initialize() { - $crate::async_runtime::block_on(<$rbt as $crate::Robot>::opcontrol(unsafe { + $crate::async_runtime::block_on(<$rbt as $crate::AsyncRobot>::opcontrol(unsafe { ROBOT .as_mut() .expect("Expected initialize to run before comp_init") @@ -106,7 +173,71 @@ macro_rules! __gen_exports { }; } -/// Allows your robot code to be executed by the pros kernel. +/// Allows your async robot code to be executed by the pros kernel. +/// If your robot struct implements Default then you can just supply this macro with its type. +/// If not, you can supply an expression that returns your robot type to initialize your robot struct. +/// +/// Example of using the macro with a struct that implements Default: +/// ```rust +/// use pros::prelude::*; +/// #[derive(Default)] +/// struct ExampleRobot; +/// #[async_trait] +/// impl AsyncRobot for ExampleRobot { +/// asnyc fn opcontrol(&mut self) -> pros::Result { +/// println!("Hello, world!"); +/// Ok(()) +/// } +/// } +/// async_robot!(ExampleRobot); +/// ``` +/// +/// Example of using the macro with a struct that does not implement Default: +/// ```rust +/// use pros::prelude::*; +/// struct ExampleRobot { +/// x: i32, +/// } +/// #[async_trait] +/// impl AsyncRobot for ExampleRobot { +/// async fn opcontrol(&mut self) -> pros::Result { +/// println!("Hello, world! {}", self.x); +/// Ok(()) +/// } +/// } +/// impl ExampleRobot { +/// pub fn new() -> Self { +/// Self { x: 5 } +/// } +/// } +/// async_robot!(ExampleRobot, ExampleRobot::new()); +#[macro_export] +macro_rules! async_robot { + ($rbt:ty) => { + $crate::__gen_async_exports!($rbt); + + #[no_mangle] + extern "C" fn initialize() { + ::pros::task::__init_main(); + unsafe { + ROBOT = Some(Default::default()); + } + } + }; + ($rbt:ty, $init:expr) => { + $crate::__gen_async_exports!($rbt); + + #[no_mangle] + extern "C" fn initialize() { + ::pros::task::__init_main(); + unsafe { + ROBOT = Some($init); + } + } + }; +} + +/// Allows your sync robot code to be executed by the pros kernel. /// If your robot struct implements Default then you can just supply this macro with its type. /// If not, you can supply an expression that returns your robot type to initialize your robot struct. /// @@ -115,13 +246,13 @@ macro_rules! __gen_exports { /// use pros::prelude::*; /// #[derive(Default)] /// struct ExampleRobot; -/// impl Robot for ExampleRobot { -/// fn opcontrol(&mut self) -> Result { +/// impl SyncRobot for ExampleRobot { +/// asnyc fn opcontrol(&mut self) -> pros::Result { /// println!("Hello, world!"); /// Ok(()) /// } /// } -/// robot!(ExampleRobot); +/// sync_robot!(ExampleRobot); /// ``` /// /// Example of using the macro with a struct that does not implement Default: @@ -130,8 +261,8 @@ macro_rules! __gen_exports { /// struct ExampleRobot { /// x: i32, /// } -/// impl Robot for ExampleRobot { -/// fn opcontrol(&mut self) -> Result { +/// impl SyncRobot for ExampleRobot { +/// async fn opcontrol(&mut self) -> pros::Result { /// println!("Hello, world! {}", self.x); /// Ok(()) /// } @@ -141,11 +272,11 @@ macro_rules! __gen_exports { /// Self { x: 5 } /// } /// } -/// robot!(ExampleRobot, ExampleRobot::new()); +/// sync_robot!(ExampleRobot, ExampleRobot::new()); #[macro_export] -macro_rules! robot { +macro_rules! sync_robot { ($rbt:ty) => { - $crate::__gen_exports!($rbt); + $crate::__gen_sync_exports!($rbt); #[no_mangle] extern "C" fn initialize() { @@ -156,7 +287,7 @@ macro_rules! robot { } }; ($rbt:ty, $init:expr) => { - $crate::__gen_exports!($rbt); + $crate::__gen_sync_exports!($rbt); #[no_mangle] extern "C" fn initialize() { @@ -169,8 +300,8 @@ macro_rules! robot { } pub mod prelude { - pub use crate::robot; - pub use crate::Robot; + pub use crate::{ async_robot, sync_robot }; + pub use crate::{ AsyncRobot, SyncRobot }; // Import Box from alloc so that it can be used in async_trait! pub use crate::{async_trait, os_task_local, print, println}; diff --git a/pros/src/task.rs b/pros/src/task.rs index 50af39d1..0bebb35c 100644 --- a/pros/src/task.rs +++ b/pros/src/task.rs @@ -1,7 +1,6 @@ use core::{cell::RefCell, future::Future, hash::Hash, panic, ptr::NonNull, task::Poll}; use alloc::boxed::Box; -use cfg_if::cfg_if; use hashbrown::HashMap; use slab::Slab; use snafu::Snafu;