[glsl-in] Fix void function calls

This commit is contained in:
João Capucho
2021-05-20 22:28:34 +01:00
committed by Dzmitry Malyshau
parent c526c85258
commit 4e95c46a9d
3 changed files with 86 additions and 44 deletions

View File

@@ -24,6 +24,8 @@ pub struct FunctionDeclaration {
pub handle: Handle<Function>,
/// 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<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Handle<Expression>, 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<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Option<Handle<Expression>>, 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))
}
}

View File

@@ -15,10 +15,10 @@ impl Program<'_> {
fc: FunctionCallKind,
raw_args: &[Handle<HirExpr>],
meta: SourceMetadata,
) -> Result<Handle<Expression>, ErrorKind> {
) -> Result<Option<Handle<Expression>>, 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::<Result<_, _>>()?;
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,
},
);

View File

@@ -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(