diff --git a/src/arena.rs b/src/arena.rs index 174c79b540..bd3a3d7762 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -240,6 +240,11 @@ impl Arena { marker: PhantomData, } } + + /// Clears the arena keeping all allocations + pub fn clear(&mut self) { + self.data.clear() + } } impl ops::Index> for Arena { diff --git a/src/front/glsl/context.rs b/src/front/glsl/context.rs index 33b89410c8..8b30a6a2bc 100644 --- a/src/front/glsl/context.rs +++ b/src/front/glsl/context.rs @@ -29,9 +29,9 @@ pub struct Context { pub lookup_global_var_exps: FastHashMap, pub samplers: FastHashMap, Handle>, - pub hir_exprs: Arena, pub typifier: Typifier, emitter: Emitter, + stmt_ctx: Option, } impl Context { @@ -51,9 +51,9 @@ impl Context { ), samplers: FastHashMap::default(), - hir_exprs: Arena::default(), typifier: Typifier::new(), emitter: Emitter::default(), + stmt_ctx: Some(StmtContext::new()), }; this.emit_start(); @@ -280,14 +280,71 @@ impl Context { self.scopes.pop(); } + /// Returns a [`StmtContext`](StmtContext) to be used in parsing and lowering + /// + /// # Panics + /// - If more than one [`StmtContext`](StmtContext) are active at the same + /// time or if the previous call didn't use it in lowering. + #[must_use] + pub fn stmt_ctx(&mut self) -> StmtContext { + self.stmt_ctx.take().unwrap() + } + + /// Lowers a [`HirExpr`](HirExpr) which might produce a [`Expression`](Expression). + /// + /// consumes a [`StmtContext`](StmtContext) returning it to the context so + /// that it can be used again later. + pub fn lower( + &mut self, + mut stmt: StmtContext, + parser: &mut Parser, + expr: Handle, + lhs: bool, + body: &mut Block, + ) -> Result<(Option>, SourceMetadata)> { + let res = self.lower_inner(&stmt, parser, expr, lhs, body); + + stmt.hir_exprs.clear(); + self.stmt_ctx = Some(stmt); + + res + } + + /// Similar to [`lower`](Self::lower) but returns an error if the expression + /// returns void (ie. doesn't produce a [`Expression`](Expression)). + /// + /// consumes a [`StmtContext`](StmtContext) returning it to the context so + /// that it can be used again later. pub fn lower_expect( &mut self, + mut stmt: StmtContext, parser: &mut Parser, expr: Handle, lhs: bool, body: &mut Block, ) -> Result<(Handle, SourceMetadata)> { - let (maybe_expr, meta) = self.lower(parser, expr, lhs, body)?; + let res = self.lower_expect_inner(&stmt, parser, expr, lhs, body); + + stmt.hir_exprs.clear(); + self.stmt_ctx = Some(stmt); + + res + } + + /// internal implementation of [`lower_expect`](Self::lower_expect) + /// + /// this method is only public because it's used in + /// [`function_call`](Parser::function_call), unless you know what + /// you're doing use [`lower_expect`](Self::lower_expect) + pub fn lower_expect_inner( + &mut self, + stmt: &StmtContext, + parser: &mut Parser, + expr: Handle, + lhs: bool, + body: &mut Block, + ) -> Result<(Handle, SourceMetadata)> { + let (maybe_expr, meta) = self.lower_inner(stmt, parser, expr, lhs, body)?; let expr = match maybe_expr { Some(e) => e, @@ -302,19 +359,22 @@ impl Context { Ok((expr, meta)) } - pub fn lower( + /// Internal implementation of [`lower`](Self::lower) + fn lower_inner( &mut self, + stmt: &StmtContext, parser: &mut Parser, expr: Handle, lhs: bool, body: &mut Block, ) -> Result<(Option>, SourceMetadata)> { - let HirExpr { kind, meta } = self.hir_exprs[expr].clone(); + let HirExpr { ref kind, meta } = stmt.hir_exprs[expr]; - let handle = match kind { + let handle = match *kind { HirExprKind::Access { base, index } => { - let base = self.lower_expect(parser, base, true, body)?.0; - let (index, index_meta) = self.lower_expect(parser, index, false, body)?; + let base = self.lower_expect_inner(stmt, parser, base, true, body)?.0; + let (index, index_meta) = + self.lower_expect_inner(stmt, parser, index, false, body)?; let pointer = parser .solve_constant(self, index, index_meta) @@ -354,17 +414,19 @@ impl Context { pointer } - HirExprKind::Select { base, field } => { - let base = self.lower_expect(parser, base, lhs, body)?.0; + HirExprKind::Select { base, ref field } => { + let base = self.lower_expect_inner(stmt, parser, base, lhs, body)?.0; - parser.field_selection(self, lhs, body, base, &field, meta)? + parser.field_selection(self, lhs, body, base, field, meta)? } HirExprKind::Constant(constant) if !lhs => { self.add_expression(Expression::Constant(constant), body) } HirExprKind::Binary { left, op, right } if !lhs => { - let (mut left, left_meta) = self.lower_expect(parser, left, false, body)?; - let (mut right, right_meta) = self.lower_expect(parser, right, false, body)?; + let (mut left, left_meta) = + self.lower_expect_inner(stmt, parser, left, false, body)?; + let (mut right, right_meta) = + self.lower_expect_inner(stmt, parser, right, false, body)?; match op { BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight => self @@ -439,11 +501,11 @@ impl Context { } } HirExprKind::Unary { op, expr } if !lhs => { - let expr = self.lower_expect(parser, expr, false, body)?.0; + let expr = self.lower_expect_inner(stmt, parser, expr, false, body)?.0; self.add_expression(Expression::Unary { op, expr }, body) } - HirExprKind::Variable(var) => { + HirExprKind::Variable(ref var) => { if lhs { if !var.mutable { parser.errors.push(Error { @@ -461,9 +523,15 @@ impl Context { var.expr } } - HirExprKind::Call(call) if !lhs => { - let maybe_expr = - parser.function_or_constructor_call(self, body, call.kind, &call.args, meta)?; + HirExprKind::Call(ref call) if !lhs => { + let maybe_expr = parser.function_or_constructor_call( + self, + stmt, + body, + call.kind.clone(), + &call.args, + meta, + )?; return Ok((maybe_expr, meta)); } HirExprKind::Conditional { @@ -471,9 +539,13 @@ impl Context { accept, reject, } if !lhs => { - let condition = self.lower_expect(parser, condition, false, body)?.0; - let (mut accept, accept_meta) = self.lower_expect(parser, accept, false, body)?; - let (mut reject, reject_meta) = self.lower_expect(parser, reject, false, body)?; + let condition = self + .lower_expect_inner(stmt, parser, condition, false, body)? + .0; + let (mut accept, accept_meta) = + self.lower_expect_inner(stmt, parser, accept, false, body)?; + let (mut reject, reject_meta) = + self.lower_expect_inner(stmt, parser, reject, false, body)?; self.binary_implicit_conversion( parser, @@ -493,8 +565,9 @@ impl Context { ) } HirExprKind::Assign { tgt, value } if !lhs => { - let (pointer, ptr_meta) = self.lower_expect(parser, tgt, true, body)?; - let (mut value, value_meta) = self.lower_expect(parser, value, false, body)?; + let (pointer, ptr_meta) = self.lower_expect_inner(stmt, parser, tgt, true, body)?; + let (mut value, value_meta) = + self.lower_expect_inner(stmt, parser, value, false, body)?; let scalar_components = self.expr_scalar_components(parser, pointer, ptr_meta)?; @@ -564,7 +637,7 @@ impl Context { false => BinaryOperator::Subtract, }; - let pointer = self.lower_expect(parser, expr, true, body)?.0; + let pointer = self.lower_expect_inner(stmt, parser, expr, true, body)?.0; let left = self.add_expression(Expression::Load { pointer }, body); let uint = match parser.resolve_type(self, left, meta)?.scalar_kind() { @@ -641,7 +714,7 @@ impl Context { _ => { return Err(Error { kind: ErrorKind::SemanticError( - format!("{:?} cannot be in the left hand side", self.hir_exprs[expr]) + format!("{:?} cannot be in the left hand side", stmt.hir_exprs[expr]) .into(), ), meta, @@ -779,3 +852,22 @@ impl Index> for Context { &self.expressions[index] } } + +/// Helper struct passed when parsing expressions +/// +/// This struct should only be obtained trough [`stmt_ctx`](Context::stmt_ctx) +/// and only one of these may be active at any time per context. +#[derive(Debug)] +pub struct StmtContext { + /// A arena of high level expressions which can be lowered trough a + /// [`Context`](Context) to naga's [`Expression`](crate::Expression)s + pub hir_exprs: Arena, +} + +impl StmtContext { + fn new() -> Self { + StmtContext { + hir_exprs: Arena::new(), + } + } +} diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 6475c0aa22..dd2d6d0f7c 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -1,6 +1,6 @@ use super::{ ast::*, - context::Context, + context::{Context, StmtContext}, error::{Error, ErrorKind}, types::{scalar_components, type_power}, Parser, Result, SourceMetadata, @@ -41,6 +41,7 @@ impl Parser { pub(crate) fn function_or_constructor_call( &mut self, ctx: &mut Context, + stmt: &StmtContext, body: &mut Block, fc: FunctionCallKind, raw_args: &[Handle], @@ -48,7 +49,7 @@ impl Parser { ) -> Result>> { let args: Vec<_> = raw_args .iter() - .map(|e| ctx.lower_expect(self, *e, false, body)) + .map(|e| ctx.lower_expect_inner(stmt, self, *e, false, body)) .collect::>()?; match fc { @@ -307,14 +308,16 @@ impl Parser { Ok(Some(h)) } FunctionCallKind::Function(name) => { - self.function_call(ctx, body, name, args, raw_args, meta) + self.function_call(ctx, stmt, body, name, args, raw_args, meta) } } } + #[allow(clippy::too_many_arguments)] fn function_call( &mut self, ctx: &mut Context, + stmt: &StmtContext, body: &mut Block, name: String, mut args: Vec<(Handle, SourceMetadata)>, @@ -969,8 +972,13 @@ impl Parser { .iter() .zip(raw_args.iter().zip(parameters.iter())) { - let (mut handle, meta) = - ctx.lower_expect(self, *expr, parameter_info.qualifier.is_lhs(), body)?; + let (mut handle, meta) = ctx.lower_expect_inner( + stmt, + self, + *expr, + parameter_info.qualifier.is_lhs(), + body, + )?; if let TypeInner::Vector { size, kind, width } = *self.resolve_type(ctx, handle, meta)? @@ -1025,27 +1033,16 @@ impl Parser { ctx.emit_start(); for (tgt, pointer) in proxy_writes { - let temp_ref = ctx.hir_exprs.append(HirExpr { - kind: HirExprKind::Variable(VariableReference { - expr: pointer, - load: true, - mutable: true, - entry_arg: None, - }), - meta, - }); - let assign = ctx.hir_exprs.append(HirExpr { - kind: HirExprKind::Assign { - tgt, - value: temp_ref, - }, - meta, - }); + let value = ctx.add_expression(Expression::Load { pointer }, body); + let target = ctx.lower_expect_inner(stmt, self, tgt, true, body)?.0; - let _ = ctx.lower_expect(self, assign, false, body)?; + ctx.emit_flush(body); + body.push(Statement::Store { + pointer: target, + value, + }); + ctx.emit_start(); } - ctx.emit_flush(body); - ctx.emit_start(); Ok(result) } diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index b002f9b16c..a5ee5f409c 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -192,8 +192,9 @@ impl<'source> ParsingContext<'source> { let mut ctx = Context::new(parser, &mut block); - let expr = self.parse_conditional(parser, &mut ctx, &mut block, None)?; - let (root, meta) = ctx.lower_expect(parser, expr, false, &mut block)?; + let mut stmt_ctx = ctx.stmt_ctx(); + let expr = self.parse_conditional(parser, &mut ctx, &mut stmt_ctx, &mut block, None)?; + let (root, meta) = ctx.lower_expect(stmt_ctx, parser, expr, false, &mut block)?; Ok((parser.solve_constant(&ctx, root, meta)?, meta)) } diff --git a/src/front/glsl/parser/declarations.rs b/src/front/glsl/parser/declarations.rs index a127517947..d6fbd7c706 100644 --- a/src/front/glsl/parser/declarations.rs +++ b/src/front/glsl/parser/declarations.rs @@ -98,8 +98,9 @@ impl<'source> ParsingContext<'source> { meta, )) } else { - let expr = self.parse_assignment(parser, ctx, body)?; - let (mut init, init_meta) = ctx.lower_expect(parser, expr, false, body)?; + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_assignment(parser, ctx, &mut stmt, body)?; + let (mut init, init_meta) = ctx.lower_expect(stmt, parser, expr, false, body)?; let scalar_components = scalar_components(&parser.module.types[ty].inner); if let Some((kind, width)) = scalar_components { diff --git a/src/front/glsl/parser/expressions.rs b/src/front/glsl/parser/expressions.rs index f0d98dd2ae..59eacb9a4e 100644 --- a/src/front/glsl/parser/expressions.rs +++ b/src/front/glsl/parser/expressions.rs @@ -1,7 +1,7 @@ use crate::{ front::glsl::{ ast::{FunctionCall, FunctionCallKind, HirExpr, HirExprKind}, - context::Context, + context::{Context, StmtContext}, error::{ErrorKind, ExpectedToken}, parser::ParsingContext, token::{Token, TokenValue}, @@ -16,6 +16,7 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, ) -> Result> { let mut token = self.bump(parser)?; @@ -35,7 +36,7 @@ impl<'source> ParsingContext<'source> { ), TokenValue::BoolConstant(value) => (1, ScalarValue::Bool(value)), TokenValue::LeftParen => { - let expr = self.parse_expression(parser, ctx, body)?; + let expr = self.parse_expression(parser, ctx, stmt, body)?; let meta = self.expect(parser, TokenValue::RightParen)?.meta; token.meta = token.meta.union(&meta); @@ -64,7 +65,7 @@ impl<'source> ParsingContext<'source> { inner: ConstantInner::Scalar { width, value }, }); - Ok(ctx.hir_exprs.append(HirExpr { + Ok(stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Constant(handle), meta: token.meta, })) @@ -74,6 +75,7 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, meta: &mut SourceMetadata, ) -> Result>> { @@ -82,7 +84,7 @@ impl<'source> ParsingContext<'source> { *meta = meta.union(&token.meta); } else { loop { - args.push(self.parse_assignment(parser, ctx, body)?); + args.push(self.parse_assignment(parser, ctx, stmt, body)?); let token = self.bump(parser)?; match token.value { @@ -111,6 +113,7 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, ) -> Result> { let mut base = match self.expect_peek(parser)?.value { @@ -118,7 +121,7 @@ impl<'source> ParsingContext<'source> { let (name, mut meta) = self.expect_ident(parser)?; let expr = if self.bump_if(parser, TokenValue::LeftParen).is_some() { - let args = self.parse_function_call_args(parser, ctx, body, &mut meta)?; + let args = self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?; let kind = match parser.lookup_type.get(&name) { Some(ty) => FunctionCallKind::TypeConstructor(*ty), @@ -146,7 +149,7 @@ impl<'source> ParsingContext<'source> { } }; - ctx.hir_exprs.append(expr) + stmt.hir_exprs.append(expr) } TokenValue::TypeName(_) => { let Token { value, mut meta } = self.bump(parser)?; @@ -160,7 +163,7 @@ impl<'source> ParsingContext<'source> { let maybe_size = self.parse_array_specifier(parser)?; self.expect(parser, TokenValue::LeftParen)?; - let args = self.parse_function_call_args(parser, ctx, body, &mut meta)?; + let args = self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?; if let Some(array_size) = maybe_size { let stride = parser.module.types[handle] @@ -193,7 +196,7 @@ impl<'source> ParsingContext<'source> { }) } - ctx.hir_exprs.append(HirExpr { + stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Call(FunctionCall { kind: FunctionCallKind::TypeConstructor(handle), args, @@ -201,7 +204,7 @@ impl<'source> ParsingContext<'source> { meta, }) } - _ => self.parse_primary(parser, ctx, body)?, + _ => self.parse_primary(parser, ctx, stmt, body)?, }; while let TokenValue::LeftBracket @@ -213,10 +216,10 @@ impl<'source> ParsingContext<'source> { match value { TokenValue::LeftBracket => { - let index = self.parse_expression(parser, ctx, body)?; + let index = self.parse_expression(parser, ctx, stmt, body)?; let end_meta = self.expect(parser, TokenValue::RightBracket)?.meta; - base = ctx.hir_exprs.append(HirExpr { + base = stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Access { base, index }, meta: meta.union(&end_meta), }) @@ -224,13 +227,13 @@ impl<'source> ParsingContext<'source> { TokenValue::Dot => { let (field, end_meta) = self.expect_ident(parser)?; - base = ctx.hir_exprs.append(HirExpr { + base = stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Select { base, field }, meta: meta.union(&end_meta), }) } TokenValue::Increment => { - base = ctx.hir_exprs.append(HirExpr { + base = stmt.hir_exprs.append(HirExpr { kind: HirExprKind::IncDec { increment: true, postfix: true, @@ -240,7 +243,7 @@ impl<'source> ParsingContext<'source> { }) } TokenValue::Decrement => { - base = ctx.hir_exprs.append(HirExpr { + base = stmt.hir_exprs.append(HirExpr { kind: HirExprKind::IncDec { increment: false, postfix: true, @@ -260,6 +263,7 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, ) -> Result> { // TODO: prefix inc/dec @@ -267,8 +271,8 @@ impl<'source> ParsingContext<'source> { TokenValue::Plus | TokenValue::Dash | TokenValue::Bang | TokenValue::Tilde => { let Token { value, meta } = self.bump(parser)?; - let expr = self.parse_unary(parser, ctx, body)?; - let end_meta = ctx.hir_exprs[expr].meta; + let expr = self.parse_unary(parser, ctx, stmt, body)?; + let end_meta = stmt.hir_exprs[expr].meta; let kind = match value { TokenValue::Dash => HirExprKind::Unary { @@ -282,7 +286,7 @@ impl<'source> ParsingContext<'source> { _ => return Ok(expr), }; - ctx.hir_exprs.append(HirExpr { + stmt.hir_exprs.append(HirExpr { kind, meta: meta.union(&end_meta), }) @@ -290,9 +294,9 @@ impl<'source> ParsingContext<'source> { TokenValue::Increment | TokenValue::Decrement => { let Token { value, meta } = self.bump(parser)?; - let expr = self.parse_unary(parser, ctx, body)?; + let expr = self.parse_unary(parser, ctx, stmt, body)?; - ctx.hir_exprs.append(HirExpr { + stmt.hir_exprs.append(HirExpr { kind: HirExprKind::IncDec { increment: match value { TokenValue::Increment => true, @@ -305,7 +309,7 @@ impl<'source> ParsingContext<'source> { meta, }) } - _ => self.parse_postfix(parser, ctx, body)?, + _ => self.parse_postfix(parser, ctx, stmt, body)?, }) } @@ -313,14 +317,15 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, passtrough: Option>, min_bp: u8, ) -> Result> { let mut left = passtrough .ok_or(ErrorKind::EndOfFile /* Dummy error */) - .or_else(|_| self.parse_unary(parser, ctx, body))?; - let start_meta = ctx.hir_exprs[left].meta; + .or_else(|_| self.parse_unary(parser, ctx, stmt, body))?; + let start_meta = stmt.hir_exprs[left].meta; while let Some((l_bp, r_bp)) = binding_power(&self.expect_peek(parser)?.value) { if l_bp < min_bp { @@ -329,10 +334,10 @@ impl<'source> ParsingContext<'source> { let Token { value, .. } = self.bump(parser)?; - let right = self.parse_binary(parser, ctx, body, None, r_bp)?; - let end_meta = ctx.hir_exprs[right].meta; + let right = self.parse_binary(parser, ctx, stmt, body, None, r_bp)?; + let end_meta = stmt.hir_exprs[right].meta; - left = ctx.hir_exprs.append(HirExpr { + left = stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Binary { left, op: match value { @@ -370,19 +375,20 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, passtrough: Option>, ) -> Result> { - let mut condition = self.parse_binary(parser, ctx, body, passtrough, 0)?; - let start_meta = ctx.hir_exprs[condition].meta; + let mut condition = self.parse_binary(parser, ctx, stmt, body, passtrough, 0)?; + let start_meta = stmt.hir_exprs[condition].meta; if self.bump_if(parser, TokenValue::Question).is_some() { - let accept = self.parse_expression(parser, ctx, body)?; + let accept = self.parse_expression(parser, ctx, stmt, body)?; self.expect(parser, TokenValue::Colon)?; - let reject = self.parse_assignment(parser, ctx, body)?; - let end_meta = ctx.hir_exprs[reject].meta; + let reject = self.parse_assignment(parser, ctx, stmt, body)?; + let end_meta = stmt.hir_exprs[reject].meta; - condition = ctx.hir_exprs.append(HirExpr { + condition = stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Conditional { condition, accept, @@ -399,18 +405,19 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, ) -> Result> { - let tgt = self.parse_unary(parser, ctx, body)?; - let start_meta = ctx.hir_exprs[tgt].meta; + let tgt = self.parse_unary(parser, ctx, stmt, body)?; + let start_meta = stmt.hir_exprs[tgt].meta; Ok(match self.expect_peek(parser)?.value { TokenValue::Assign => { self.bump(parser)?; - let value = self.parse_assignment(parser, ctx, body)?; - let end_meta = ctx.hir_exprs[value].meta; + let value = self.parse_assignment(parser, ctx, stmt, body)?; + let end_meta = stmt.hir_exprs[value].meta; - ctx.hir_exprs.append(HirExpr { + stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Assign { tgt, value }, meta: start_meta.union(&end_meta), }) @@ -426,10 +433,10 @@ impl<'source> ParsingContext<'source> { | TokenValue::RightShiftAssign | TokenValue::XorAssign => { let token = self.bump(parser)?; - let right = self.parse_assignment(parser, ctx, body)?; - let end_meta = ctx.hir_exprs[right].meta; + let right = self.parse_assignment(parser, ctx, stmt, body)?; + let end_meta = stmt.hir_exprs[right].meta; - let value = ctx.hir_exprs.append(HirExpr { + let value = stmt.hir_exprs.append(HirExpr { meta: start_meta.union(&end_meta), kind: HirExprKind::Binary { left: tgt, @@ -450,12 +457,12 @@ impl<'source> ParsingContext<'source> { }, }); - ctx.hir_exprs.append(HirExpr { + stmt.hir_exprs.append(HirExpr { kind: HirExprKind::Assign { tgt, value }, meta: start_meta.union(&end_meta), }) } - _ => self.parse_conditional(parser, ctx, body, Some(tgt))?, + _ => self.parse_conditional(parser, ctx, stmt, body, Some(tgt))?, }) } @@ -463,13 +470,14 @@ impl<'source> ParsingContext<'source> { &mut self, parser: &mut Parser, ctx: &mut Context, + stmt: &mut StmtContext, body: &mut Block, ) -> Result> { - let mut expr = self.parse_assignment(parser, ctx, body)?; + let mut expr = self.parse_assignment(parser, ctx, stmt, body)?; while let TokenValue::Comma = self.expect_peek(parser)?.value { self.bump(parser)?; - expr = self.parse_assignment(parser, ctx, body)?; + expr = self.parse_assignment(parser, ctx, stmt, body)?; } Ok(expr) diff --git a/src/front/glsl/parser/functions.rs b/src/front/glsl/parser/functions.rs index 24e1ac9870..efc72803bf 100644 --- a/src/front/glsl/parser/functions.rs +++ b/src/front/glsl/parser/functions.rs @@ -71,9 +71,10 @@ impl<'source> ParsingContext<'source> { } _ => { // TODO: Implicit conversions - let expr = self.parse_expression(parser, ctx, body)?; + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_expression(parser, ctx, &mut stmt, body)?; self.expect(parser, TokenValue::Semicolon)?; - Some(ctx.lower_expect(parser, expr, false, body)?.0) + Some(ctx.lower_expect(stmt, parser, expr, false, body)?.0) } }; @@ -92,8 +93,9 @@ impl<'source> ParsingContext<'source> { self.expect(parser, TokenValue::LeftParen)?; let condition = { - let expr = self.parse_expression(parser, ctx, body)?; - ctx.lower_expect(parser, expr, false, body)?.0 + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_expression(parser, ctx, &mut stmt, body)?; + ctx.lower_expect(stmt, parser, expr, false, body)?.0 }; self.expect(parser, TokenValue::RightParen)?; @@ -120,8 +122,9 @@ impl<'source> ParsingContext<'source> { self.expect(parser, TokenValue::LeftParen)?; // TODO: Implicit conversions let selector = { - let expr = self.parse_expression(parser, ctx, body)?; - ctx.lower_expect(parser, expr, false, body)?.0 + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_expression(parser, ctx, &mut stmt, body)?; + ctx.lower_expect(stmt, parser, expr, false, body)?.0 }; self.expect(parser, TokenValue::RightParen)?; @@ -137,8 +140,10 @@ impl<'source> ParsingContext<'source> { TokenValue::Case => { self.bump(parser)?; let value = { - let expr = self.parse_expression(parser, ctx, body)?; - let (root, meta) = ctx.lower_expect(parser, expr, false, body)?; + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_expression(parser, ctx, &mut stmt, body)?; + let (root, meta) = + ctx.lower_expect(stmt, parser, expr, false, body)?; let constant = parser.solve_constant(ctx, root, meta)?; match parser.module.constants[constant].inner { @@ -252,11 +257,14 @@ impl<'source> ParsingContext<'source> { let mut loop_body = Block::new(); + let mut stmt = ctx.stmt_ctx(); self.expect(parser, TokenValue::LeftParen)?; - let root = self.parse_expression(parser, ctx, &mut loop_body)?; + let root = self.parse_expression(parser, ctx, &mut stmt, &mut loop_body)?; self.expect(parser, TokenValue::RightParen)?; - let expr = ctx.lower_expect(parser, root, false, &mut loop_body)?.0; + let expr = ctx + .lower_expect(stmt, parser, root, false, &mut loop_body)? + .0; let condition = ctx.add_expression( Expression::Unary { op: UnaryOperator::Not, @@ -287,12 +295,16 @@ impl<'source> ParsingContext<'source> { let mut loop_body = Block::new(); self.parse_statement(parser, ctx, &mut loop_body)?; + let mut stmt = ctx.stmt_ctx(); + self.expect(parser, TokenValue::While)?; self.expect(parser, TokenValue::LeftParen)?; - let root = self.parse_expression(parser, ctx, &mut loop_body)?; + let root = self.parse_expression(parser, ctx, &mut stmt, &mut loop_body)?; self.expect(parser, TokenValue::RightParen)?; - let expr = ctx.lower_expect(parser, root, false, &mut loop_body)?.0; + let expr = ctx + .lower_expect(stmt, parser, root, false, &mut loop_body)? + .0; let condition = ctx.add_expression( Expression::Unary { op: UnaryOperator::Not, @@ -325,8 +337,9 @@ impl<'source> ParsingContext<'source> { if self.peek_type_name(parser) || self.peek_type_qualifier(parser) { self.parse_declaration(parser, ctx, body, false)?; } else { - let expr = self.parse_expression(parser, ctx, body)?; - ctx.lower(parser, expr, false, body)?; + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_expression(parser, ctx, &mut stmt, body)?; + ctx.lower(stmt, parser, expr, false, body)?; self.expect(parser, TokenValue::Semicolon)?; } } @@ -361,8 +374,9 @@ impl<'source> ParsingContext<'source> { value } else { - let root = self.parse_expression(parser, ctx, &mut block)?; - ctx.lower_expect(parser, root, false, &mut block)?.0 + let mut stmt = ctx.stmt_ctx(); + let root = self.parse_expression(parser, ctx, &mut stmt, &mut block)?; + ctx.lower_expect(stmt, parser, root, false, &mut block)?.0 }; let condition = ctx.add_expression( @@ -388,8 +402,10 @@ impl<'source> ParsingContext<'source> { match self.expect_peek(parser)?.value { TokenValue::RightParen => {} _ => { - let rest = self.parse_expression(parser, ctx, &mut continuing)?; - ctx.lower(parser, rest, false, &mut continuing)?; + let mut stmt = ctx.stmt_ctx(); + let rest = + self.parse_expression(parser, ctx, &mut stmt, &mut continuing)?; + ctx.lower(stmt, parser, rest, false, &mut continuing)?; } } @@ -425,8 +441,9 @@ impl<'source> ParsingContext<'source> { | TokenValue::IntConstant(_) | TokenValue::BoolConstant(_) | TokenValue::FloatConstant(_) => { - let expr = self.parse_expression(parser, ctx, body)?; - ctx.lower(parser, expr, false, body)?; + let mut stmt = ctx.stmt_ctx(); + let expr = self.parse_expression(parser, ctx, &mut stmt, body)?; + ctx.lower(stmt, parser, expr, false, body)?; self.expect(parser, TokenValue::Semicolon)?; } TokenValue::Semicolon => {