Skip to content

Commit

Permalink
refactor(core-macro): change macros to private
Browse files Browse the repository at this point in the history
  • Loading branch information
SARDONYX-sard committed Jan 18, 2024
1 parent ecec408 commit 7935810
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 47 deletions.
2 changes: 1 addition & 1 deletion dar2oar_core/src/condition_parser/actor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::dar_interface::ParseError;
use super::macros::get_try_into;
use crate::{
conditions::{CompareValues, ConditionSet, IsActorBase},
dar_syntax::syntax::FnArg,
get_try_into,
values::{ActorValue, ActorValueType, Cmp, NumericValue},
};

Expand Down
2 changes: 1 addition & 1 deletion dar2oar_core/src/condition_parser/compare.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::dar_interface::ParseError;
use super::macros::get_try_into;
use crate::{
conditions::{CompareValues, ConditionSet},
dar_syntax::syntax::FnArg,
get_try_into,
values::{Cmp, NumericValue, PluginValue},
};

Expand Down
6 changes: 3 additions & 3 deletions dar2oar_core/src/condition_parser/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use super::dar_interface::ParseError;
use super::equip::parse_equip;
use super::faction::parse_faction;
use super::has::parse_has;
use super::macros::{gen_cond, get_try_into, GetArg as _};
use crate::conditions::{
And, Condition, ConditionSet, CurrentGameTime, CurrentWeather, IsClass, IsCombatStyle,
IsInLocation, IsMovementDirection, IsParentCell, IsRace, IsVoiceType, IsWorldSpace, IsWorn,
IsWornHasKeyword, Level, Or, RandomCondition,
};
use crate::dar_syntax::syntax::{self, Expression};
use crate::values::{Cmp, DirectionValue, NumericValue};
use crate::{gen_cond, get_into, get_try_into};

