Skip to content

Commit

Permalink
Small move of modules and added first few MIR passes
Browse files Browse the repository at this point in the history
  • Loading branch information
diondokter committed Aug 21, 2024
1 parent 0cb8ee8 commit 4c2a041
Show file tree
Hide file tree
Showing 9 changed files with 545 additions and 136 deletions.
1 change: 1 addition & 0 deletions generation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ description = "Code generation for the `device-driver` crate"
readme.workspace = true

[dependencies]
anyhow = "1.0.86"
convert_case = "0.6.0"
indexmap = { version = "2.1.0", features = ["serde"] }
prettyplease = "0.2.15"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,6 @@ impl TryFrom<syn::Ident> for mir::Integer {
}
}

impl From<dsl_hir::NameCase> for mir::NameCase {
fn from(value: dsl_hir::NameCase) -> Self {
match value {
dsl_hir::NameCase::Varying => mir::NameCase::Varying,
dsl_hir::NameCase::Pascal => mir::NameCase::Pascal,
dsl_hir::NameCase::Snake => mir::NameCase::Snake,
dsl_hir::NameCase::ScreamingSnake => mir::NameCase::ScreamingSnake,
dsl_hir::NameCase::Camel => mir::NameCase::Camel,
dsl_hir::NameCase::Kebab => mir::NameCase::Kebab,
dsl_hir::NameCase::Cobol => mir::NameCase::Cobol,
}
}
}

impl TryFrom<dsl_hir::Repeat> for mir::Repeat {
type Error = syn::Error;

Expand Down Expand Up @@ -145,7 +131,7 @@ impl TryFrom<dsl_hir::GlobalConfigList> for mir::GlobalConfig {
dsl_hir::GlobalConfig::BufferAddressType(value) => {
global_config.buffer_address_type = Some(value.try_into()?)
}
dsl_hir::GlobalConfig::NameCase(value) => global_config.name_case = value.into(),
dsl_hir::GlobalConfig::NameWordBoundaries(value) => global_config.name_word_boundaries = value,
}
}

Expand Down Expand Up @@ -856,6 +842,8 @@ fn transform_command_override(

#[cfg(test)]
mod tests {
use convert_case::Boundary;

use super::*;

#[test]
Expand Down Expand Up @@ -883,7 +871,7 @@ mod tests {
type RegisterAddressType = i8;
type CommandAddressType = u128;
type BufferAddressType = u32;
type NameCase = Pascal;
type NameWordBoundaries = \"-\";
}",
)
.unwrap();
Expand All @@ -901,7 +889,7 @@ mod tests {
register_address_type: Some(mir::Integer::I8),
command_address_type: Some(mir::Integer::U128),
buffer_address_type: Some(mir::Integer::U32),
name_case: mir::NameCase::Pascal,
name_word_boundaries: vec![Boundary::Hyphen],
}
);
}
Expand Down
165 changes: 67 additions & 98 deletions generation/src/dsl_hir.rs → generation/src/dsl_hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
//! > | (`type` `RegisterAddressType` `=` _IntegerType_`;`)
//! > | (`type` `CommandAddressType` `=` _IntegerType_`;`)
//! > | (`type` `BufferAddressType` `=` _IntegerType_`;`)
//! > | (`type` `NameCase` `=` _NameCase_`;`)
//! > | (`type` `NameWordBoundaries` `=` _NameWordBoundaries_`;`)
//!
//! _NameCase_:
//! _NameWordBoundaries_:
//! This specifies the input, not the output. Only applies to object and field names.
//! > `Varying`|`Pascal`|`Snake`|`ScreamingSnake`|`Camel`|`Kebab`|`Cobol`
//! > [_Boundary_*]
//! > | _String_
//!
//! _ObjectList_:
//! > (_Object_(`,` _Object_)*`,`?)?
Expand Down Expand Up @@ -150,15 +151,18 @@

use std::mem::Discriminant;

use convert_case::Boundary;
use proc_macro2::Span;
use syn::{
braced, bracketed,
parse::{Parse, ParseStream},
punctuated::Punctuated,
spanned::Spanned,
LitInt, Token,
Ident, LitInt, LitStr, Token,
};

