1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::sync::Arc;
use glsl_lang::ast::*;
use super::instantiate::InstantiateTemplate;
use super::{FnHandle, FnRef, GlobalScope, ParsedDeclaration, TransformUnit};
use crate::Result;
#[derive(Default, Debug, Clone)]
pub struct Unit {
global_scope: GlobalScope,
external_declarations: Vec<ExternalDeclaration>,
}
impl Unit {
pub fn new() -> Self {
Self {
global_scope: GlobalScope::new(),
external_declarations: Vec::new(),
}
}
pub fn with_context(global_scope: GlobalScope) -> Self {
Self {
global_scope,
external_declarations: Vec::new(),
}
}
pub fn into_translation_unit(self) -> Result<TranslationUnit> {
Ok(TranslationUnit(
self.external_declarations.into_iter().collect(),
))
}
}
impl TransformUnit for Unit {
fn global_scope(&self) -> &GlobalScope {
&self.global_scope
}
fn global_scope_mut(&mut self) -> &mut GlobalScope {
&mut self.global_scope
}
fn push_function_declaration(&mut self, def: FunctionDefinition) {
self.global_scope
.known_functions_mut()
.insert(def.prototype.name.0.clone(), def.prototype.clone());
let span = def.span;
self.external_declarations.push(ExternalDeclaration::new(
ExternalDeclarationData::FunctionDefinition(def),
span,
));
}
fn parse_external_declaration(
&mut self,
extdecl: ExternalDeclaration,
) -> Result<Option<FnHandle>> {
let unparsed;
match self.global_scope.parse_external_declaration(extdecl)? {
ParsedDeclaration::ConsumedAsType => {
return Ok(None);
}
ParsedDeclaration::ConsumedAsTemplate(r) => {
return Ok(Some(r.into()));
}
ParsedDeclaration::Unparsed(extdecl) => {
unparsed = extdecl;
}
}
let extdecl = Arc::try_unwrap(unparsed).unwrap();
match extdecl.content {
ExternalDeclarationData::FunctionDefinition(def) => {
let decls =
InstantiateTemplate::new(None).instantiate(&mut self.global_scope, def)?;
for d in decls {
self.push_function_declaration(d);
}
let f = self.external_declarations.last().unwrap();
match &f.content {
ExternalDeclarationData::FunctionDefinition(def) => {
return Ok(Some(
Node::new(
FnRef {
prototype: &def.prototype,
statement: &def.statement,
},
extdecl.span,
)
.into(),
));
}
_ => unreachable!(),
}
}
other => self
.external_declarations
.push(Node::new(other, extdecl.span)),
}
Ok(None)
}
}