glslt/transform/
global_scope.rs1use std::collections::HashSet;
2use std::sync::Arc;
3
4use glsl_lang::ast::*;
5
6use indexmap::IndexMap;
7
8use super::template::{TemplateDefinition, TryTemplate};
9use super::{ResolvedArgument, ResolvedArgumentExpr, Scope};
10
11use crate::{Error, Result, TransformConfig};
12
13pub enum ParsedDeclaration {
15 ConsumedAsType,
17 ConsumedAsTemplate(Arc<TemplateDefinition>),
19 Unparsed(Arc<ExternalDeclaration>),
21}
22
23#[derive(Default, Debug, Clone)]
25pub struct GlobalScope {
26 config: TransformConfig,
28 declared_pointer_types: IndexMap<SmolStr, FunctionPrototype>,
30 declared_templates: IndexMap<SmolStr, Arc<TemplateDefinition>>,
32 known_functions: IndexMap<SmolStr, FunctionPrototype>,
34 instantiated_templates: HashSet<SmolStr>,
36 instanced_templates: Vec<FunctionDefinition>,
38}
39
40impl GlobalScope {
41 pub fn new() -> Self {
43 Self::default()
44 }
45
46 pub fn with_config(config: TransformConfig) -> Self {
48 Self {
49 config,
50 ..Default::default()
51 }
52 }
53
54 fn parse_function_prototype(&mut self, prototype: FunctionPrototype) -> Result<()> {
55 if let Some(previous) = self.declared_pointer_types.get(&prototype.name.0) {
56 return Err(Error::new_duplicate_pointer_definition(
58 &prototype.name,
59 previous,
60 ));
61 } else {
62 info!("declared pointer: {}", prototype.name.0);
63
64 self.declared_pointer_types
65 .insert(prototype.name.0.clone(), prototype);
66 }
67
68 Ok(())
69 }
70
71 fn parse_declaration(&mut self, decl: Declaration) -> Result<ParsedDeclaration> {
72 match decl.content {
73 DeclarationData::FunctionPrototype(prototype) => {
74 self.parse_function_prototype(prototype)?;
76 Ok(ParsedDeclaration::ConsumedAsType)
77 }
78 other => Ok(ParsedDeclaration::Unparsed(Arc::new(
79 ExternalDeclaration::new(
80 ExternalDeclarationData::Declaration(Declaration::new(other, decl.span)),
81 decl.span,
82 ),
83 ))),
84 }
85 }
86
87 fn parse_function_definition(&mut self, def: FunctionDefinition) -> Result<ParsedDeclaration> {
88 let span = def.span;
89
90 let name = def.prototype.name.0.clone();
92 let template =
93 super::template::parse_definition_as_template(def, &self.declared_pointer_types)?;
94
95 match template {
96 TryTemplate::Template(template) => {
97 info!("declared template: {}", template.ast().prototype.name.0);
98
99 self.declared_templates
101 .insert(name.clone(), Arc::new(*template));
102
103 let parsed = self.declared_templates.get(&name).unwrap();
104 Ok(ParsedDeclaration::ConsumedAsTemplate(parsed.clone()))
105 }
106 TryTemplate::Function(def) => Ok(ParsedDeclaration::Unparsed(Arc::new(
107 ExternalDeclaration::new(ExternalDeclarationData::FunctionDefinition(*def), span),
108 ))),
109 }
110 }
111
112 pub fn known_functions_mut(&mut self) -> &mut IndexMap<SmolStr, FunctionPrototype> {
114 &mut self.known_functions
115 }
116
117 pub fn declared_templates(&self) -> &IndexMap<SmolStr, Arc<TemplateDefinition>> {
119 &self.declared_templates
120 }
121
122 pub fn declared_pointer_types(&self) -> &IndexMap<SmolStr, FunctionPrototype> {
124 &self.declared_pointer_types
125 }
126
127 pub fn parse_external_declaration(
141 &mut self,
142 extdecl: ExternalDeclaration,
143 ) -> Result<ParsedDeclaration> {
144 let span = extdecl.span;
145
146 match extdecl.content {
147 ExternalDeclarationData::Declaration(decl) => self.parse_declaration(decl),
148 ExternalDeclarationData::FunctionDefinition(def) => {
149 Ok(self.parse_function_definition(def)?)
150 }
151 other => Ok(ParsedDeclaration::Unparsed(Arc::new(
153 ExternalDeclaration::new(other, span),
154 ))),
155 }
156 }
157
158 pub fn push_function_declaration(&mut self, def: &FunctionDefinition) {
167 self.known_functions
169 .insert(def.prototype.name.0.clone(), def.prototype.clone());
170 }
171}
172
173impl Scope for GlobalScope {
174 fn config(&self) -> &TransformConfig {
175 &self.config
176 }
177
178 fn parent_scope(&self) -> Option<&dyn Scope> {
179 None
180 }
181
182 fn declared_pointer_types(&self) -> &IndexMap<SmolStr, FunctionPrototype> {
183 &self.declared_pointer_types
184 }
185
186 fn get_template(&self, template_name: &str) -> Option<Arc<TemplateDefinition>> {
187 self.declared_templates.get(template_name).cloned()
188 }
189
190 fn template_instance_declared(&self, template_name: &str) -> bool {
191 self.instantiated_templates.contains(template_name)
192 }
193
194 fn register_template_instance(&mut self, definitions: Vec<FunctionDefinition>) {
195 for template in definitions {
196 let template_name = template.prototype.name.0.as_str();
197
198 self.instantiated_templates.insert(template_name.into());
200
201 self.instanced_templates.push(template);
203 }
204 }
205
206 fn take_instanced_templates(&mut self) -> Vec<FunctionDefinition> {
207 std::mem::replace(&mut self.instanced_templates, Vec::with_capacity(2))
208 }
209
210 fn resolve_function_name(&self, name: &str) -> Option<ResolvedArgument> {
211 self.known_functions
212 .get(name)
213 .map(|proto| ResolvedArgument {
214 body: ResolvedArgumentExpr::FunctionName(proto.name.0.clone()),
215 pointer_type: proto,
216 })
217 }
218
219 fn transform_arg_call(
220 &mut self,
221 _expr: &mut Expr,
222 _instantiator: &mut super::instantiate::InstantiateTemplate,
223 ) -> Result<()> {
224 Err(Error::TransformAsTemplate)
225 }
226
227 fn captured_parameters(&self) -> &[super::instantiate::CapturedParameter] {
228 &[]
229 }
230}