Skip to content

Commit

Permalink
Add macros
Browse files Browse the repository at this point in the history
  • Loading branch information
BlueZeeKing committed Apr 16, 2024
1 parent b72a699 commit 43e9ca6
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 77 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ members = [
"crates/utils",
"crates/navx",
"crates/math",
"build-system/bindings",
"build-system/bindings", "crates/macros",
]
13 changes: 13 additions & 0 deletions crates/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "macros"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
darling = "0.20.8"
proc-macro2 = "1.0.79"
quote = "1.0.36"
syn = { version = "2.0.58", features = ["full"] }
120 changes: 120 additions & 0 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use darling::{ast::NestedMeta, FromMeta};
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::{parse_macro_input, parse_quote, FnArg, Ident, ItemFn, Token};

#[derive(FromMeta)]
struct Args {
#[darling(default)]
priority_name: Option<Ident>,
#[darling(default)]
function_name: Option<Ident>,
#[darling(default)]
subsystem_name: Option<Ident>,
#[darling(default)]
wait: Option<bool>,
}

#[proc_macro_attribute]
pub fn subsystem_task(args: TokenStream, input: TokenStream) -> TokenStream {
let args = match NestedMeta::parse_meta_list(args.into()) {
Ok(v) => v,
Err(e) => {
return TokenStream::from(darling::Error::from(e).write_errors());
}
};

let args = match Args::from_list(&args) {
Ok(v) => v,
Err(e) => {
return TokenStream::from(e.write_errors());
}
};

let input2: proc_macro2::TokenStream = input.clone().into();
let parsed_input = parse_macro_input!(input as ItemFn);

let mut new_fn = parsed_input.clone();

new_fn.sig.ident = args.function_name.unwrap_or_else(|| {
Ident::new(
&format!("{}_subsystem", parsed_input.sig.ident),
Span::call_site(),
)
});
new_fn.sig.asyncness = Some(Token![async](Span::call_site()));

let subsystem_name = args
.subsystem_name
.unwrap_or_else(|| Ident::new("subsystem", Span::call_site()));

let first = new_fn
.sig
.inputs
.first_mut()
.expect("The function must have an argument");

*first = parse_quote!(#subsystem_name: &::utils::subsystem::Subsystem<Self>);

let priority_name = args
.priority_name
.unwrap_or_else(|| Ident::new("priority", Span::call_site()));

new_fn.sig.inputs.push(parse_quote! {
#priority_name: u32
});

let name = parsed_input.sig.ident;

let func_args = parsed_input
.sig
.inputs
.into_iter()
.skip(1)
.filter_map(|arg| match arg {
FnArg::Receiver(_) => None,
FnArg::Typed(val) => Some(val),
})
.map(|val| val.pat);

let run = if parsed_input.sig.asyncness.is_none() {
quote! {
#subsystem_name.#name(#(#func_args),*)
}
} else {
quote! {
#subsystem_name.#name(#(#func_args),*).await
}
};

let wait = if args.wait.unwrap_or(false) {
quote! {
let res = #run;

::futures::future::pending::<()>().await;

drop(#subsystem_name);

res
}
} else {
run
};

new_fn.block = parse_quote! {
{
let mut #subsystem_name = #subsystem_name.lock(#priority_name).await;

#wait
}
};

quote! {
#input2

#new_fn

}
.into()
}
1 change: 1 addition & 0 deletions example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ revlib = { path = "../crates/revlib" }
ctre = { path = "../crates/ctre" }
utils = { path = "../crates/utils" }
hal-sys = { path = "../crates/hal-sys" }
macros = { path = "../crates/macros" }
futures = "0.3.28"
anyhow = "1.0.75"
63 changes: 16 additions & 47 deletions example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use robotrs::{
robot::AsyncRobot,
scheduler::guard,
time::delay,
yield_now, Deadzone, FailableDefault,
yield_now, Deadzone,
};
use subsystems::{Arm, Drivetrain, Intake};
use utils::{subsystem::Subsystem, trigger::TriggerExt, wait};
use utils::{subsystem::Subsystem, trigger::TriggerExt};

pub mod subsystems;

Expand Down Expand Up @@ -112,68 +112,37 @@ impl AsyncRobot for Robot {
anyhow::Ok(())
});

self.controller.y().while_pressed(|| async {
let mut arm = self.arm.lock(1).await;
arm.start_raise()?;

wait!();

anyhow::Ok(())
});

self.controller.a().while_pressed(|| async {
let mut arm = self.arm.lock(1).await;
arm.start_lower()?;

wait!();
self.controller
.y()
.while_pressed(|| Arm::start_raise_subsystem(&self.arm, 1));

anyhow::Ok(())
});
self.controller
.a()
.while_pressed(|| Arm::start_lower_subsystem(&self.arm, 1));

self.controller
.wait_right_y(AxisTarget::Up(0.65))
.while_pressed(|| async {
let mut intake = self.intake.lock(1).await;
intake.intake_cube()?;

wait!();

anyhow::Ok(())
});
.while_pressed(|| Intake::intake_cube_subsystem(&self.intake, 1));

self.controller
.wait_right_y(AxisTarget::Down(0.65))
.while_pressed(|| async {
let mut intake = self.intake.lock(1).await;
intake.intake_cone()?;

wait!();

anyhow::Ok(())
});
.while_pressed(|| Intake::intake_cone_subsystem(&self.intake, 1));

self.controller
.left_bumper()
.or(self.controller.right_bumper())
.while_pressed(|| async {
let mut intake = self.intake.lock(1).await;
intake.start_release()?;

wait!();

anyhow::Ok(())
});
.while_pressed(|| Intake::start_release_subsystem(&self.intake, 1));

Ok(())
}
}

