diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index b0781715af..d770efcee0 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -24,6 +24,8 @@ pub struct FunctionDeclaration { pub handle: Handle, /// Wheter this function was already defined or is just a prototype pub defined: bool, + /// Wheter or not this function returns void (nothing) + pub void: bool, } #[derive(Debug)] @@ -321,24 +323,46 @@ impl<'function> Context<'function> { self.scopes.pop(); } - pub fn lower( + pub fn lower_expect( &mut self, program: &mut Program, expr: Handle, lhs: bool, body: &mut Block, ) -> Result<(Handle, SourceMetadata), ErrorKind> { + let (maybe_expr, meta) = self.lower(program, expr, lhs, body)?; + + let expr = match maybe_expr { + Some(e) => e, + None => { + return Err(ErrorKind::SemanticError( + meta, + "Expression returns void".into(), + )) + } + }; + + Ok((expr, meta)) + } + + pub fn lower( + &mut self, + program: &mut Program, + expr: Handle, + lhs: bool, + body: &mut Block, + ) -> Result<(Option>, SourceMetadata), ErrorKind> { let HirExpr { kind, meta } = self.hir_exprs[expr].clone(); let handle = match kind { HirExprKind::Access { base, index } => { - let base = self.lower(program, base, lhs, body)?.0; - let index = self.lower(program, index, false, body)?.0; + let base = self.lower_expect(program, base, lhs, body)?.0; + let index = self.lower_expect(program, index, false, body)?.0; self.add_expression(Expression::Access { base, index }, body) } HirExprKind::Select { base, field } => { - let base = self.lower(program, base, lhs, body)?.0; + let base = self.lower_expect(program, base, lhs, body)?.0; program.field_selection(self, body, base, &field, meta)? } @@ -346,8 +370,8 @@ impl<'function> Context<'function> { self.add_expression(Expression::Constant(constant), body) } HirExprKind::Binary { left, op, right } if !lhs => { - let (left, left_meta) = self.lower(program, left, false, body)?; - let (right, right_meta) = self.lower(program, right, false, body)?; + let (left, left_meta) = self.lower_expect(program, left, false, body)?; + let (right, right_meta) = self.lower_expect(program, right, false, body)?; if let BinaryOperator::Equal | BinaryOperator::NotEqual = op { let equals = op == BinaryOperator::Equal; @@ -386,7 +410,7 @@ impl<'function> Context<'function> { } } HirExprKind::Unary { op, expr } if !lhs => { - let expr = self.lower(program, expr, false, body)?.0; + let expr = self.lower_expect(program, expr, false, body)?.0; self.add_expression(Expression::Unary { op, expr }, body) } @@ -405,16 +429,17 @@ impl<'function> Context<'function> { } } HirExprKind::Call(call) if !lhs => { - program.function_call(self, body, call.kind, &call.args, meta)? + let maybe_expr = program.function_call(self, body, call.kind, &call.args, meta)?; + return Ok((maybe_expr, meta)); } HirExprKind::Conditional { condition, accept, reject, } if !lhs => { - let condition = self.lower(program, condition, false, body)?.0; - let accept = self.lower(program, accept, false, body)?.0; - let reject = self.lower(program, reject, false, body)?.0; + let condition = self.lower_expect(program, condition, false, body)?.0; + let accept = self.lower_expect(program, accept, false, body)?.0; + let reject = self.lower_expect(program, reject, false, body)?.0; self.add_expression( Expression::Select { @@ -426,8 +451,8 @@ impl<'function> Context<'function> { ) } HirExprKind::Assign { tgt, value } if !lhs => { - let pointer = self.lower(program, tgt, true, body)?.0; - let value = self.lower(program, value, false, body)?.0; + let pointer = self.lower_expect(program, tgt, true, body)?.0; + let value = self.lower_expect(program, value, false, body)?.0; self.emit_flush(body); self.emit_start(); @@ -444,7 +469,7 @@ impl<'function> Context<'function> { } }; - Ok((handle, meta)) + Ok((Some(handle), meta)) } } diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 766f255e12..7659d23ea0 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -15,10 +15,10 @@ impl Program<'_> { fc: FunctionCallKind, raw_args: &[Handle], meta: SourceMetadata, - ) -> Result, ErrorKind> { + ) -> Result>, ErrorKind> { let args: Vec<_> = raw_args .iter() - .map(|e| ctx.lower(self, *e, false, body)) + .map(|e| ctx.lower_expect(self, *e, false, body)) .collect::>()?; match fc { @@ -89,7 +89,7 @@ impl Program<'_> { ) }; - Ok(h) + Ok(Some(h)) } FunctionCallKind::Function(name) => { match name.as_str() { @@ -98,14 +98,14 @@ impl Program<'_> { return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta)); } ctx.samplers.insert(args[0].0, args[1].0); - Ok(args[0].0) + Ok(Some(args[0].0)) } "texture" => { if args.len() != 2 { return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta)); } if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() { - Ok(ctx.add_expression( + Ok(Some(ctx.add_expression( Expression::ImageSample { image: args[0].0, sampler, @@ -116,7 +116,7 @@ impl Program<'_> { depth_ref: None, }, body, - )) + ))) } else { Err(ErrorKind::SemanticError(meta, "Bad call to texture".into())) } @@ -126,7 +126,7 @@ impl Program<'_> { return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta)); } if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() { - Ok(ctx.add_expression( + Ok(Some(ctx.add_expression( Expression::ImageSample { image: args[0].0, sampler, @@ -137,7 +137,7 @@ impl Program<'_> { depth_ref: None, }, body, - )) + ))) } else { Err(ErrorKind::SemanticError( meta, @@ -151,7 +151,7 @@ impl Program<'_> { if args.len() != 1 { return Err(ErrorKind::wrong_function_args(name, 1, args.len(), meta)); } - Ok(ctx.add_expression( + Ok(Some(ctx.add_expression( Expression::Math { fun: match name.as_str() { "ceil" => MathFunction::Ceil, @@ -176,13 +176,13 @@ impl Program<'_> { arg2: None, }, body, - )) + ))) } "pow" | "dot" | "max" => { if args.len() != 2 { return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta)); } - Ok(ctx.add_expression( + Ok(Some(ctx.add_expression( Expression::Math { fun: match name.as_str() { "pow" => MathFunction::Pow, @@ -195,13 +195,13 @@ impl Program<'_> { arg2: None, }, body, - )) + ))) } "mix" | "clamp" => { if args.len() != 3 { return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta)); } - Ok(ctx.add_expression( + Ok(Some(ctx.add_expression( Expression::Math { fun: match name.as_str() { "mix" => MathFunction::Mix, @@ -213,14 +213,14 @@ impl Program<'_> { arg2: Some(args[2].0), }, body, - )) + ))) } "lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" | "equal" | "notEqual" => { if args.len() != 2 { return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta)); } - Ok(ctx.add_expression( + Ok(Some(ctx.add_expression( Expression::Binary { op: match name.as_str() { "lessThan" => BinaryOperator::Less, @@ -235,7 +235,7 @@ impl Program<'_> { right: args[1].0, }, body, - )) + ))) } "isinf" | "isnan" | "all" | "any" => { let fun = match name.as_str() { @@ -246,7 +246,9 @@ impl Program<'_> { _ => unreachable!(), }; - self.parse_relational_fun(ctx, body, name, &args, fun, meta) + Ok(Some( + self.parse_relational_fun(ctx, body, name, &args, fun, meta)?, + )) } _ => { let mut parameters = Vec::new(); @@ -273,22 +275,27 @@ impl Program<'_> { let mut arguments = Vec::with_capacity(raw_args.len()); for (qualifier, expr) in fun.parameters.iter().zip(raw_args.iter()) { - let handle = ctx.lower(self, *expr, qualifier.is_lhs(), body)?.0; + let handle = ctx.lower_expect(self, *expr, qualifier.is_lhs(), body)?.0; arguments.push(handle) } ctx.emit_flush(body); - let expression = ctx.add_expression(Expression::Call(fun.handle), body); + let result = if !fun.void { + Some(ctx.add_expression(Expression::Call(fun.handle), body)) + } else { + None + }; + body.push(crate::Statement::Call { function: fun.handle, arguments, - result: Some(expression), + result, }); ctx.emit_start(); - Ok(expression) + Ok(result) } } } @@ -351,6 +358,8 @@ impl Program<'_> { } } + let void = function.result.is_none(); + if let Some(decl) = self.lookup_function.get_mut(&sig) { if decl.defined { return Err(ErrorKind::SemanticError( @@ -369,6 +378,7 @@ impl Program<'_> { parameters, handle, defined: true, + void, }, ); } @@ -391,6 +401,7 @@ impl Program<'_> { name, parameters: function.arguments.iter().map(|p| p.ty).collect(), }; + let void = function.result.is_none(); for (arg, qualifier) in function.arguments.iter_mut().zip(parameters.iter()) { if qualifier.is_lhs() { @@ -412,6 +423,7 @@ impl Program<'_> { parameters, handle, defined: false, + void, }, ); diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index 3e9fd25bb8..56fc1c32df 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -330,7 +330,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { ); let expr = self.parse_conditional(&mut ctx, &mut block, None)?; - let (root, meta) = ctx.lower(self.program, expr, false, &mut block)?; + let (root, meta) = ctx.lower_expect(self.program, expr, false, &mut block)?; Ok((self.program.solve_constant(&ctx, root, meta)?, meta)) } @@ -434,7 +434,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { )) } else { let expr = self.parse_assignment(ctx, body)?; - Ok(ctx.lower(self.program, expr, false, body)?) + Ok(ctx.lower_expect(self.program, expr, false, body)?) } } @@ -1183,7 +1183,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { _ => { let expr = self.parse_expression(ctx, body)?; self.expect(TokenValue::Semicolon)?; - Some(ctx.lower(self.program, expr, false, body)?.0) + Some(ctx.lower_expect(self.program, expr, false, body)?.0) } }; @@ -1203,7 +1203,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { self.expect(TokenValue::LeftParen)?; let condition = { let expr = self.parse_expression(ctx, body)?; - ctx.lower(self.program, expr, false, body)?.0 + ctx.lower_expect(self.program, expr, false, body)?.0 }; self.expect(TokenValue::RightParen)?; @@ -1230,7 +1230,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { self.expect(TokenValue::LeftParen)?; let selector = { let expr = self.parse_expression(ctx, body)?; - ctx.lower(self.program, expr, false, body)?.0 + ctx.lower_expect(self.program, expr, false, body)?.0 }; self.expect(TokenValue::RightParen)?; @@ -1247,7 +1247,8 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { self.bump()?; let value = { let expr = self.parse_expression(ctx, body)?; - let (root, meta) = ctx.lower(self.program, expr, false, body)?; + let (root, meta) = + ctx.lower_expect(self.program, expr, false, body)?; let constant = self.program.solve_constant(&ctx, root, meta)?; match self.program.module.constants[constant].inner { @@ -1332,7 +1333,9 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { let root = self.parse_expression(ctx, &mut loop_body)?; self.expect(TokenValue::RightParen)?; - let expr = ctx.lower(self.program, root, false, &mut loop_body)?.0; + let expr = ctx + .lower_expect(self.program, root, false, &mut loop_body)? + .0; let condition = ctx.add_expression( Expression::Unary { op: UnaryOperator::Not, @@ -1368,7 +1371,9 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { let root = self.parse_expression(ctx, &mut loop_body)?; self.expect(TokenValue::RightParen)?; - let expr = ctx.lower(self.program, root, false, &mut loop_body)?.0; + let expr = ctx + .lower_expect(self.program, root, false, &mut loop_body)? + .0; let condition = ctx.add_expression( Expression::Unary { op: UnaryOperator::Not, @@ -1439,7 +1444,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { value } else { let root = self.parse_expression(ctx, &mut block)?; - ctx.lower(self.program, root, false, &mut block)?.0 + ctx.lower_expect(self.program, root, false, &mut block)?.0 }; let condition = ctx.add_expression(