pub mod mir_transform;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Device {
pub global_config_list: GlobalConfigList,
Expand Down Expand Up @@ -211,7 +215,7 @@ pub enum GlobalConfig {
RegisterAddressType(syn::Ident),
CommandAddressType(syn::Ident),
BufferAddressType(syn::Ident),
NameCase(NameCase),
NameWordBoundaries(Vec<Boundary>),
}

impl Parse for GlobalConfig {
Expand Down Expand Up @@ -268,54 +272,42 @@ impl Parse for GlobalConfig {
let value = input.parse()?;
input.parse::<Token![;]>()?;
Ok(Self::BufferAddressType(value))
} else if lookahead.peek(kw::NameCase) {
input.parse::<kw::NameCase>()?;
} else if lookahead.peek(kw::NameWordBoundaries) {
input.parse::<kw::NameWordBoundaries>()?;
input.parse::<Token![=]>()?;
let value = input.parse()?;
input.parse::<Token![;]>()?;
Ok(Self::NameCase(value))
} else {
Err(lookahead.error())
}
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum NameCase {
Varying,
Pascal,
Snake,
ScreamingSnake,
Camel,
Kebab,
Cobol,
}
let value = if input.peek(syn::token::Bracket) {
let bracket_input;
bracketed!(bracket_input in input);

let boundaries = Punctuated::<Ident, Token![,]>::parse_terminated(&bracket_input)?;
boundaries
.into_iter()
.map(|ident| {
for b in Boundary::all() {
if format!("{b:?}").to_lowercase() == ident.to_string().to_lowercase() {
return Ok(b);
}
}

impl Parse for NameCase {
fn parse(input: ParseStream) -> syn::Result<Self> {
let lookahead = input.lookahead1();
Err(syn::Error::new(ident.span(), &format!("`{}` is not a valid boundary name. One of the following was expected: {:?}", ident, Boundary::all())))
}).collect::<Result<Vec<_>, _>>()?
} else {
let string_value = match input.parse::<LitStr>() {
Ok(lit) => lit.value(),
Err(e) => {
return Err(syn::Error::new(
e.span(),
"Expected an array of boundaries or a string",
));
}
};

Boundary::list_from(&string_value)
};

if lookahead.peek(kw::Varying) {
input.parse::<kw::Varying>()?;
Ok(Self::Varying)
} else if lookahead.peek(kw::Pascal) {
input.parse::<kw::Pascal>()?;
Ok(Self::Pascal)
} else if lookahead.peek(kw::Snake) {
input.parse::<kw::Snake>()?;
Ok(Self::Snake)
} else if lookahead.peek(kw::ScreamingSnake) {
input.parse::<kw::ScreamingSnake>()?;
Ok(Self::ScreamingSnake)
} else if lookahead.peek(kw::Camel) {
input.parse::<kw::Camel>()?;
Ok(Self::Camel)
} else if lookahead.peek(kw::Kebab) {
input.parse::<kw::Kebab>()?;
Ok(Self::Kebab)
} else if lookahead.peek(kw::Cobol) {
input.parse::<kw::Cobol>()?;
Ok(Self::Cobol)
input.parse::<Token![;]>()?;
Ok(Self::NameWordBoundaries(value))
} else {
Err(lookahead.error())
}
Expand Down Expand Up @@ -1394,16 +1386,7 @@ mod kw {
syn::custom_keyword!(RegisterAddressType);
syn::custom_keyword!(CommandAddressType);
syn::custom_keyword!(BufferAddressType);
syn::custom_keyword!(NameCase);

// NameCase options
syn::custom_keyword!(Varying);
syn::custom_keyword!(Pascal);
syn::custom_keyword!(Snake);
syn::custom_keyword!(ScreamingSnake);
syn::custom_keyword!(Camel);
syn::custom_keyword!(Kebab);
syn::custom_keyword!(Cobol);
syn::custom_keyword!(NameWordBoundaries);

// Access
syn::custom_keyword!(Access);
Expand Down Expand Up @@ -2200,42 +2183,6 @@ mod tests {
);
}

#[test]
fn parse_name_case() {
assert_eq!(
syn::parse_str::<NameCase>("Varying").unwrap(),
NameCase::Varying
);
assert_eq!(
syn::parse_str::<NameCase>("Pascal").unwrap(),
NameCase::Pascal
);
assert_eq!(
syn::parse_str::<NameCase>("Snake").unwrap(),
NameCase::Snake
);
assert_eq!(
syn::parse_str::<NameCase>("ScreamingSnake").unwrap(),
NameCase::ScreamingSnake
);
assert_eq!(
syn::parse_str::<NameCase>("Camel").unwrap(),
NameCase::Camel
);
assert_eq!(
syn::parse_str::<NameCase>("Kebab").unwrap(),
NameCase::Kebab
);
assert_eq!(
syn::parse_str::<NameCase>("Cobol").unwrap(),
NameCase::Cobol
);
assert_eq!(
syn::parse_str::<NameCase>("bla").unwrap_err().to_string(),
"expected one of: `Varying`, `Pascal`, `Snake`, `ScreamingSnake`, `Camel`, `Kebab`, `Cobol`"
);
}

#[test]
fn parse_global_config_list() {
assert_eq!(
Expand Down Expand Up @@ -2278,18 +2225,40 @@ mod tests {

assert_eq!(
syn::parse_str::<GlobalConfigList>(
"config { type DefaultByteOrder = LE; type DefaultBitOrder = LSB0; type NameCase = Camel; }"
"config { type DefaultByteOrder = LE; type DefaultBitOrder = LSB0; type NameWordBoundaries = \"aA:1B\"; }"
)
.unwrap(),
GlobalConfigList {
configs: vec![
GlobalConfig::DefaultByteOrder(ByteOrder::LE),
GlobalConfig::DefaultBitOrder(BitOrder::LSB0),
GlobalConfig::NameCase(NameCase::Camel)
GlobalConfig::NameWordBoundaries(vec![Boundary::LowerUpper, Boundary::DigitUpper])
]
}
);

assert_eq!(
syn::parse_str::<GlobalConfigList>("config { type NameWordBoundaries = [DigitLower, Hyphen]; }")
.unwrap(),
GlobalConfigList {
configs: vec![
GlobalConfig::NameWordBoundaries(vec![Boundary::DigitLower, Boundary::Hyphen])
]
}
);

assert_eq!(
syn::parse_str::<GlobalConfigList>("config { type NameWordBoundaries = 5; }")
.unwrap_err().to_string(),
"Expected an array of boundaries or a string"
);

assert_eq!(
syn::parse_str::<GlobalConfigList>("config { type NameWordBoundaries = [lol]; }")
.unwrap_err().to_string(),
"`lol` is not a valid boundary name. One of the following was expected: [Hyphen, Underscore, Space, LowerUpper, UpperLower, DigitUpper, UpperDigit, DigitLower, LowerDigit, Acronym]"
);

assert_eq!(
syn::parse_str::<GlobalConfigList>(
"config { type RegisterAddressType = u8; type CommandAddressType = u16; type BufferAddressType = u32; }"
Expand All @@ -2308,7 +2277,7 @@ mod tests {
syn::parse_str::<GlobalConfigList>("config { type DefaultRegisterAccesssss = RW; }")
.unwrap_err()
.to_string(),
"expected one of: `DefaultRegisterAccess`, `DefaultFieldAccess`, `DefaultBufferAccess`, `DefaultByteOrder`, `DefaultBitOrder`, `RegisterAddressType`, `CommandAddressType`, `BufferAddressType`, `NameCase`"
"expected one of: `DefaultRegisterAccess`, `DefaultFieldAccess`, `DefaultBufferAccess`, `DefaultByteOrder`, `DefaultBitOrder`, `RegisterAddressType`, `CommandAddressType`, `BufferAddressType`, `NameWordBoundaries`"
);
}

Expand Down
1 change: 0 additions & 1 deletion generation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub mod deserialization;
mod generation;

pub mod dsl_hir;
pub mod dsl_hir_mir_transform;
pub mod mir;

#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize)]
Expand Down
Loading

0 comments on commit 4c2a041

Please sign in to comment.