impl FailableDefault for Robot {
fn failable_default() -> anyhow::Result<Self> {
impl Robot {
pub fn new() -> anyhow::Result<Self> {
Ok(Self {
drivetrain: Subsystem::new(FailableDefault::failable_default()?),
arm: Subsystem::new(FailableDefault::failable_default()?),
intake: Subsystem::new(FailableDefault::failable_default()?),
drivetrain: Subsystem::new(Drivetrain::new()?),
arm: Subsystem::new(Arm::new()?),
intake: Subsystem::new(Intake::new()?),
controller: XboxController::new(0)?,
})
}
Expand Down
4 changes: 1 addition & 3 deletions example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use robotrs::FailableDefault;

fn main() {
robotrs::scheduler::RobotScheduler::start_robot(example::Robot::failable_default);
robotrs::scheduler::RobotScheduler::start_robot(example::Robot::new);
}
16 changes: 6 additions & 10 deletions example/src/subsystems/arm.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use anyhow::Result;
use macros::subsystem_task;
use revlib::SparkMax;
use robotrs::{
control::ControlSafe,
motor::{IdleMode, SetIdleMode},
time::Alarm,
FailableDefault,
time::delay,
};
use std::time::Duration;

Expand All @@ -25,12 +25,14 @@ impl Arm {
Ok(Self { motor })
}

#[subsystem_task(wait)]
pub fn start_raise(&mut self) -> Result<()> {
self.motor.set(-ARM_SPEED)?;

Ok(())
}

#[subsystem_task(wait)]
pub fn start_lower(&mut self) -> Result<()> {
self.motor.set(ARM_SPEED)?;

Expand All @@ -40,7 +42,7 @@ impl Arm {
pub async fn raise(&mut self) -> Result<()> {
self.start_raise()?;

Alarm::new(Duration::from_secs(2)).await?;
delay(Duration::from_secs(2)).await;

self.stop();

Expand All @@ -50,7 +52,7 @@ impl Arm {
pub async fn lower(&mut self) -> Result<()> {
self.start_lower()?;

Alarm::new(Duration::from_secs(2)).await?;
delay(Duration::from_secs(2)).await;

self.stop();

Expand All @@ -63,9 +65,3 @@ impl ControlSafe for Arm {
self.motor.stop();
}
}

impl FailableDefault for Arm {
fn failable_default() -> Result<Self> {
Self::new()
}
}
7 changes: 0 additions & 7 deletions example/src/subsystems/drivetrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use revlib::SparkMax;
use robotrs::{
control::ControlSafe,
motor::{IdleMode, MotorController, SetIdleMode},
FailableDefault,
};

pub struct Drivetrain {
Expand Down Expand Up @@ -56,9 +55,3 @@ impl ControlSafe for Drivetrain {
self.right_motor.stop();
}
}

impl FailableDefault for Drivetrain {
fn failable_default() -> Result<Self> {
Self::new()
}
}
16 changes: 7 additions & 9 deletions example/src/subsystems/intake.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use anyhow::Result;
use macros::subsystem_task;
use revlib::SparkMax;
use robotrs::{
control::ControlSafe,
motor::{IdleMode, SetIdleMode},
time::Alarm,
FailableDefault,
time::delay,
};
use std::time::Duration;

Expand All @@ -30,16 +30,18 @@ impl Intake {
})
}

#[subsystem_task]
pub async fn release_cube(&mut self) -> Result<()> {
self.motor.set(-1.0)?;

Alarm::new(Duration::from_secs(1)).await?;
delay(Duration::from_secs(1)).await;

self.motor.stop();

Ok(())
}

#[subsystem_task(wait)]
pub fn intake_cube(&mut self) -> Result<()> {
self.motor.set(0.66)?;

Expand All @@ -48,6 +50,7 @@ impl Intake {
Ok(())
}

#[subsystem_task(wait)]
pub fn intake_cone(&mut self) -> Result<()> {
self.motor.set(-1.0)?;

Expand All @@ -56,6 +59,7 @@ impl Intake {
Ok(())
}

#[subsystem_task(wait)]
pub fn start_release(&mut self) -> Result<()> {
if let Some(item) = &self.last_item {
self.motor.set(match item {
Expand All @@ -73,9 +77,3 @@ impl ControlSafe for Intake {
self.motor.stop();
}
}

impl FailableDefault for Intake {
fn failable_default() -> Result<Self> {
Self::new()
}
}

0 comments on commit 43e9ca6

Please sign in to comment.