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 (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 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}