Skip to main content

ptx_parser/unparser/
variable.rs

1use super::PtxUnparser;
2use crate::{
3    lexer::PtxToken,
4    r#type::{
5        common::AttributeDirective,
6        variable::{
7            GlobalInitializer, InitializerValue, ModuleVariableDirective, VariableDirective,
8            VariableModifier,
9        },
10    },
11    unparser::{push_decimal, push_directive, push_identifier, push_space},
12};
13
14impl PtxUnparser for InitializerValue {
15    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
16        self.unparse_tokens_mode(tokens, false);
17    }
18
19    fn unparse_tokens_mode(&self, tokens: &mut Vec<PtxToken>, spaced: bool) {
20        match self {
21            InitializerValue::NumericLiteral {
22                value: immediate, ..
23            } => immediate.unparse_tokens_mode(tokens, spaced),
24            InitializerValue::FunctionSymbol { name: symbol, .. } => {
25                push_identifier(tokens, &symbol.val)
26            }
27            InitializerValue::StringLiteral { value, .. } => {
28                tokens.push(PtxToken::StringLiteral(value.clone()));
29            }
30        }
31    }
32}
33
34impl PtxUnparser for GlobalInitializer {
35    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
36        self.unparse_tokens_mode(tokens, false);
37    }
38
39    fn unparse_tokens_mode(&self, tokens: &mut Vec<PtxToken>, spaced: bool) {
40        match self {
41            GlobalInitializer::Scalar { value, .. } => value.unparse_tokens_mode(tokens, spaced),
42            GlobalInitializer::Aggregate {
43                values: elements, ..
44            } => {
45                tokens.push(PtxToken::LBrace);
46                for (index, element) in elements.iter().enumerate() {
47                    if index > 0 {
48                        tokens.push(PtxToken::Comma);
49                        push_space(tokens, spaced);
50                    }
51                    element.unparse_tokens_mode(tokens, spaced);
52                }
53                tokens.push(PtxToken::RBrace);
54            }
55        }
56    }
57}
58
59impl PtxUnparser for VariableModifier {
60    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
61        self.unparse_tokens_mode(tokens, false);
62    }
63
64    fn unparse_tokens_mode(&self, tokens: &mut Vec<PtxToken>, spaced: bool) {
65        match self {
66            VariableModifier::Vector { value: width, .. } => {
67                push_directive(tokens, &format!("v{width}"));
68            }
69            VariableModifier::Alignment { value, .. } => {
70                push_directive(tokens, "align");
71                push_space(tokens, spaced);
72                push_decimal(tokens, value.to_string());
73            }
74            VariableModifier::Ptr { .. } => push_directive(tokens, "ptr"),
75        }
76    }
77}
78
79fn unparse_array_dimensions(tokens: &mut Vec<PtxToken>, extents: &[Option<u64>], spaced: bool) {
80    let _ = spaced;
81    for extent in extents {
82        tokens.push(PtxToken::LBracket);
83        if let Some(value) = extent {
84            push_decimal(tokens, value.to_string());
85        }
86        tokens.push(PtxToken::RBracket);
87    }
88}
89
90fn unparse_initializer(
91    tokens: &mut Vec<PtxToken>,
92    initializer: &Option<GlobalInitializer>,
93    spaced: bool,
94) {
95    if let Some(initializer) = initializer {
96        tokens.push(PtxToken::Equals);
97        push_space(tokens, spaced);
98        initializer.unparse_tokens_mode(tokens, spaced);
99    }
100}
101
102fn unparse_prefix(
103    tokens: &mut Vec<PtxToken>,
104    linkage_modifiers: &[VariableModifier],
105    other_modifiers: &[VariableModifier],
106    attributes: &[AttributeDirective],
107    spaced: bool,
108) {
109    for attribute in attributes {
110        attribute.unparse_tokens_mode(tokens, spaced);
111        push_space(tokens, spaced);
112    }
113    for modifier in linkage_modifiers {
114        modifier.unparse_tokens_mode(tokens, spaced);
115        push_space(tokens, spaced);
116    }
117    for modifier in other_modifiers {
118        modifier.unparse_tokens_mode(tokens, spaced);
119        push_space(tokens, spaced);
120    }
121}
122
123fn split_modifiers(
124    modifiers: &[VariableModifier],
125) -> (Vec<VariableModifier>, Vec<VariableModifier>) {
126    // Linkage is now handled at module level, not in modifiers
127    // All modifiers go to "other" category
128    (Vec::new(), modifiers.to_vec())
129}
130
131impl PtxUnparser for VariableDirective {
132    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
133        self.unparse_tokens_mode(tokens, false);
134    }
135
136    fn unparse_tokens_mode(&self, tokens: &mut Vec<PtxToken>, spaced: bool) {
137        let (linkage_modifiers, other_modifiers) = split_modifiers(&self.modifiers);
138        unparse_prefix(
139            tokens,
140            &linkage_modifiers,
141            &other_modifiers,
142            &self.attributes,
143            spaced,
144        );
145        if spaced {
146            if let Some(PtxToken::Space) = tokens.last() {
147                // remove trailing space if prefix was empty
148                tokens.pop();
149            }
150        }
151        self.ty.unparse_tokens_mode(tokens, spaced);
152        push_space(tokens, spaced);
153        push_identifier(tokens, &self.name.val);
154        unparse_array_dimensions(tokens, &self.array_dims, spaced);
155        unparse_initializer(tokens, &self.initializer, spaced);
156        tokens.push(PtxToken::Semicolon);
157    }
158}
159
160impl PtxUnparser for ModuleVariableDirective {
161    fn unparse_tokens(&self, tokens: &mut Vec<PtxToken>) {
162        self.unparse_tokens_mode(tokens, false);
163    }
164
165    fn unparse_tokens_mode(&self, tokens: &mut Vec<PtxToken>, spaced: bool) {
166        match self {
167            ModuleVariableDirective::Tex { directive, .. } => {
168                push_directive(tokens, "tex");
169                push_space(tokens, spaced);
170                directive.unparse_tokens_mode(tokens, spaced);
171            }
172            ModuleVariableDirective::Shared { directive, .. } => {
173                push_directive(tokens, "shared");
174                push_space(tokens, spaced);
175                directive.unparse_tokens_mode(tokens, spaced);
176            }
177            ModuleVariableDirective::Global { directive, .. } => {
178                push_directive(tokens, "global");
179                push_space(tokens, spaced);
180                directive.unparse_tokens_mode(tokens, spaced);
181            }
182            ModuleVariableDirective::Const { directive, .. } => {
183                push_directive(tokens, "const");
184                push_space(tokens, spaced);
185                directive.unparse_tokens_mode(tokens, spaced);
186            }
187        }
188    }
189}