pub fn parse_conditions(input: syntax::Condition) -> Result<ConditionSet, ParseError> {
Ok(match input {
Expand Down Expand Up @@ -56,7 +56,7 @@ fn parse_condition(condition: Expression<'_>) -> Result<ConditionSet, ParseError
"IsLevelLessThan" => ConditionSet::Level(Level {
negated,
comparison: Cmp::Lt,
numeric_value: get_into!(args[0], "NumericValue"),
numeric_value: args.try_get(0, "NumericValue")?.into(),
..Default::default()
}),
"CurrentWeather" => gen_cond!(
Expand Down Expand Up @@ -109,7 +109,7 @@ fn parse_condition(condition: Expression<'_>) -> Result<ConditionSet, ParseError
"Random" => ConditionSet::RandomCondition(RandomCondition {
negated,
comparison: Cmp::Le,
numeric_value: get_into!(args[0], "NumericValue in Random"),
numeric_value: args.try_get(0, "NumericValue in Random")?.into(),
..Default::default()
}),
"CurrentGameTimeLessThan" => ConditionSet::CurrentGameTime(CurrentGameTime {
Expand Down
6 changes: 3 additions & 3 deletions dar2oar_core/src/condition_parser/equip.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::dar_interface::ParseError;
use super::macros::get_try_into;
use super::{dar_interface::ParseError, macros::GetArg as _};
use crate::{
conditions::{ConditionSet, IsEquipped, IsEquippedHasKeyword, IsEquippedType},
dar_syntax::syntax::FnArg,
get_into, get_try_into,
values::{NumericLiteral, TypeValue},
};

Expand Down Expand Up @@ -36,7 +36,7 @@ pub(super) fn parse_equip(
ConditionSet::IsEquippedHasKeyword(IsEquippedHasKeyword {
negated,
left_hand: condition_name == "IsEquippedLeftHasKeyword",
keyword: get_into!(args[0], "Keyword"),
keyword: args.try_get(0, "Keyword")?.into(),
..Default::default()
})
}
Expand Down
4 changes: 2 additions & 2 deletions dar2oar_core/src/condition_parser/faction.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::dar_interface::ParseError;
use super::macros::{get_try_into, GetArg as _};
use crate::{
conditions::{ConditionSet, FactionRank, IsInFaction},
dar_syntax::syntax::FnArg,
get_into, get_try_into,
values::Cmp,
};

Expand All @@ -16,7 +16,7 @@ pub(super) fn parse_faction(
negated,
faction: get_try_into!(args[0], "PluginValue")?,
comparison,
numeric_value: get_into!(args[1], "NumericValue"),
numeric_value: args.try_get(1, "NumericValue")?.into(),
..Default::default()
}))
};
Expand Down
5 changes: 3 additions & 2 deletions dar2oar_core/src/condition_parser/has.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::dar_interface::ParseError;
use super::macros::{gen_cond, get_try_into, GetArg as _};
use crate::conditions::{
ConditionSet, HasKeyword, HasMagicEffect, HasMagicEffectWithKeyword, HasPerk, HasRefType,
HasSpell,
};
use crate::{dar_syntax::syntax::FnArg, gen_cond, get_into, get_try_into};
use crate::dar_syntax::syntax::FnArg;

pub(super) fn parse_has(
condition_name: &str,
Expand All @@ -12,7 +13,7 @@ pub(super) fn parse_has(
) -> Result<ConditionSet, ParseError> {
Ok(match condition_name {
"HasKeyword" => ConditionSet::HasKeyword(HasKeyword {
keyword: get_into!(args[0], "keyword in HasKeyword"),
keyword: args.try_get(0, "keyword in HasKeyword")?.into(),
negated,
..Default::default()
}),
Expand Down
102 changes: 67 additions & 35 deletions dar2oar_core/src/condition_parser/macros.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,91 @@
#[macro_export]
macro_rules! get_arg {
($args:ident[$index:literal], $expected:literal) => {
$args.get($index).ok_or(ParseError::UnexpectedValue(
$expected.to_string(),
format!("None in args[{}]", $index),
))
};
($args:ident[$index:literal], $expected:literal, $actual:literal) => {
$args.get($index).ok_or(ParseError::UnexpectedValue(
$expected.to_string(),
$actual.to_string(),
))
};
}
use super::ParseError;
use crate::dar_syntax::syntax::FnArg;

/// get arg & into
/// A trait for safely accessing elements in a vector without causing runtime panics.
///
/// Return early if \[$index\]th of args cannot be obtained. After that, do into.
#[macro_export]
macro_rules! get_into {
($args:ident[$index:literal], $expected:literal) => {
$crate::get_arg!($args[$index], $expected)?.into()
};
($args:ident[$index:literal], $expected:literal, $actual:literal) => {
$crate::get_arg!($args[$index], $expected, $actual)?.into()
};
/// This trait provides methods to access the index of a vector, returning a result
/// with either the desired element or an error if the index is out of bounds.
pub(super) trait GetArg {
/// The type of the output, which is a result containing a reference to the desired element
/// or a error if the index is out of bounds.
///
/// Use [Generic Associated Types(GATs)](https://blog.rust-lang.org/2022/10/28/gats-stabilization.html#what-are-gats)
/// for the `&T` in [`Vec<T>`] because it has the same lifeTime as [Vec].
type Output<'a>
where
Self: 'a;

/// Access the element at the specified index of the vector.
///
/// # Returns
///
/// A result containing a reference to the desired element or a `Error` if the index is out of bounds.
fn try_get(&self, index: usize, expected: impl ToString) -> Self::Output<'_>;

/// Access the element at the specified index of the vector with additional information in case of an error.
///
/// # Returns
///
/// A result containing a reference to the desired element or a `Error` with detailed information if the index is out of bounds.
fn try_get_real<T>(&self, index: usize, expected: T, actual: T) -> Self::Output<'_>
where
T: ToString;
}

impl GetArg for Vec<FnArg<'_>> {
type Output<'a> = Result<&'a FnArg<'a>, ParseError> where Self: 'a;

fn try_get(&self, index: usize, expected: impl ToString) -> Self::Output<'_> {
self.get(index).ok_or(ParseError::UnexpectedValue(
expected.to_string(),
format!("None in args[{}]", index),
))
}

fn try_get_real<T>(&self, index: usize, expected: T, actual: T) -> Self::Output<'_>
where
T: ToString,
{
self.get(index).ok_or(ParseError::UnexpectedValue(
expected.to_string(),
actual.to_string(),
))
}
}

/// get arg & try_into
#[macro_export]
/// Access [Vec::get](https://doc.rust-lang.org/stable/alloc/vec/struct.Vec.html#method.get)(index) & try_into()
macro_rules! get_try_into {
($args:ident[$index:literal], $expected:literal) => {
$crate::get_arg!($args[$index], $expected)?.try_into()
<Vec<crate::dar_syntax::syntax::FnArg<'_>> as $crate::condition_parser::macros::GetArg>::try_get(
&$args, $index, $expected,
)?
.try_into()
};
($args:ident[$index:literal], $expected:literal, $actual:literal) => {
$crate::get_arg!($args[$index], $expected, $actual)?.try_into()
<Vec<crate::dar_syntax::syntax::FnArg<'_>> as $crate::condition_parser::macros::GetArg>::try_get_real(
&$args, $index, $expected, $actual
)?
.try_into()
};
}
pub(super) use get_try_into;

// Generate COnditionSet & get arg then try_into(exec `into()` if use into Option)
/// $id:ident, $field_name:ident, $args:ident $negated:expr, $expected:literal, into(This is Option use into)
#[macro_export]
/// Generate `ConditionSet` & [Vec]::get(index) & try_into() (can use `into` if you need)
macro_rules! gen_cond {
($id:ident($field_name:ident, $negated:ident), $args:ident, $expected:literal) => {
ConditionSet::$id($id {
negated: $negated,
$field_name: $crate::get_try_into!($args[0], $expected)?,
$field_name: $crate::condition_parser::macros::get_try_into!($args[0], $expected)?,
..Default::default()
})
};
($id:ident($field_name:ident, $negated:ident), $args:ident, $expected:literal, into) => {
ConditionSet::$id($id {
negated: $negated,
$field_name: $crate::get_into!($args[0], $expected),
negated: $negated,
$field_name:
<Vec<crate::dar_syntax::syntax::FnArg<'_>> as $crate::condition_parser::macros::GetArg>::try_get(&$args,0, $expected)?.into(),
..Default::default()
})
};
}
pub(super) use gen_cond;

0 comments on commit 7935810

Please sign in to comment.