diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index 5da25fbf57..c570fd79b3 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -200,6 +200,8 @@ impl<'function> Context<'function> { let var = VariableReference { expr, load: Some(self.expressions.append(Expression::Load { pointer: expr })), + // TODO: respect constant qualifier + mutable: true, }; self.lookup_global_var_exps.insert(name.into(), var.clone()); @@ -218,7 +220,11 @@ impl<'function> Context<'function> { .expressions .append(Expression::Constant(*program.lookup_constants.get(name)?)); - let var = VariableReference { expr, load: None }; + let var = VariableReference { + expr, + load: None, + mutable: false, + }; self.lookup_constant_exps.insert(name.into(), var.clone()); @@ -236,7 +242,7 @@ impl<'function> Context<'function> { } /// Add variable to current scope - pub fn add_local_var(&mut self, name: String, expr: Handle) { + pub fn add_local_var(&mut self, name: String, expr: Handle, mutable: bool) { if let Some(current) = self.scopes.last_mut() { let load = self.expressions.append(Expression::Load { pointer: expr }); @@ -245,13 +251,14 @@ impl<'function> Context<'function> { VariableReference { expr, load: Some(load), + mutable, }, ); } } /// Add function argument to current scope - pub fn add_function_arg(&mut self, name: Option, ty: Handle) { + pub fn add_function_arg(&mut self, name: Option, ty: Handle, mutable: bool) { let index = self.arguments.len(); self.arguments.push(FunctionArgument { name: name.clone(), @@ -265,7 +272,14 @@ impl<'function> Context<'function> { .expressions .append(Expression::FunctionArgument(index as u32)); - (*current).insert(name, VariableReference { expr, load: None }); + (*current).insert( + name, + VariableReference { + expr, + load: None, + mutable, + }, + ); } } } @@ -347,6 +361,13 @@ impl<'function> Context<'function> { } ExprKind::Variable(var) => { if lhs { + if !var.mutable { + return Err(ErrorKind::SemanticError( + expr.meta, + "Variable cannot be used in LHS position".into(), + )); + } + var.expr } else { var.load.unwrap_or(var.expr) @@ -392,6 +413,7 @@ impl<'function> Context<'function> { pub struct VariableReference { pub expr: Handle, pub load: Option>, + pub mutable: bool, } #[derive(Debug, Clone)] @@ -469,7 +491,7 @@ pub enum StructLayout { Std140, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum ParameterQualifier { In, Out, diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index bd90a66e3f..727d010b58 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -1518,13 +1518,15 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { ) -> Result<()> { loop { if self.peek_type_name() || self.peek_parameter_qualifier() { - parameters.push(self.parse_parameter_qualifier()); + let qualifier = self.parse_parameter_qualifier(); + let mutable = qualifier != ParameterQualifier::Const; + parameters.push(qualifier); let ty = self.parse_type_non_void()?.0; match self.expect_peek()?.value { TokenValue::Comma => { self.bump()?; - context.add_function_arg(None, ty); + context.add_function_arg(None, ty, mutable); continue; } TokenValue::Identifier(_) => { @@ -1533,7 +1535,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { let size = self.parse_array_specifier()?; let ty = self.maybe_array(ty, size); - context.add_function_arg(Some(name), ty); + context.add_function_arg(Some(name), ty, mutable); if self.bump_if(TokenValue::Comma).is_some() { continue; diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index 7985633c28..7aaff1d7aa 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -385,13 +385,19 @@ impl Program<'_> { return Err(ErrorKind::VariableAlreadyDeclared(name)); } - // FIXME: this should be removed after - // fixing the lack of constant qualifier support - #[allow(clippy::never_loop)] + let mut mutable = true; + for qualifier in qualifiers { match *qualifier { TypeQualifier::StorageQualifier(StorageQualifier::Const) => { - return Err(ErrorKind::NotImplemented("const qualifier")); + if !mutable { + return Err(ErrorKind::SemanticError( + meta, + "Cannot use more than one constant qualifier per declaration".into(), + )); + } + + mutable = false; } _ => { return Err(ErrorKind::SemanticError( @@ -409,7 +415,7 @@ impl Program<'_> { }); let expr = ctx.expressions.append(Expression::LocalVariable(handle)); - ctx.add_local_var(name, expr); + ctx.add_local_var(name, expr, mutable); Ok(expr) }