Skip to content

Commit

Permalink
Merge pull request #23 from DLR-FT/improve-ergonomics
Browse files Browse the repository at this point in the history
allow cold and warm start for the same function & add set_mode & add tests
  • Loading branch information
wucke13 authored Jul 28, 2023
2 parents 27975fb + c5e4730 commit 0aa3a19
Show file tree
Hide file tree
Showing 19 changed files with 144 additions and 89 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ strum = ["dep:strum"]

[dependencies]
serde = { version = "1.0", features = ["derive"], default-features = false, optional = true }
strum = { version = "0.24", features = ["derive"], default-features = false, optional = true }
strum = { version = "0.25", features = ["derive"], default-features = false, optional = true }
a653rs_macros = { version = "0.3.1", path = "macros", optional = true }

[dev-dependencies]
Expand Down
8 changes: 4 additions & 4 deletions macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ proc-macro = true
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = [ "full" ] }
syn = { version = "2.0", features = [ "full" ] }
static_assertions = "1.1"
bytesize = "1.2"
strum = { version = "0.24", features = ["derive"] }
darling = "0.14"
itertools = "0.10"
strum = { version = "0.25", features = ["derive"] }
darling = "0.20"
itertools = "0.11"
convert_case = "0.6"
humantime = "2.1"

