Skip to main content

dry4rust/rust/normalizer/
helpers.rs

1// Copyright (c) 2026 Matjaz Domen Pecan
2// Copyright 2026 Umberto Gotti <umberto.gotti@umbertogotti.dev>
3// Licensed under the MIT License
4// SPDX-License-Identifier: MIT
5
6use crate::node::{BinOpKind, LiteralKind, NodeKind, NormalizedNode, UnOpKind};
7use crate::normalization_context::NormalizationContext;
8use syn::punctuated::Punctuated;
9
10use syn::BinOp;
11use syn::Expr;
12use syn::Lit;
13use syn::Macro;
14use syn::Member;
15use syn::UnOp;
16
17#[must_use]
18pub fn member_to_string(member: &Member) -> String {
19    match member {
20        Member::Named(ident) => ident.to_string(),
21        Member::Unnamed(idx) => idx.index.to_string(),
22    }
23}
24
25impl NormalizationContext {
26    pub fn normalize_macro(&mut self, mac: &Macro) -> NormalizedNode {
27        let name = mac
28            .path
29            .segments
30            .last()
31            .map(|s| s.ident.to_string())
32            .unwrap_or_default();
33        let args = if mac.tokens.is_empty() {
34            Vec::new()
35        } else {
36            match mac.parse_body_with(Punctuated::<Expr, syn::Token![,]>::parse_terminated) {
37                Ok(punct) => punct.into_iter().map(|e| self.normalize_expr(&e)).collect(),
38                Err(_) => vec![NormalizedNode::leaf(NodeKind::Opaque)],
39            }
40        };
41        NormalizedNode::with_children(NodeKind::MacroCall { name }, args)
42    }
43}
44
45#[must_use]
46pub const fn normalize_lit(lit: &Lit) -> NormalizedNode {
47    match lit {
48        Lit::Str(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::Str)),
49        Lit::ByteStr(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::ByteStr)),
50        Lit::CStr(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::CStr)),
51        Lit::Byte(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::Byte)),
52        Lit::Char(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::Char)),
53        Lit::Int(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::Int)),
54        Lit::Float(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::Float)),
55        Lit::Bool(_) => NormalizedNode::leaf(NodeKind::Literal(LiteralKind::Bool)),
56        _ => NormalizedNode::leaf(NodeKind::Opaque),
57    }
58}
59
60#[must_use]
61pub const fn normalize_bin_op(op: &BinOp) -> BinOpKind {
62    match op {
63        BinOp::Add(_) => BinOpKind::Add,
64        BinOp::Sub(_) => BinOpKind::Sub,
65        BinOp::Mul(_) => BinOpKind::Mul,
66        BinOp::Div(_) => BinOpKind::Div,
67        BinOp::Rem(_) => BinOpKind::Rem,
68        BinOp::And(_) => BinOpKind::And,
69        BinOp::Or(_) => BinOpKind::Or,
70        BinOp::BitXor(_) => BinOpKind::BitXor,
71        BinOp::BitAnd(_) => BinOpKind::BitAnd,
72        BinOp::BitOr(_) => BinOpKind::BitOr,
73        BinOp::Shl(_) => BinOpKind::Shl,
74        BinOp::Shr(_) => BinOpKind::Shr,
75        BinOp::Eq(_) => BinOpKind::Eq,
76        BinOp::Lt(_) => BinOpKind::Lt,
77        BinOp::Le(_) => BinOpKind::Le,
78        BinOp::Ne(_) => BinOpKind::Ne,
79        BinOp::Ge(_) => BinOpKind::Ge,
80        BinOp::Gt(_) => BinOpKind::Gt,
81        BinOp::AddAssign(_) => BinOpKind::AddAssign,
82        BinOp::SubAssign(_) => BinOpKind::SubAssign,
83        BinOp::MulAssign(_) => BinOpKind::MulAssign,
84        BinOp::DivAssign(_) => BinOpKind::DivAssign,
85        BinOp::RemAssign(_) => BinOpKind::RemAssign,
86        BinOp::BitXorAssign(_) => BinOpKind::BitXorAssign,
87        BinOp::BitAndAssign(_) => BinOpKind::BitAndAssign,
88        BinOp::BitOrAssign(_) => BinOpKind::BitOrAssign,
89        BinOp::ShlAssign(_) => BinOpKind::ShlAssign,
90        BinOp::ShrAssign(_) => BinOpKind::ShrAssign,
91        _ => BinOpKind::Other,
92    }
93}
94
95#[must_use]
96pub const fn normalize_un_op(op: &UnOp) -> UnOpKind {
97    match op {
98        UnOp::Deref(_) => UnOpKind::Deref,
99        UnOp::Not(_) => UnOpKind::Not,
100        UnOp::Neg(_) => UnOpKind::Neg,
101        _ => UnOpKind::Other,
102    }
103}