Skip to content

Commit 6035b07

Browse files
SparkyPotatoteoxoyjimblandy
committed
[wgsl-in] Implement module-level scoping.
Fixes #1745: Support out-of-order module scope declarations in WGSL Fixes #1044: Forbid local variable shadowing in WGSL Fixes #2076: [wgsl-in] no error for duplicated type definition Fixes #2071: Global item does not support 'const' Fixes #2105: [wgsl-in] Type aliases for a vecN<T> doesn't work when constructing vec from a single argument Fixes #1775: Referencing a function without a return type yields an unknown identifier error. Fixes #2089: Error span reported on the declaration of a variable instead of its use Fixes #1996: [wgsl-in] Confusing error: "expected unsigned/signed integer literal, found '1'" Separate parsing from lowering by generating an AST, which desugars as much as possible down to something like Naga IR. The AST is then used to resolve identifiers while lowering to Naga IR. Co-authored-by: Teodor Tanasoaia <[email protected]> Co-authored-by: Jim Blandy <[email protected]>
1 parent 7effd12 commit 6035b07

File tree

104 files changed

+9846
-8030
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+9846
-8030
lines changed

src/back/wgsl/writer.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,7 @@ impl<W: Write> Writer<W> {
18501850
} => {
18511851
let name = &self.names[&NameKey::Constant(handle)];
18521852
// First write only constant name
1853-
write!(self.out, "let {}: ", name)?;
1853+
write!(self.out, "const {}: ", name)?;
18541854
// Next write constant type and value
18551855
match *value {
18561856
crate::ScalarValue::Sint(value) => {
@@ -1874,7 +1874,7 @@ impl<W: Write> Writer<W> {
18741874
crate::ConstantInner::Composite { ty, ref components } => {
18751875
let name = &self.names[&NameKey::Constant(handle)];
18761876
// First write only constant name
1877-
write!(self.out, "let {}: ", name)?;
1877+
write!(self.out, "const {}: ", name)?;
18781878
// Next write constant type
18791879
self.write_type(module, ty)?;
18801880

src/front/glsl/parser_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ fn expressions() {
796796
# version 450
797797
void main() {
798798
uint index = 0;
799-
799+
800800
--index;
801801
++index;
802802
}

src/front/glsl/types.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -300,20 +300,7 @@ impl Parser {
300300
meta: Span,
301301
) -> Result<Handle<Type>> {
302302
self.typifier_grow(ctx, expr, meta)?;
303-
let resolution = &ctx.typifier[expr];
304-
Ok(match *resolution {
305-
// If the resolution is already a handle return early
306-
crate::proc::TypeResolution::Handle(ty) => ty,
307-
// If it's a value we need to clone it
308-
crate::proc::TypeResolution::Value(_) => match resolution.clone() {
309-
// This is unreachable
310-
crate::proc::TypeResolution::Handle(ty) => ty,
311-
// Add the value to the type arena and return the handle
312-
crate::proc::TypeResolution::Value(inner) => {
313-
self.module.types.insert(Type { name: None, inner }, meta)
314-
}
315-
},
316-
})
303+
Ok(ctx.typifier.register_type(expr, &mut self.module.types))
317304
}
318305

319306
/// Invalidates the cached type resolution for `expr` forcing a recomputation

src/front/mod.rs

+63-4
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,35 @@ impl super::ConstantInner {
6464
}
6565
}
6666

67-
/// Helper processor that derives the types of all expressions.
67+
/// A table of types for an `Arena<Expression>`.
68+
///
69+
/// A front end can use a `Typifier` to get types for an arena's expressions
70+
/// while it is still contributing expressions to it. At any point, you can call
71+
/// [`typifier.grow(expr, arena, ctx)`], where `expr` is a `Handle<Expression>`
72+
/// referring to something in `arena`, and the `Typifier` will resolve the types
73+
/// of all the expressions up to and including `expr`. Then you can write
74+
/// `typifier[handle]` to get the type of any handle at or before `expr`.
75+
///
76+
/// Note that `Typifier` does *not* build an `Arena<Type>` as a part of its
77+
/// usual operation. Ideally, a module's type arena should only contain types
78+
/// actually needed by `Handle<Type>`s elsewhere in the module — functions,
79+
/// variables, [`Compose`] expressions, other types, and so on — so we don't
80+
/// want every little thing that occurs as the type of some intermediate
81+
/// expression to show up there.
82+
///
83+
/// Instead, `Typifier` accumulates a [`TypeResolution`] for each expression,
84+
/// which refers to the `Arena<Type>` in the [`ResolveContext`] passed to `grow`
85+
/// as needed. [`TypeResolution`] is a lightweight representation for
86+
/// intermediate types like this; see its documentation for details.
87+
///
88+
/// If you do need to register a `Typifier`'s conclusion in an `Arena<Type>`
89+
/// (say, for a [`LocalVariable`] whose type you've inferred), you can use
90+
/// [`register_type`] to do so.
91+
///
92+
/// [`typifier.grow(expr, arena)`]: Typifier::grow
93+
/// [`register_type`]: Typifier::register_type
94+
/// [`Compose`]: crate::Expression::Compose
95+
/// [`LocalVariable`]: crate::LocalVariable
6896
#[derive(Debug, Default)]
6997
pub struct Typifier {
7098
resolutions: Vec<TypeResolution>,
@@ -89,6 +117,34 @@ impl Typifier {
89117
self.resolutions[expr_handle.index()].inner_with(types)
90118
}
91119

120+
/// Add an expression's type to an `Arena<Type>`.
121+
///
122+
/// Add the type of `expr_handle` to `types`, and return a `Handle<Type>`
123+
/// referring to it.
124+
///
125+
/// # Note
126+
///
127+
/// If you just need a [`TypeInner`] for `expr_handle`'s type, consider
128+
/// using `typifier[expression].inner_with(types)` instead. Calling
129+
/// [`TypeResolution::inner_with`] often lets us avoid adding anything to
130+
/// the arena, which can significantly reduce the number of types that end
131+
/// up in the final module.
132+
///
133+
/// [`TypeInner`]: crate::TypeInner
134+
pub fn register_type(
135+
&self,
136+
expr_handle: Handle<crate::Expression>,
137+
types: &mut UniqueArena<crate::Type>,
138+
) -> Handle<crate::Type> {
139+
match self[expr_handle].clone() {
140+
TypeResolution::Handle(handle) => handle,
141+
TypeResolution::Value(inner) => {
142+
types.insert(crate::Type { name: None, inner }, crate::Span::UNDEFINED)
143+
}
144+
}
145+
}
146+
147+
/// Grow this typifier until it contains a type for `expr_handle`.
92148
pub fn grow(
93149
&mut self,
94150
expr_handle: Handle<crate::Expression>,
@@ -106,10 +162,13 @@ impl Typifier {
106162
Ok(())
107163
}
108164

109-
/// Invalidates the cached type resolution for `expr_handle` forcing a recomputation
165+
/// Recompute the type resolution for `expr_handle`.
166+
///
167+
/// If the type of `expr_handle` hasn't yet been calculated, call
168+
/// [`grow`](Self::grow) to ensure it is covered.
110169
///
111-
/// If the type of the expression hasn't yet been calculated a
112-
/// [`grow`](Self::grow) is performed instead
170+
/// In either case, when this returns, `self[expr_handle]` should be an
171+
/// updated type resolution for `expr_handle`.
113172
pub fn invalidate(
114173
&mut self,
115174
expr_handle: Handle<crate::Expression>,

0 commit comments

Comments
 (0)