Expand Down
8 changes: 6 additions & 2 deletions macros/src/generate/apex/partition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ impl Context {
let ctx = self.get_context_ident();
parse_quote! {
impl<'a, H> #ctx <'a, H> {
pub fn get_partition_status(&self) -> PartitionStatus {
Partition::get_partition_status()
pub fn get_partition_status(&self) -> a653rs::prelude::PartitionStatus {
Partition::get_status()
}

pub fn set_partition_mode(&self, mode: a653rs::prelude::OperatingMode) -> Result<(), Error> {
Partition::set_mode(mode)
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions macros/src/parse/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::str::FromStr;
use darling::{FromAttributes, FromMeta};
use proc_macro2::Ident;
use quote::format_ident;
use strum::{Display, EnumDiscriminants, EnumIter, EnumString};
use strum::{Display, EnumString};
// use strum::{Display, EnumString, EnumVariantNames, VariantNames};
use syn::{parse_quote, spanned::Spanned, Attribute, Item, Type};

Expand Down Expand Up @@ -106,8 +106,7 @@ impl MayFromAttributes for QueuingInProc {
}
}

#[derive(Debug, Clone, Display, EnumDiscriminants)]
#[strum_discriminants(derive(EnumIter))]
#[derive(Debug, Clone, Display)]
pub enum Channel {
SamplingOut(Ident, SamplingOutProc),
SamplingIn(Ident, SamplingInProc),
Expand Down
100 changes: 46 additions & 54 deletions macros/src/parse/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,8 @@ use crate::parse::util::{no_return_type, remove_attributes, single_function_argu

#[derive(Debug, Copy, Clone, AsRefStr)]
enum StartType {
Warm(Span),
Cold(Span),
}

impl StartType {
fn span(&self) -> &Span {
match self {
StartType::Warm(s) => s,
StartType::Cold(s) => s,
}
}
Warm,
Cold,
}

#[derive(Debug, Clone, FromAttributes)]
Expand All @@ -29,32 +20,16 @@ struct StartFlags {
cold: Flag,
}

impl TryFrom<StartFlags> for Option<StartType> {
type Error = syn::Error;

fn try_from(value: StartFlags) -> Result<Self, Self::Error> {
impl From<StartFlags> for Vec<StartType> {
fn from(value: StartFlags) -> Self {
let mut flags = vec![];
if value.warm.is_present() {
flags.push(StartType::Warm(value.warm.span()))
flags.push(StartType::Warm)
}
if value.cold.is_present() {
flags.push(StartType::Cold(value.cold.span()))
}
match flags.len() {
0 => Ok(None),
1 => Ok(Some(flags[0])),
_ => {
let mut flags = flags.iter();
let mut err = syn::Error::new(
*flags.next().unwrap().span(),
"Multiple start flags attached to same function.",
);
for (i, flag) in flags.enumerate() {
err.combine(syn::Error::new(*flag.span(), format!("{}th flag", i + 2)))
}
Err(err)
}
flags.push(StartType::Cold)
}
flags
}
}

Expand Down Expand Up @@ -97,28 +72,23 @@ impl Start {
_ => None,
}) {
let start = StartFlags::from_attributes(&item.attrs)?;
let start: Option<StartType> = start.try_into()?;
let start = if let Some(start) = start {
start
} else {
continue;
};

// Remove start attributes from item //
remove_attributes("start", &mut item.attrs)?;
// Remove start attributes from item //

let leftover = match start {
StartType::Warm(_) => warm.replace(item.clone()),
StartType::Cold(_) => cold.replace(item.clone()),
};
if let Some(leftover) = leftover {
let mut err = syn::Error::new(
item.span(),
format!("{}Start already defined", start.as_ref()),
);
err.combine(syn::Error::new(leftover.span(), "First definition here"));
return Err(err);
let starts: Vec<StartType> = start.into();
for start in starts {
// Remove start attributes from item
remove_attributes("start", &mut item.attrs)?;

let leftover = match start {
StartType::Warm => warm.replace(item.clone()),
StartType::Cold => cold.replace(item.clone()),
};
if let Some(leftover) = leftover {
let mut err = syn::Error::new(
item.span(),
format!("{}Start already defined", start.as_ref()),
);
err.combine(syn::Error::new(leftover.span(), "First definition here"));
return Err(err);
}
}
}
Start {
Expand All @@ -130,3 +100,25 @@ impl Start {
.verify_fn_form()
}
}

#[cfg(test)]
mod tests {
use syn::parse_quote;

use crate::parse::start::*;

#[test]
fn test_start_flags_from_attributes_both_present() {
use darling::FromAttributes;

// Mock attributes
let warm_attr = parse_quote!(#[start(warm)]);
let cold_attr = parse_quote!(#[start(cold)]);

// Test case: Both warm and cold attributes are present
let flags: StartFlags = StartFlags::from_attributes(&[warm_attr, cold_attr])
.expect("Failed to parse StartFlags");
assert!(flags.warm.is_present());
assert!(flags.cold.is_present());
}
}
59 changes: 55 additions & 4 deletions macros/src/parse/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use syn::{parse_quote, Attribute, FnArg, Ident, ReturnType, Signature};
pub fn contains_attribute(attr: &str, attrs: &[Attribute]) -> bool {
attrs
.iter()
.flat_map(|a| a.parse_meta())
.map(|a| a.meta.clone())
.flat_map(|m| m.path().get_ident().cloned())
.any(|i| i.to_string().eq(attr))
}
Expand Down Expand Up @@ -46,18 +46,18 @@ pub fn single_function_argument(ty: &syn::Type, sig: &Signature) -> syn::Result<
return Err(syn::Error::new_spanned(t.ty.clone(), msg));
}
} else {
return Err(syn::Error::new(sig.paren_token.span, msg));
return Err(syn::Error::new(sig.paren_token.span.join(), msg));
}
if sig.inputs.len() > 1 {
return Err(syn::Error::new(sig.paren_token.span, msg));
return Err(syn::Error::new(sig.paren_token.span.join(), msg));
}
Ok(())
}

pub fn remove_attributes(attr: &str, attrs: &mut Vec<Attribute>) -> syn::Result<()> {
let attr = syn::parse_str::<Ident>(attr)?;
attrs.retain(|a| {
a.path
a.path()
.segments
.first()
.map_or_else(|| true, |p| !p.ident.eq(&attr))
Expand Down Expand Up @@ -106,3 +106,54 @@ impl FromMeta for WrappedDuration {
}
}
}

#[cfg(test)]
mod tests {
use crate::parse::util::*;

#[test]
fn test_contains_attribute() {
use syn::{parse_quote, Attribute};

let attr1: Attribute = parse_quote!(#[sample_attr]);
let attr2: Attribute = parse_quote!(#[another_attr]);

let attrs = vec![attr1, attr2];

assert!(contains_attribute("sample_attr", &attrs));
assert!(contains_attribute("another_attr", &attrs));
assert!(!contains_attribute("non_existent_attr", &attrs));
}

#[test]
fn test_no_return_type() {
use syn::{parse_quote, ReturnType};

let valid_return: ReturnType = parse_quote!(-> ());

// Function with valid return type
assert!(no_return_type("TestFn", &valid_return).is_ok());

// Function with invalid return type (usize)
let invalid_return: ReturnType = parse_quote!(-> usize);
assert!(no_return_type("TestFn", &invalid_return).is_err());
}

#[test]
fn test_remove_attributes() {
use syn::{parse_quote, Attribute};

let attr1: Attribute = parse_quote!(#[sample_attr]);
let attr2: Attribute = parse_quote!(#[another_attr]);

let mut attrs = vec![attr1, attr2.clone()];

// Removing an attribute that exists
remove_attributes("sample_attr", &mut attrs).unwrap();
assert_eq!(attrs, vec![attr2.clone()]);

// Removing an attribute that does not exist
remove_attributes("non_existent_attr", &mut attrs).unwrap();
assert_eq!(attrs, vec![attr2]);
}
}
2 changes: 1 addition & 1 deletion src/apex/blackboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub mod abstraction {
use core::sync::atomic::AtomicPtr;

// Reexport important basic-types for downstream-user
pub use super::basic::{ApexBlackboardP1, BlackboardId, BlackboardStatus};
pub use super::basic::{BlackboardId, BlackboardStatus};
use crate::bindings::*;
use crate::hidden::Key;
use crate::prelude::*;
Expand Down
2 changes: 1 addition & 1 deletion src/apex/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub mod abstraction {
use core::sync::atomic::AtomicPtr;

// Reexport important basic-types for downstream-user
pub use super::basic::{ApexBufferP1, BufferId, BufferStatus};
pub use super::basic::{BufferId, BufferStatus};
use crate::bindings::*;
use crate::hidden::Key;
use crate::prelude::*;
Expand Down
3 changes: 1 addition & 2 deletions src/apex/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ pub mod basic {
pub mod abstraction {
// Reexport important basic-types for downstream-user
pub use super::basic::{
ApexErrorP1, ApexErrorP4, ErrorCode, ErrorHandlerConcurrencyControl, ErrorStatus,
MAX_ERROR_MESSAGE_SIZE,
ErrorCode, ErrorHandlerConcurrencyControl, ErrorStatus, MAX_ERROR_MESSAGE_SIZE,
};
use crate::bindings::*;
use crate::hidden::Key;
Expand Down
3 changes: 2 additions & 1 deletion src/apex/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ pub mod abstraction {
use core::sync::atomic::AtomicPtr;

// Reexport important basic-types for downstream-user
pub use super::basic::{ApexEventP1, EventId, EventState, EventStatus};
pub use super::basic::{EventId, EventState, EventStatus};
use crate::bindings::*;
use crate::hidden::Key;
use crate::prelude::*;

Expand Down
4 changes: 2 additions & 2 deletions src/apex/memory_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ pub mod abstraction {
use core::marker::PhantomData;
use core::slice::from_raw_parts_mut;

use super::basic::ApexMemoryBlockStatus;
// Reexport important basic-types for downstream-user
pub use super::basic::{ApexMemoryBlockP2, MemoryBlockMode, MemoryBlockName, MemoryBlockSize};
pub use super::basic::{MemoryBlockMode, MemoryBlockName, MemoryBlockSize};
use crate::bindings::*;
use crate::hidden::Key;
use crate::prelude::*;

Expand Down
2 changes: 1 addition & 1 deletion src/apex/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub mod abstraction {
use core::sync::atomic::AtomicPtr;

// Reexport important basic-types for downstream-user
pub use super::basic::{ApexMutexP1, LockCount, MutexId, MutexName, MutexStatus};
pub use super::basic::{LockCount, MutexId, MutexName, MutexStatus};
use crate::bindings::*;
use crate::hidden::Key;
use crate::prelude::*;
Expand Down
20 changes: 16 additions & 4 deletions src/apex/partition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub mod abstraction {
use core::sync::atomic::AtomicPtr;

// Reexport important basic-types for downstream-user
pub use super::basic::{ApexPartitionP4, NumCores, OperatingMode, PartitionId, StartCondition};
pub use super::basic::{NumCores, OperatingMode, PartitionId, StartCondition};
use crate::bindings::*;
use crate::hidden::Key;
use crate::prelude::*;
Expand Down Expand Up @@ -132,7 +132,15 @@ pub mod abstraction {
where
A: ApexPartitionP4,
{
fn get_partition_status() -> PartitionStatus;
fn get_status() -> PartitionStatus;

/// change partition mode
/// DO NOT CALL THIS WITH [OperatingMode::Normal] FROM THE START FUNCTION.
///
/// # Errors
/// - [Error::NoAction]: `mode` is [OperatingMode::Normal] and partition mode is [OperatingMode::Normal]
/// - [Error::InvalidMode]: `mode` is [OperatingMode::WarmStart] and partition mode is [OperatingMode::ColdStart]
fn set_mode(mode: OperatingMode) -> Result<(), Error>;

fn run(self) -> !;
}
Expand All @@ -142,15 +150,19 @@ pub mod abstraction {
P: Partition<A>,
A: ApexPartitionP4,
{
fn get_partition_status() -> PartitionStatus {
fn get_status() -> PartitionStatus {
A::get_partition_status::<Key>().into()
}

fn set_mode(mode: OperatingMode) -> Result<(), Error> {
Ok(A::set_partition_mode::<Key>(mode)?)
}

fn run(self) -> ! {
let mut ctx = StartContext {
_a: Default::default(),
};
let status = Self::get_partition_status();
let status = Self::get_status();

match status.operating_mode {
OperatingMode::ColdStart => self.cold_start(&mut ctx),
Expand Down
3 changes: 1 addition & 2 deletions src/apex/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ pub mod abstraction {

// Reexport important basic-types for downstream-user
pub use super::basic::{
ApexProcessP1, ApexProcessP4, Deadline, LockLevel, Priority, ProcessId, ProcessIndex,
ProcessName, StackSize,
Deadline, LockLevel, Priority, ProcessId, ProcessIndex, ProcessName, StackSize,
};
use crate::bindings::*;
use crate::hidden::Key;
Expand Down
Loading

0 comments on commit 0aa3a19

Please sign in to comment.