1use std::fmt;
35
36use super::{Expression, Identifier, Variable};
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64#[repr(C)]
65pub enum ReductionOperator {
66 Add = 0, Multiply = 1, Subtract = 2, BitwiseAnd = 10, BitwiseOr = 11, BitwiseXor = 12, LogicalAnd = 20, LogicalOr = 21, Min = 30,
82 Max = 31,
83
84 MinusEqual = 40, Custom = 100,
89}
90
91impl fmt::Display for ReductionOperator {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 match self {
94 ReductionOperator::Add => write!(f, "+"),
95 ReductionOperator::Multiply => write!(f, "*"),
96 ReductionOperator::Subtract => write!(f, "-"),
97 ReductionOperator::BitwiseAnd => write!(f, "&"),
98 ReductionOperator::BitwiseOr => write!(f, "|"),
99 ReductionOperator::BitwiseXor => write!(f, "^"),
100 ReductionOperator::LogicalAnd => write!(f, "&&"),
101 ReductionOperator::LogicalOr => write!(f, "||"),
102 ReductionOperator::Min => write!(f, "min"),
103 ReductionOperator::Max => write!(f, "max"),
104 ReductionOperator::MinusEqual => write!(f, "-="),
105 ReductionOperator::Custom => write!(f, "custom"),
106 }
107 }
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
129#[repr(C)]
130pub enum MapType {
131 To = 0,
133 From = 1,
135 ToFrom = 2,
137 Alloc = 3,
139 Release = 4,
141 Delete = 5,
143}
144
145impl fmt::Display for MapType {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 match self {
148 MapType::To => write!(f, "to"),
149 MapType::From => write!(f, "from"),
150 MapType::ToFrom => write!(f, "tofrom"),
151 MapType::Alloc => write!(f, "alloc"),
152 MapType::Release => write!(f, "release"),
153 MapType::Delete => write!(f, "delete"),
154 }
155 }
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
177#[repr(C)]
178pub enum ScheduleKind {
179 Static = 0,
181 Dynamic = 1,
183 Guided = 2,
185 Auto = 3,
187 Runtime = 4,
189}
190
191impl fmt::Display for ScheduleKind {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 match self {
194 ScheduleKind::Static => write!(f, "static"),
195 ScheduleKind::Dynamic => write!(f, "dynamic"),
196 ScheduleKind::Guided => write!(f, "guided"),
197 ScheduleKind::Auto => write!(f, "auto"),
198 ScheduleKind::Runtime => write!(f, "runtime"),
199 }
200 }
201}
202
203#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
219#[repr(C)]
220pub enum ScheduleModifier {
221 Monotonic = 0,
223 Nonmonotonic = 1,
225 Simd = 2,
227}
228
229impl fmt::Display for ScheduleModifier {
230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231 match self {
232 ScheduleModifier::Monotonic => write!(f, "monotonic"),
233 ScheduleModifier::Nonmonotonic => write!(f, "nonmonotonic"),
234 ScheduleModifier::Simd => write!(f, "simd"),
235 }
236 }
237}
238
239#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
258#[repr(C)]
259pub enum DependType {
260 In = 0,
262 Out = 1,
264 Inout = 2,
266 Mutexinoutset = 3,
268 Depobj = 4,
270 Source = 5,
272 Sink = 6,
274}
275
276impl fmt::Display for DependType {
277 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278 match self {
279 DependType::In => write!(f, "in"),
280 DependType::Out => write!(f, "out"),
281 DependType::Inout => write!(f, "inout"),
282 DependType::Mutexinoutset => write!(f, "mutexinoutset"),
283 DependType::Depobj => write!(f, "depobj"),
284 DependType::Source => write!(f, "source"),
285 DependType::Sink => write!(f, "sink"),
286 }
287 }
288}
289
290#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
309#[repr(C)]
310pub enum DefaultKind {
311 Shared = 0,
313 None = 1,
315 Private = 2,
317 Firstprivate = 3,
319}
320
321impl fmt::Display for DefaultKind {
322 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323 match self {
324 DefaultKind::Shared => write!(f, "shared"),
325 DefaultKind::None => write!(f, "none"),
326 DefaultKind::Private => write!(f, "private"),
327 DefaultKind::Firstprivate => write!(f, "firstprivate"),
328 }
329 }
330}
331
332#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
348#[repr(C)]
349pub enum ProcBind {
350 Master = 0,
352 Close = 1,
354 Spread = 2,
356 Primary = 3,
358}
359
360impl fmt::Display for ProcBind {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 match self {
363 ProcBind::Master => write!(f, "master"),
364 ProcBind::Close => write!(f, "close"),
365 ProcBind::Spread => write!(f, "spread"),
366 ProcBind::Primary => write!(f, "primary"),
367 }
368 }
369}
370
371#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
387#[repr(C)]
388pub enum MemoryOrder {
389 SeqCst = 0,
391 AcqRel = 1,
393 Release = 2,
395 Acquire = 3,
397 Relaxed = 4,
399}
400
401impl fmt::Display for MemoryOrder {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 match self {
404 MemoryOrder::SeqCst => write!(f, "seq_cst"),
405 MemoryOrder::AcqRel => write!(f, "acq_rel"),
406 MemoryOrder::Release => write!(f, "release"),
407 MemoryOrder::Acquire => write!(f, "acquire"),
408 MemoryOrder::Relaxed => write!(f, "relaxed"),
409 }
410 }
411}
412
413#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
429#[repr(C)]
430pub enum AtomicOp {
431 Read = 0,
433 Write = 1,
435 Update = 2,
437 Capture = 3,
439}
440
441impl fmt::Display for AtomicOp {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 match self {
444 AtomicOp::Read => write!(f, "read"),
445 AtomicOp::Write => write!(f, "write"),
446 AtomicOp::Update => write!(f, "update"),
447 AtomicOp::Capture => write!(f, "capture"),
448 }
449 }
450}
451
452#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
471#[repr(C)]
472pub enum DeviceType {
473 Host = 0,
475 Nohost = 1,
477 Any = 2,
479}
480
481impl fmt::Display for DeviceType {
482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483 match self {
484 DeviceType::Host => write!(f, "host"),
485 DeviceType::Nohost => write!(f, "nohost"),
486 DeviceType::Any => write!(f, "any"),
487 }
488 }
489}
490
491#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
507#[repr(C)]
508pub enum LinearModifier {
509 Val = 0,
511 Ref = 1,
513 Uval = 2,
515}
516
517impl fmt::Display for LinearModifier {
518 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519 match self {
520 LinearModifier::Val => write!(f, "val"),
521 LinearModifier::Ref => write!(f, "ref"),
522 LinearModifier::Uval => write!(f, "uval"),
523 }
524 }
525}
526
527#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
543#[repr(C)]
544pub enum LastprivateModifier {
545 Conditional = 0,
547}
548
549impl fmt::Display for LastprivateModifier {
550 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551 match self {
552 LastprivateModifier::Conditional => write!(f, "conditional"),
553 }
554 }
555}
556
557#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
573#[repr(C)]
574pub enum OrderKind {
575 Concurrent = 0,
577}
578
579impl fmt::Display for OrderKind {
580 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581 match self {
582 OrderKind::Concurrent => write!(f, "concurrent"),
583 }
584 }
585}
586
587#[derive(Debug, Clone, PartialEq)]
633pub enum ClauseItem {
634 Identifier(Identifier),
636 Variable(Variable),
638 Expression(Expression),
640}
641
642impl fmt::Display for ClauseItem {
643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644 match self {
645 ClauseItem::Identifier(id) => write!(f, "{id}"),
646 ClauseItem::Variable(var) => write!(f, "{var}"),
647 ClauseItem::Expression(expr) => write!(f, "{expr}"),
648 }
649 }
650}
651
652impl From<Identifier> for ClauseItem {
653 fn from(id: Identifier) -> Self {
654 ClauseItem::Identifier(id)
655 }
656}
657
658impl From<Variable> for ClauseItem {
659 fn from(var: Variable) -> Self {
660 ClauseItem::Variable(var)
661 }
662}
663
664impl From<Expression> for ClauseItem {
665 fn from(expr: Expression) -> Self {
666 ClauseItem::Expression(expr)
667 }
668}
669
670#[derive(Debug, Clone, PartialEq)]
716pub enum ClauseData {
717 Bare(Identifier),
722
723 Expression(Expression),
728
729 ItemList(Vec<ClauseItem>),
734
735 Private { items: Vec<ClauseItem> },
740
741 Firstprivate { items: Vec<ClauseItem> },
743
744 Lastprivate {
746 modifier: Option<LastprivateModifier>,
747 items: Vec<ClauseItem>,
748 },
749
750 Shared { items: Vec<ClauseItem> },
752
753 Default(DefaultKind),
755
756 Reduction {
761 operator: ReductionOperator,
762 items: Vec<ClauseItem>,
763 },
764
765 Map {
770 map_type: Option<MapType>,
771 mapper: Option<Identifier>,
772 items: Vec<ClauseItem>,
773 },
774
775 UseDevicePtr { items: Vec<ClauseItem> },
777
778 UseDeviceAddr { items: Vec<ClauseItem> },
780
781 IsDevicePtr { items: Vec<ClauseItem> },
783
784 HasDeviceAddr { items: Vec<ClauseItem> },
786
787 Depend {
792 depend_type: DependType,
793 items: Vec<ClauseItem>,
794 },
795
796 Priority { priority: Expression },
798
799 Affinity { items: Vec<ClauseItem> },
801
802 Schedule {
807 kind: ScheduleKind,
808 modifiers: Vec<ScheduleModifier>,
809 chunk_size: Option<Expression>,
810 },
811
812 Collapse { n: Expression },
814
815 Ordered { n: Option<Expression> },
817
818 Linear {
823 modifier: Option<LinearModifier>,
824 items: Vec<ClauseItem>,
825 step: Option<Expression>,
826 },
827
828 Aligned {
830 items: Vec<ClauseItem>,
831 alignment: Option<Expression>,
832 },
833
834 Safelen { length: Expression },
836
837 Simdlen { length: Expression },
839
840 If {
845 directive_name: Option<Identifier>,
846 condition: Expression,
847 },
848
849 ProcBind(ProcBind),
854
855 NumThreads { num: Expression },
857
858 Device { device_num: Expression },
863
864 DeviceType(DeviceType),
866
867 AtomicDefaultMemOrder(MemoryOrder),
872
873 AtomicOperation {
875 op: AtomicOp,
876 memory_order: Option<MemoryOrder>,
877 },
878
879 Order(OrderKind),
884
885 NumTeams { num: Expression },
890
891 ThreadLimit { limit: Expression },
893
894 Allocate {
899 allocator: Option<Identifier>,
900 items: Vec<ClauseItem>,
901 },
902
903 Allocator { allocator: Identifier },
905
906 Copyin { items: Vec<ClauseItem> },
911
912 Copyprivate { items: Vec<ClauseItem> },
914
915 DistSchedule {
917 kind: ScheduleKind,
918 chunk_size: Option<Expression>,
919 },
920
921 Grainsize { grain: Expression },
923
924 NumTasks { num: Expression },
926
927 Filter { thread_num: Expression },
929
930 Generic {
932 name: Identifier,
933 data: Option<String>,
934 },
935}
936
937impl fmt::Display for ClauseData {
938 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
939 match self {
940 ClauseData::Bare(name) => write!(f, "{name}"),
941 ClauseData::Expression(expr) => write!(f, "{expr}"),
942 ClauseData::ItemList(items) => {
943 for (i, item) in items.iter().enumerate() {
944 if i > 0 {
945 write!(f, ", ")?;
946 }
947 write!(f, "{item}")?;
948 }
949 Ok(())
950 }
951 ClauseData::Private { items } => {
952 write!(f, "private(")?;
953 for (i, item) in items.iter().enumerate() {
954 if i > 0 {
955 write!(f, ", ")?;
956 }
957 write!(f, "{item}")?;
958 }
959 write!(f, ")")
960 }
961 ClauseData::Firstprivate { items } => {
962 write!(f, "firstprivate(")?;
963 for (i, item) in items.iter().enumerate() {
964 if i > 0 {
965 write!(f, ", ")?;
966 }
967 write!(f, "{item}")?;
968 }
969 write!(f, ")")
970 }
971 ClauseData::Lastprivate { modifier, items } => {
972 write!(f, "lastprivate(")?;
973 if let Some(m) = modifier {
974 write!(f, "{m}: ")?;
975 }
976 for (i, item) in items.iter().enumerate() {
977 if i > 0 {
978 write!(f, ", ")?;
979 }
980 write!(f, "{item}")?;
981 }
982 write!(f, ")")
983 }
984 ClauseData::Shared { items } => {
985 write!(f, "shared(")?;
986 for (i, item) in items.iter().enumerate() {
987 if i > 0 {
988 write!(f, ", ")?;
989 }
990 write!(f, "{item}")?;
991 }
992 write!(f, ")")
993 }
994 ClauseData::Default(kind) => write!(f, "default({kind})"),
995 ClauseData::Reduction { operator, items } => {
996 write!(f, "reduction({operator}: ")?;
997 for (i, item) in items.iter().enumerate() {
998 if i > 0 {
999 write!(f, ", ")?;
1000 }
1001 write!(f, "{item}")?;
1002 }
1003 write!(f, ")")
1004 }
1005 ClauseData::Map {
1006 map_type,
1007 mapper,
1008 items,
1009 } => {
1010 write!(f, "map(")?;
1011 if let Some(mapper_id) = mapper {
1012 write!(f, "mapper({mapper_id}), ")?;
1013 }
1014 if let Some(mt) = map_type {
1015 write!(f, "{mt}: ")?;
1016 }
1017 for (i, item) in items.iter().enumerate() {
1018 if i > 0 {
1019 write!(f, ", ")?;
1020 }
1021 write!(f, "{item}")?;
1022 }
1023 write!(f, ")")
1024 }
1025 ClauseData::Schedule {
1026 kind,
1027 modifiers,
1028 chunk_size,
1029 } => {
1030 write!(f, "schedule(")?;
1031 if !modifiers.is_empty() {
1032 for (i, m) in modifiers.iter().enumerate() {
1033 if i > 0 {
1034 write!(f, ", ")?;
1035 }
1036 write!(f, "{m}")?;
1037 }
1038 write!(f, ": ")?;
1039 }
1040 write!(f, "{kind}")?;
1041 if let Some(chunk) = chunk_size {
1042 write!(f, ", {chunk}")?;
1043 }
1044 write!(f, ")")
1045 }
1046 ClauseData::Linear {
1047 modifier,
1048 items,
1049 step,
1050 } => {
1051 write!(f, "linear(")?;
1052 if let Some(m) = modifier {
1053 write!(f, "{m}: ")?;
1054 }
1055 for (i, item) in items.iter().enumerate() {
1056 if i > 0 {
1057 write!(f, ", ")?;
1058 }
1059 write!(f, "{item}")?;
1060 }
1061 if let Some(s) = step {
1062 write!(f, ": {s}")?;
1063 }
1064 write!(f, ")")
1065 }
1066 ClauseData::If {
1067 directive_name,
1068 condition,
1069 } => {
1070 write!(f, "if(")?;
1071 if let Some(name) = directive_name {
1072 write!(f, "{name}: ")?;
1073 }
1074 write!(f, "{condition})")
1075 }
1076 ClauseData::NumThreads { num } => write!(f, "num_threads({num})"),
1077 ClauseData::ProcBind(pb) => write!(f, "proc_bind({pb})"),
1078 ClauseData::Device { device_num } => write!(f, "device({device_num})"),
1079 ClauseData::DeviceType(dt) => write!(f, "device_type({dt})"),
1080 ClauseData::Collapse { n } => write!(f, "collapse({n})"),
1081 ClauseData::Ordered { n } => {
1082 write!(f, "ordered")?;
1083 if let Some(num) = n {
1084 write!(f, "({num})")?;
1085 }
1086 Ok(())
1087 }
1088 ClauseData::Depend { depend_type, items } => {
1089 write!(f, "depend({depend_type}: ")?;
1090 for (i, item) in items.iter().enumerate() {
1091 if i > 0 {
1092 write!(f, ", ")?;
1093 }
1094 write!(f, "{item}")?;
1095 }
1096 write!(f, ")")
1097 }
1098 _ => write!(f, "<clause>"),
1100 }
1101 }
1102}
1103
1104impl ClauseData {
1105 pub fn is_default(&self) -> bool {
1107 matches!(self, ClauseData::Default(_))
1108 }
1109
1110 pub fn is_private(&self) -> bool {
1112 matches!(self, ClauseData::Private { .. })
1113 }
1114
1115 pub fn is_firstprivate(&self) -> bool {
1117 matches!(self, ClauseData::Firstprivate { .. })
1118 }
1119
1120 pub fn is_lastprivate(&self) -> bool {
1122 matches!(self, ClauseData::Lastprivate { .. })
1123 }
1124
1125 pub fn is_shared(&self) -> bool {
1127 matches!(self, ClauseData::Shared { .. })
1128 }
1129
1130 pub fn is_reduction(&self) -> bool {
1132 matches!(self, ClauseData::Reduction { .. })
1133 }
1134
1135 pub fn is_map(&self) -> bool {
1137 matches!(self, ClauseData::Map { .. })
1138 }
1139
1140 pub fn is_if(&self) -> bool {
1142 matches!(self, ClauseData::If { .. })
1143 }
1144
1145 pub fn is_num_threads(&self) -> bool {
1147 matches!(self, ClauseData::NumThreads { .. })
1148 }
1149
1150 pub fn is_collapse(&self) -> bool {
1152 matches!(self, ClauseData::Collapse { .. })
1153 }
1154
1155 pub fn is_ordered(&self) -> bool {
1157 matches!(self, ClauseData::Ordered { .. })
1158 }
1159
1160 pub fn is_schedule(&self) -> bool {
1162 matches!(self, ClauseData::Schedule { .. })
1163 }
1164
1165 pub fn is_device(&self) -> bool {
1167 matches!(self, ClauseData::Device { .. })
1168 }
1169
1170 pub fn is_depend(&self) -> bool {
1172 matches!(self, ClauseData::Depend { .. })
1173 }
1174
1175 pub fn is_linear(&self) -> bool {
1177 matches!(self, ClauseData::Linear { .. })
1178 }
1179
1180 pub fn is_proc_bind(&self) -> bool {
1182 matches!(self, ClauseData::ProcBind(_))
1183 }
1184}
1185
1186#[cfg(test)]
1187mod tests {
1188 use super::*;
1189
1190 #[test]
1192 fn test_reduction_operator_display() {
1193 assert_eq!(ReductionOperator::Add.to_string(), "+");
1194 assert_eq!(ReductionOperator::Multiply.to_string(), "*");
1195 assert_eq!(ReductionOperator::Subtract.to_string(), "-");
1196 assert_eq!(ReductionOperator::BitwiseAnd.to_string(), "&");
1197 assert_eq!(ReductionOperator::BitwiseOr.to_string(), "|");
1198 assert_eq!(ReductionOperator::BitwiseXor.to_string(), "^");
1199 assert_eq!(ReductionOperator::LogicalAnd.to_string(), "&&");
1200 assert_eq!(ReductionOperator::LogicalOr.to_string(), "||");
1201 assert_eq!(ReductionOperator::Min.to_string(), "min");
1202 assert_eq!(ReductionOperator::Max.to_string(), "max");
1203 assert_eq!(ReductionOperator::MinusEqual.to_string(), "-=");
1204 assert_eq!(ReductionOperator::Custom.to_string(), "custom");
1205 }
1206
1207 #[test]
1208 fn test_reduction_operator_equality() {
1209 assert_eq!(ReductionOperator::Add, ReductionOperator::Add);
1210 assert_ne!(ReductionOperator::Add, ReductionOperator::Multiply);
1211 }
1212
1213 #[test]
1214 fn test_reduction_operator_copy_clone() {
1215 let op1 = ReductionOperator::Max;
1216 let op2 = op1; let op3 = op1; assert_eq!(op1, op2);
1219 assert_eq!(op1, op3);
1220 }
1221
1222 #[test]
1223 fn test_reduction_operator_discriminants() {
1224 assert_eq!(ReductionOperator::Add as i32, 0);
1226 assert_eq!(ReductionOperator::Multiply as i32, 1);
1227 assert_eq!(ReductionOperator::BitwiseAnd as i32, 10);
1228 assert_eq!(ReductionOperator::LogicalAnd as i32, 20);
1229 assert_eq!(ReductionOperator::Min as i32, 30);
1230 assert_eq!(ReductionOperator::Custom as i32, 100);
1231 }
1232
1233 #[test]
1235 fn test_map_type_display() {
1236 assert_eq!(MapType::To.to_string(), "to");
1237 assert_eq!(MapType::From.to_string(), "from");
1238 assert_eq!(MapType::ToFrom.to_string(), "tofrom");
1239 assert_eq!(MapType::Alloc.to_string(), "alloc");
1240 assert_eq!(MapType::Release.to_string(), "release");
1241 assert_eq!(MapType::Delete.to_string(), "delete");
1242 }
1243
1244 #[test]
1245 fn test_map_type_all_variants() {
1246 let all_types = vec![
1248 MapType::To,
1249 MapType::From,
1250 MapType::ToFrom,
1251 MapType::Alloc,
1252 MapType::Release,
1253 MapType::Delete,
1254 ];
1255 for mt in all_types {
1256 assert!(!mt.to_string().is_empty());
1257 }
1258 }
1259
1260 #[test]
1262 fn test_schedule_kind_display() {
1263 assert_eq!(ScheduleKind::Static.to_string(), "static");
1264 assert_eq!(ScheduleKind::Dynamic.to_string(), "dynamic");
1265 assert_eq!(ScheduleKind::Guided.to_string(), "guided");
1266 assert_eq!(ScheduleKind::Auto.to_string(), "auto");
1267 assert_eq!(ScheduleKind::Runtime.to_string(), "runtime");
1268 }
1269
1270 #[test]
1271 fn test_schedule_kind_equality() {
1272 assert_eq!(ScheduleKind::Static, ScheduleKind::Static);
1273 assert_ne!(ScheduleKind::Static, ScheduleKind::Dynamic);
1274 }
1275
1276 #[test]
1278 fn test_schedule_modifier_display() {
1279 assert_eq!(ScheduleModifier::Monotonic.to_string(), "monotonic");
1280 assert_eq!(ScheduleModifier::Nonmonotonic.to_string(), "nonmonotonic");
1281 assert_eq!(ScheduleModifier::Simd.to_string(), "simd");
1282 }
1283
1284 #[test]
1285 fn test_schedule_modifier_all_variants() {
1286 let all_mods = vec![
1287 ScheduleModifier::Monotonic,
1288 ScheduleModifier::Nonmonotonic,
1289 ScheduleModifier::Simd,
1290 ];
1291 for sm in all_mods {
1292 assert!(!sm.to_string().is_empty());
1293 }
1294 }
1295
1296 #[test]
1298 fn test_depend_type_display() {
1299 assert_eq!(DependType::In.to_string(), "in");
1300 assert_eq!(DependType::Out.to_string(), "out");
1301 assert_eq!(DependType::Inout.to_string(), "inout");
1302 assert_eq!(DependType::Mutexinoutset.to_string(), "mutexinoutset");
1303 assert_eq!(DependType::Depobj.to_string(), "depobj");
1304 assert_eq!(DependType::Source.to_string(), "source");
1305 assert_eq!(DependType::Sink.to_string(), "sink");
1306 }
1307
1308 #[test]
1309 fn test_depend_type_all_variants() {
1310 let all_types = vec![
1311 DependType::In,
1312 DependType::Out,
1313 DependType::Inout,
1314 DependType::Mutexinoutset,
1315 DependType::Depobj,
1316 DependType::Source,
1317 DependType::Sink,
1318 ];
1319 for dt in all_types {
1320 assert!(!dt.to_string().is_empty());
1321 }
1322 }
1323
1324 #[test]
1326 fn test_default_kind_display() {
1327 assert_eq!(DefaultKind::Shared.to_string(), "shared");
1328 assert_eq!(DefaultKind::None.to_string(), "none");
1329 assert_eq!(DefaultKind::Private.to_string(), "private");
1330 assert_eq!(DefaultKind::Firstprivate.to_string(), "firstprivate");
1331 }
1332
1333 #[test]
1334 fn test_default_kind_language_specific() {
1335 let dk = DefaultKind::Private;
1337 assert_eq!(dk.to_string(), "private");
1338 }
1339
1340 #[test]
1342 fn test_proc_bind_display() {
1343 assert_eq!(ProcBind::Master.to_string(), "master");
1344 assert_eq!(ProcBind::Close.to_string(), "close");
1345 assert_eq!(ProcBind::Spread.to_string(), "spread");
1346 assert_eq!(ProcBind::Primary.to_string(), "primary");
1347 }
1348
1349 #[test]
1350 fn test_proc_bind_deprecated_master() {
1351 assert_eq!(ProcBind::Master.to_string(), "master");
1354 assert_eq!(ProcBind::Primary.to_string(), "primary");
1355 }
1356
1357 #[test]
1359 fn test_memory_order_display() {
1360 assert_eq!(MemoryOrder::SeqCst.to_string(), "seq_cst");
1361 assert_eq!(MemoryOrder::AcqRel.to_string(), "acq_rel");
1362 assert_eq!(MemoryOrder::Release.to_string(), "release");
1363 assert_eq!(MemoryOrder::Acquire.to_string(), "acquire");
1364 assert_eq!(MemoryOrder::Relaxed.to_string(), "relaxed");
1365 }
1366
1367 #[test]
1368 fn test_memory_order_strength() {
1369 let all_orders = [
1372 MemoryOrder::SeqCst,
1373 MemoryOrder::AcqRel,
1374 MemoryOrder::Release,
1375 MemoryOrder::Acquire,
1376 MemoryOrder::Relaxed,
1377 ];
1378 assert_eq!(all_orders.len(), 5);
1379 }
1380
1381 #[test]
1383 fn test_atomic_op_display() {
1384 assert_eq!(AtomicOp::Read.to_string(), "read");
1385 assert_eq!(AtomicOp::Write.to_string(), "write");
1386 assert_eq!(AtomicOp::Update.to_string(), "update");
1387 assert_eq!(AtomicOp::Capture.to_string(), "capture");
1388 }
1389
1390 #[test]
1391 fn test_atomic_op_all_variants() {
1392 let all_ops = vec![
1393 AtomicOp::Read,
1394 AtomicOp::Write,
1395 AtomicOp::Update,
1396 AtomicOp::Capture,
1397 ];
1398 for ao in all_ops {
1399 assert!(!ao.to_string().is_empty());
1400 }
1401 }
1402
1403 #[test]
1405 fn test_device_type_display() {
1406 assert_eq!(DeviceType::Host.to_string(), "host");
1407 assert_eq!(DeviceType::Nohost.to_string(), "nohost");
1408 assert_eq!(DeviceType::Any.to_string(), "any");
1409 }
1410
1411 #[test]
1412 fn test_device_type_all_variants() {
1413 let all_types = vec![DeviceType::Host, DeviceType::Nohost, DeviceType::Any];
1414 for dt in all_types {
1415 assert!(!dt.to_string().is_empty());
1416 }
1417 }
1418
1419 #[test]
1421 fn test_linear_modifier_display() {
1422 assert_eq!(LinearModifier::Val.to_string(), "val");
1423 assert_eq!(LinearModifier::Ref.to_string(), "ref");
1424 assert_eq!(LinearModifier::Uval.to_string(), "uval");
1425 }
1426
1427 #[test]
1429 fn test_lastprivate_modifier_display() {
1430 assert_eq!(LastprivateModifier::Conditional.to_string(), "conditional");
1431 }
1432
1433 #[test]
1435 fn test_order_kind_display() {
1436 assert_eq!(OrderKind::Concurrent.to_string(), "concurrent");
1437 }
1438
1439 #[test]
1441 fn test_enum_sizes_for_ffi() {
1442 use std::mem::size_of;
1443
1444 assert!(size_of::<ReductionOperator>() <= size_of::<usize>());
1446 assert!(size_of::<MapType>() <= size_of::<usize>());
1447 assert!(size_of::<ScheduleKind>() <= size_of::<usize>());
1448 assert!(size_of::<DependType>() <= size_of::<usize>());
1449 assert!(size_of::<DefaultKind>() <= size_of::<usize>());
1450 assert!(size_of::<ProcBind>() <= size_of::<usize>());
1451 assert!(size_of::<MemoryOrder>() <= size_of::<usize>());
1452 assert!(size_of::<AtomicOp>() <= size_of::<usize>());
1453 assert!(size_of::<DeviceType>() <= size_of::<usize>());
1454 assert!(size_of::<LinearModifier>() <= size_of::<usize>());
1455 assert!(size_of::<LastprivateModifier>() <= size_of::<usize>());
1456 assert!(size_of::<OrderKind>() <= size_of::<usize>());
1457 }
1458
1459 #[test]
1461 fn test_enum_hash_consistency() {
1462 use std::collections::hash_map::DefaultHasher;
1463 use std::hash::{Hash, Hasher};
1464
1465 let op1 = ReductionOperator::Add;
1466 let op2 = ReductionOperator::Add;
1467
1468 let mut hasher1 = DefaultHasher::new();
1469 let mut hasher2 = DefaultHasher::new();
1470
1471 op1.hash(&mut hasher1);
1472 op2.hash(&mut hasher2);
1473
1474 assert_eq!(hasher1.finish(), hasher2.finish());
1475 }
1476
1477 #[test]
1479 fn test_enum_debug_formatting() {
1480 let op = ReductionOperator::Add;
1481 let debug_str = format!("{op:?}");
1482 assert!(debug_str.contains("Add"));
1483 }
1484
1485 #[test]
1490 fn test_clause_item_from_identifier() {
1491 let id = Identifier::new("x");
1492 let item = ClauseItem::from(id);
1493 assert_eq!(item.to_string(), "x");
1494 }
1495
1496 #[test]
1497 fn test_clause_item_from_variable() {
1498 let var = Variable::new("arr");
1499 let item = ClauseItem::from(var);
1500 assert_eq!(item.to_string(), "arr");
1501 }
1502
1503 #[test]
1504 fn test_clause_item_from_expression() {
1505 use crate::ir::ParserConfig;
1506 let config = ParserConfig::default();
1507 let expr = Expression::new("n > 100", &config);
1508 let item = ClauseItem::from(expr);
1509 assert_eq!(item.to_string(), "n > 100");
1510 }
1511
1512 #[test]
1513 fn test_clause_item_display_identifier() {
1514 let item = ClauseItem::Identifier(Identifier::new("my_var"));
1515 assert_eq!(item.to_string(), "my_var");
1516 }
1517
1518 #[test]
1519 fn test_clause_item_display_variable_with_section() {
1520 use crate::ir::ArraySection;
1521 let section = ArraySection::single_index(Expression::unparsed("i"));
1522 let var = Variable::with_sections("arr", vec![section]);
1523 let item = ClauseItem::Variable(var);
1524 assert_eq!(item.to_string(), "arr[i]");
1525 }
1526
1527 #[test]
1528 fn test_clause_item_equality() {
1529 let item1 = ClauseItem::Identifier(Identifier::new("x"));
1530 let item2 = ClauseItem::Identifier(Identifier::new("x"));
1531 let item3 = ClauseItem::Identifier(Identifier::new("y"));
1532 assert_eq!(item1, item2);
1533 assert_ne!(item1, item3);
1534 }
1535
1536 #[test]
1537 fn test_clause_item_clone() {
1538 let item1 = ClauseItem::Identifier(Identifier::new("x"));
1539 let item2 = item1.clone();
1540 assert_eq!(item1, item2);
1541 }
1542
1543 #[test]
1548 fn test_clause_data_bare() {
1549 let clause = ClauseData::Bare(Identifier::new("nowait"));
1550 assert_eq!(clause.to_string(), "nowait");
1551 }
1552
1553 #[test]
1554 fn test_clause_data_default() {
1555 let clause = ClauseData::Default(DefaultKind::Shared);
1556 assert_eq!(clause.to_string(), "default(shared)");
1557
1558 let clause = ClauseData::Default(DefaultKind::None);
1559 assert_eq!(clause.to_string(), "default(none)");
1560 }
1561
1562 #[test]
1563 fn test_clause_data_private() {
1564 let items = vec![
1565 ClauseItem::Identifier(Identifier::new("x")),
1566 ClauseItem::Identifier(Identifier::new("y")),
1567 ];
1568 let clause = ClauseData::Private { items };
1569 assert_eq!(clause.to_string(), "private(x, y)");
1570 }
1571
1572 #[test]
1573 fn test_clause_data_private_single_item() {
1574 let items = vec![ClauseItem::Identifier(Identifier::new("x"))];
1575 let clause = ClauseData::Private { items };
1576 assert_eq!(clause.to_string(), "private(x)");
1577 }
1578
1579 #[test]
1580 fn test_clause_data_firstprivate() {
1581 let items = vec![
1582 ClauseItem::Identifier(Identifier::new("a")),
1583 ClauseItem::Identifier(Identifier::new("b")),
1584 ];
1585 let clause = ClauseData::Firstprivate { items };
1586 assert_eq!(clause.to_string(), "firstprivate(a, b)");
1587 }
1588
1589 #[test]
1590 fn test_clause_data_lastprivate_without_modifier() {
1591 let items = vec![ClauseItem::Identifier(Identifier::new("x"))];
1592 let clause = ClauseData::Lastprivate {
1593 modifier: None,
1594 items,
1595 };
1596 assert_eq!(clause.to_string(), "lastprivate(x)");
1597 }
1598
1599 #[test]
1600 fn test_clause_data_lastprivate_with_conditional() {
1601 let items = vec![ClauseItem::Identifier(Identifier::new("x"))];
1602 let clause = ClauseData::Lastprivate {
1603 modifier: Some(LastprivateModifier::Conditional),
1604 items,
1605 };
1606 assert_eq!(clause.to_string(), "lastprivate(conditional: x)");
1607 }
1608
1609 #[test]
1610 fn test_clause_data_shared() {
1611 let items = vec![
1612 ClauseItem::Identifier(Identifier::new("data")),
1613 ClauseItem::Identifier(Identifier::new("count")),
1614 ];
1615 let clause = ClauseData::Shared { items };
1616 assert_eq!(clause.to_string(), "shared(data, count)");
1617 }
1618
1619 #[test]
1620 fn test_clause_data_reduction() {
1621 let items = vec![ClauseItem::Identifier(Identifier::new("sum"))];
1622 let clause = ClauseData::Reduction {
1623 operator: ReductionOperator::Add,
1624 items,
1625 };
1626 assert_eq!(clause.to_string(), "reduction(+: sum)");
1627 }
1628
1629 #[test]
1630 fn test_clause_data_reduction_multiple_items() {
1631 let items = vec![
1632 ClauseItem::Identifier(Identifier::new("sum")),
1633 ClauseItem::Identifier(Identifier::new("total")),
1634 ];
1635 let clause = ClauseData::Reduction {
1636 operator: ReductionOperator::Add,
1637 items,
1638 };
1639 assert_eq!(clause.to_string(), "reduction(+: sum, total)");
1640 }
1641
1642 #[test]
1643 fn test_clause_data_reduction_max() {
1644 let items = vec![ClauseItem::Identifier(Identifier::new("max_val"))];
1645 let clause = ClauseData::Reduction {
1646 operator: ReductionOperator::Max,
1647 items,
1648 };
1649 assert_eq!(clause.to_string(), "reduction(max: max_val)");
1650 }
1651
1652 #[test]
1653 fn test_clause_data_map_simple() {
1654 let items = vec![ClauseItem::Variable(Variable::new("arr"))];
1655 let clause = ClauseData::Map {
1656 map_type: Some(MapType::To),
1657 mapper: None,
1658 items,
1659 };
1660 assert_eq!(clause.to_string(), "map(to: arr)");
1661 }
1662
1663 #[test]
1664 fn test_clause_data_map_tofrom() {
1665 let items = vec![ClauseItem::Variable(Variable::new("data"))];
1666 let clause = ClauseData::Map {
1667 map_type: Some(MapType::ToFrom),
1668 mapper: None,
1669 items,
1670 };
1671 assert_eq!(clause.to_string(), "map(tofrom: data)");
1672 }
1673
1674 #[test]
1675 fn test_clause_data_map_without_type() {
1676 let items = vec![ClauseItem::Variable(Variable::new("arr"))];
1677 let clause = ClauseData::Map {
1678 map_type: None,
1679 mapper: None,
1680 items,
1681 };
1682 assert_eq!(clause.to_string(), "map(arr)");
1683 }
1684
1685 #[test]
1686 fn test_clause_data_map_with_mapper() {
1687 let items = vec![ClauseItem::Variable(Variable::new("arr"))];
1688 let clause = ClauseData::Map {
1689 map_type: Some(MapType::To),
1690 mapper: Some(Identifier::new("my_mapper")),
1691 items,
1692 };
1693 assert_eq!(clause.to_string(), "map(mapper(my_mapper), to: arr)");
1694 }
1695
1696 #[test]
1697 fn test_clause_data_schedule_static() {
1698 let clause = ClauseData::Schedule {
1699 kind: ScheduleKind::Static,
1700 modifiers: vec![],
1701 chunk_size: None,
1702 };
1703 assert_eq!(clause.to_string(), "schedule(static)");
1704 }
1705
1706 #[test]
1707 fn test_clause_data_schedule_dynamic_with_chunk() {
1708 let chunk = Expression::unparsed("64");
1709 let clause = ClauseData::Schedule {
1710 kind: ScheduleKind::Dynamic,
1711 modifiers: vec![],
1712 chunk_size: Some(chunk),
1713 };
1714 assert_eq!(clause.to_string(), "schedule(dynamic, 64)");
1715 }
1716
1717 #[test]
1718 fn test_clause_data_schedule_with_modifier() {
1719 let clause = ClauseData::Schedule {
1720 kind: ScheduleKind::Static,
1721 modifiers: vec![ScheduleModifier::Monotonic],
1722 chunk_size: None,
1723 };
1724 assert_eq!(clause.to_string(), "schedule(monotonic: static)");
1725 }
1726
1727 #[test]
1728 fn test_clause_data_schedule_with_multiple_modifiers() {
1729 let clause = ClauseData::Schedule {
1730 kind: ScheduleKind::Dynamic,
1731 modifiers: vec![ScheduleModifier::Nonmonotonic, ScheduleModifier::Simd],
1732 chunk_size: Some(Expression::unparsed("32")),
1733 };
1734 assert_eq!(
1735 clause.to_string(),
1736 "schedule(nonmonotonic, simd: dynamic, 32)"
1737 );
1738 }
1739
1740 #[test]
1741 fn test_clause_data_linear_simple() {
1742 let items = vec![ClauseItem::Identifier(Identifier::new("i"))];
1743 let clause = ClauseData::Linear {
1744 modifier: None,
1745 items,
1746 step: None,
1747 };
1748 assert_eq!(clause.to_string(), "linear(i)");
1749 }
1750
1751 #[test]
1752 fn test_clause_data_linear_with_step() {
1753 let items = vec![ClauseItem::Identifier(Identifier::new("i"))];
1754 let clause = ClauseData::Linear {
1755 modifier: None,
1756 items,
1757 step: Some(Expression::unparsed("2")),
1758 };
1759 assert_eq!(clause.to_string(), "linear(i: 2)");
1760 }
1761
1762 #[test]
1763 fn test_clause_data_linear_with_modifier() {
1764 let items = vec![ClauseItem::Identifier(Identifier::new("i"))];
1765 let clause = ClauseData::Linear {
1766 modifier: Some(LinearModifier::Val),
1767 items,
1768 step: None,
1769 };
1770 assert_eq!(clause.to_string(), "linear(val: i)");
1771 }
1772
1773 #[test]
1774 fn test_clause_data_if_simple() {
1775 let condition = Expression::unparsed("n > 100");
1776 let clause = ClauseData::If {
1777 directive_name: None,
1778 condition,
1779 };
1780 assert_eq!(clause.to_string(), "if(n > 100)");
1781 }
1782
1783 #[test]
1784 fn test_clause_data_if_with_directive_name() {
1785 let condition = Expression::unparsed("n > 100");
1786 let clause = ClauseData::If {
1787 directive_name: Some(Identifier::new("parallel")),
1788 condition,
1789 };
1790 assert_eq!(clause.to_string(), "if(parallel: n > 100)");
1791 }
1792
1793 #[test]
1794 fn test_clause_data_num_threads() {
1795 let clause = ClauseData::NumThreads {
1796 num: Expression::unparsed("4"),
1797 };
1798 assert_eq!(clause.to_string(), "num_threads(4)");
1799 }
1800
1801 #[test]
1802 fn test_clause_data_proc_bind() {
1803 let clause = ClauseData::ProcBind(ProcBind::Close);
1804 assert_eq!(clause.to_string(), "proc_bind(close)");
1805 }
1806
1807 #[test]
1808 fn test_clause_data_device() {
1809 let clause = ClauseData::Device {
1810 device_num: Expression::unparsed("0"),
1811 };
1812 assert_eq!(clause.to_string(), "device(0)");
1813 }
1814
1815 #[test]
1816 fn test_clause_data_device_type() {
1817 let clause = ClauseData::DeviceType(DeviceType::Host);
1818 assert_eq!(clause.to_string(), "device_type(host)");
1819 }
1820
1821 #[test]
1822 fn test_clause_data_collapse() {
1823 let clause = ClauseData::Collapse {
1824 n: Expression::unparsed("2"),
1825 };
1826 assert_eq!(clause.to_string(), "collapse(2)");
1827 }
1828
1829 #[test]
1830 fn test_clause_data_ordered_without_param() {
1831 let clause = ClauseData::Ordered { n: None };
1832 assert_eq!(clause.to_string(), "ordered");
1833 }
1834
1835 #[test]
1836 fn test_clause_data_ordered_with_param() {
1837 let clause = ClauseData::Ordered {
1838 n: Some(Expression::unparsed("2")),
1839 };
1840 assert_eq!(clause.to_string(), "ordered(2)");
1841 }
1842
1843 #[test]
1844 fn test_clause_data_depend() {
1845 let items = vec![ClauseItem::Variable(Variable::new("x"))];
1846 let clause = ClauseData::Depend {
1847 depend_type: DependType::In,
1848 items,
1849 };
1850 assert_eq!(clause.to_string(), "depend(in: x)");
1851 }
1852
1853 #[test]
1854 fn test_clause_data_depend_inout() {
1855 let items = vec![
1856 ClauseItem::Variable(Variable::new("a")),
1857 ClauseItem::Variable(Variable::new("b")),
1858 ];
1859 let clause = ClauseData::Depend {
1860 depend_type: DependType::Inout,
1861 items,
1862 };
1863 assert_eq!(clause.to_string(), "depend(inout: a, b)");
1864 }
1865
1866 #[test]
1867 fn test_clause_data_equality() {
1868 let clause1 = ClauseData::Default(DefaultKind::Shared);
1869 let clause2 = ClauseData::Default(DefaultKind::Shared);
1870 let clause3 = ClauseData::Default(DefaultKind::None);
1871 assert_eq!(clause1, clause2);
1872 assert_ne!(clause1, clause3);
1873 }
1874
1875 #[test]
1876 fn test_clause_data_clone() {
1877 let items = vec![ClauseItem::Identifier(Identifier::new("x"))];
1878 let clause1 = ClauseData::Private { items };
1879 let clause2 = clause1.clone();
1880 assert_eq!(clause1, clause2);
1881 }
1882
1883 #[test]
1885 fn test_clause_data_private_empty_list() {
1886 let clause = ClauseData::Private { items: vec![] };
1887 assert_eq!(clause.to_string(), "private()");
1888 }
1889
1890 #[test]
1891 fn test_clause_data_reduction_empty_list() {
1892 let clause = ClauseData::Reduction {
1893 operator: ReductionOperator::Add,
1894 items: vec![],
1895 };
1896 assert_eq!(clause.to_string(), "reduction(+: )");
1897 }
1898
1899 #[test]
1901 fn test_clause_data_with_array_sections() {
1902 use crate::ir::ArraySection;
1903 let lower = Expression::unparsed("0");
1904 let length = Expression::unparsed("N");
1905 let section = ArraySection {
1906 lower_bound: Some(lower),
1907 length: Some(length),
1908 stride: None,
1909 };
1910 let var = Variable::with_sections("arr", vec![section]);
1911 let items = vec![ClauseItem::Variable(var)];
1912 let clause = ClauseData::Map {
1913 map_type: Some(MapType::To),
1914 mapper: None,
1915 items,
1916 };
1917 assert_eq!(clause.to_string(), "map(to: arr[0:N])");
1918 }
1919
1920 #[test]
1922 fn test_clause_data_with_expression_items() {
1923 let expr = Expression::unparsed("func(x, y)");
1924 let items = vec![ClauseItem::Expression(expr)];
1925 let clause = ClauseData::ItemList(items);
1926 assert_eq!(clause.to_string(), "func(x, y)");
1927 }
1928
1929 #[test]
1931 fn test_clause_data_debug() {
1932 let clause = ClauseData::Default(DefaultKind::Shared);
1933 let debug_str = format!("{clause:?}");
1934 assert!(debug_str.contains("Default"));
1935 assert!(debug_str.contains("Shared"));
1936 }
1937}