[glsl-in] Improve error api and make more errors deferred

This commit is contained in:
João Capucho
2021-08-08 00:10:56 +01:00
committed by Dzmitry Malyshau
parent f6e35f5b66
commit 1aaf77489b
18 changed files with 720 additions and 592 deletions

View File

@@ -409,22 +409,15 @@ use codespan_reporting::{
},
};
pub fn emit_glsl_parser_error(
errors: Vec<naga::front::glsl::ParseError>,
filename: &str,
source: &str,
) {
pub fn emit_glsl_parser_error(errors: Vec<naga::front::glsl::Error>, filename: &str, source: &str) {
let files = SimpleFile::new(filename, source);
let config = codespan_reporting::term::Config::default();
let writer = StandardStream::stderr(ColorChoice::Auto);
for err in errors {
let diagnostic = match err.kind.metadata() {
Some(metadata) => Diagnostic::error()
.with_message(err.kind.to_string())
.with_labels(vec![Label::primary((), metadata.start..metadata.end)]),
None => Diagnostic::error().with_message(err.kind.to_string()),
};
let diagnostic = Diagnostic::error()
.with_message(err.kind.to_string())
.with_labels(vec![Label::primary((), err.meta.start..err.meta.end)]);
term::emit(&mut writer.lock(), &config, &files, &diagnostic).expect("cannot write error");
}

View File

@@ -1,7 +1,7 @@
use super::SourceMetadata;
use crate::{
BinaryOperator, Binding, Constant, Expression, Function, GlobalVariable, Handle, Interpolation,
ResourceBinding, Sampling, StorageAccess, StorageClass, Type, UnaryOperator,
Sampling, StorageAccess, StorageClass, Type, UnaryOperator,
};
#[derive(Debug, Clone, Copy)]
@@ -102,7 +102,8 @@ pub enum HirExprKind {
pub enum TypeQualifier {
StorageQualifier(StorageQualifier),
Interpolation(Interpolation),
ResourceBinding(ResourceBinding),
Set(u32),
Binding(u32),
Location(u32),
WorkGroupSize(usize, u32),
Sampling(Sampling),

View File

@@ -5,9 +5,9 @@ use crate::{
GlobalLookup, GlobalLookupKind, HirExpr, HirExprKind, ParameterInfo,
ParameterQualifier, VariableReference,
},
error::ErrorKind,
error::{Error, ErrorKind},
types::{scalar_components, type_power},
Parser, SourceMetadata,
Parser, Result, SourceMetadata,
},
Emitter, Typifier,
},
@@ -288,16 +288,16 @@ impl Context {
expr: Handle<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Handle<Expression>, SourceMetadata), ErrorKind> {
) -> Result<(Handle<Expression>, SourceMetadata)> {
let (maybe_expr, meta) = self.lower(parser, expr, lhs, body)?;
let expr = match maybe_expr {
Some(e) => e,
None => {
return Err(ErrorKind::SemanticError(
return Err(Error {
kind: ErrorKind::SemanticError("Expression returns void".into()),
meta,
"Expression returns void".into(),
))
})
}
};
@@ -310,7 +310,7 @@ impl Context {
expr: Handle<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Option<Handle<Expression>>, SourceMetadata), ErrorKind> {
) -> Result<(Option<Handle<Expression>>, SourceMetadata)> {
let HirExpr { kind, meta } = self.hir_exprs[expr].clone();
let handle = match kind {
@@ -448,10 +448,12 @@ impl Context {
HirExprKind::Variable(var) => {
if lhs {
if !var.mutable {
return Err(ErrorKind::SemanticError(
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
"Variable cannot be used in LHS position".into(),
),
meta,
"Variable cannot be used in LHS position".into(),
));
})
}
var.expr
@@ -567,23 +569,18 @@ impl Context {
let pointer = self.lower_expect(parser, expr, true, body)?.0;
let left = self.add_expression(Expression::Load { pointer }, body);
let uint = if let Some(kind) = parser.resolve_type(self, left, meta)?.scalar_kind()
{
match kind {
ScalarKind::Sint => false,
ScalarKind::Uint => true,
_ => {
return Err(ErrorKind::SemanticError(
meta,
let uint = match parser.resolve_type(self, left, meta)?.scalar_kind() {
Some(ScalarKind::Sint) => false,
Some(ScalarKind::Uint) => true,
_ => {
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
"Increment/decrement operations must operate in integers".into(),
))
}
),
meta,
});
true
}
} else {
return Err(ErrorKind::SemanticError(
meta,
"Increment/decrement operations must operate in integers".into(),
));
};
let one = parser.module.constants.append(Constant {
@@ -644,10 +641,13 @@ impl Context {
}
}
_ => {
return Err(ErrorKind::SemanticError(
return Err(Error {
kind: ErrorKind::SemanticError(
format!("{:?} cannot be in the left hand side", self.hir_exprs[expr])
.into(),
),
meta,
format!("{:?} cannot be in the left hand side", self.hir_exprs[expr]).into(),
))
})
}
};
@@ -659,7 +659,7 @@ impl Context {
parser: &mut Parser,
expr: Handle<Expression>,
meta: SourceMetadata,
) -> Result<Option<(ScalarKind, crate::Bytes)>, ErrorKind> {
) -> Result<Option<(ScalarKind, crate::Bytes)>> {
let ty = parser.resolve_type(self, expr, meta)?;
Ok(scalar_components(ty))
}
@@ -669,16 +669,12 @@ impl Context {
parser: &mut Parser,
expr: Handle<Expression>,
meta: SourceMetadata,
) -> Result<Option<u32>, ErrorKind> {
) -> Result<Option<u32>> {
Ok(self
.expr_scalar_components(parser, expr, meta)?
.and_then(|(kind, _)| type_power(kind)))
}
pub fn get_expression(&self, expr: Handle<Expression>) -> &Expression {
&self.expressions[expr]
}
pub fn implicit_conversion(
&mut self,
parser: &mut Parser,
@@ -686,7 +682,7 @@ impl Context {
meta: SourceMetadata,
kind: ScalarKind,
width: crate::Bytes,
) -> Result<(), ErrorKind> {
) -> Result<()> {
if let (Some(tgt_power), Some(expr_power)) =
(type_power(kind), self.expr_power(parser, *expr, meta)?)
{
@@ -709,7 +705,7 @@ impl Context {
left_meta: SourceMetadata,
right: &mut Handle<Expression>,
right_meta: SourceMetadata,
) -> Result<(), ErrorKind> {
) -> Result<()> {
let left_components = self.expr_scalar_components(parser, *left, left_meta)?;
let right_components = self.expr_scalar_components(parser, *right, right_meta)?;
@@ -749,7 +745,7 @@ impl Context {
expr: &mut Handle<Expression>,
meta: SourceMetadata,
vector_size: Option<VectorSize>,
) -> Result<(), ErrorKind> {
) -> Result<()> {
let expr_type = parser.resolve_type(self, *expr, meta)?;
if let (&TypeInner::Scalar { .. }, Some(size)) = (expr_type, vector_size) {

View File

@@ -1,6 +1,6 @@
use super::{
constants::ConstantSolvingError,
token::{SourceMetadata, Token, TokenValue},
token::{SourceMetadata, TokenValue},
};
use pp_rs::token::PreprocessorError;
use std::borrow::Cow;
@@ -53,49 +53,46 @@ impl std::fmt::Display for ExpectedToken {
pub enum ErrorKind {
#[error("Unexpected end of file")]
EndOfFile,
#[error("Invalid profile: {1}")]
InvalidProfile(SourceMetadata, String),
#[error("Invalid version: {1}")]
InvalidVersion(SourceMetadata, u64),
#[error("Expected {}, found {0}", join_with_comma(.1))]
InvalidToken(Token, Vec<ExpectedToken>),
#[error("Not implemented: {1}")]
NotImplemented(SourceMetadata, &'static str),
#[error("Unknown variable: {1}")]
UnknownVariable(SourceMetadata, String),
#[error("Unknown type: {1}")]
UnknownType(SourceMetadata, String),
#[error("Unknown field: {1}")]
UnknownField(SourceMetadata, String),
#[error("Unknown layout qualifier: {1}")]
UnknownLayoutQualifier(SourceMetadata, String),
#[error("Invalid profile: {0}")]
InvalidProfile(String),
#[error("Invalid version: {0}")]
InvalidVersion(u64),
#[error("Expected {}, found {0:?}", join_with_comma(.1))]
InvalidToken(TokenValue, Vec<ExpectedToken>),
#[error("Not implemented: {0}")]
NotImplemented(&'static str),
#[error("Unknown variable: {0}")]
UnknownVariable(String),
#[error("Unknown type: {0}")]
UnknownType(String),
#[error("Unknown field: {0}")]
UnknownField(String),
#[error("Unknown layout qualifier: {0}")]
UnknownLayoutQualifier(String),
#[cfg(feature = "glsl-validate")]
#[error("Variable already declared: {1}")]
VariableAlreadyDeclared(SourceMetadata, String),
#[error("{1}")]
SemanticError(SourceMetadata, Cow<'static, str>),
#[error("{1:?}")]
PreprocessorError(SourceMetadata, PreprocessorError),
#[error("Variable already declared: {0}")]
VariableAlreadyDeclared(String),
#[error("{0}")]
SemanticError(Cow<'static, str>),
#[error("{0:?}")]
PreprocessorError(PreprocessorError),
}
impl ErrorKind {
/// Returns the TokenMetadata if available
pub fn metadata(&self) -> Option<SourceMetadata> {
match *self {
ErrorKind::UnknownVariable(metadata, _)
| ErrorKind::InvalidProfile(metadata, _)
| ErrorKind::InvalidVersion(metadata, _)
| ErrorKind::NotImplemented(metadata, _)
| ErrorKind::UnknownLayoutQualifier(metadata, _)
| ErrorKind::SemanticError(metadata, _)
| ErrorKind::UnknownField(metadata, _) => Some(metadata),
#[cfg(feature = "glsl-validate")]
ErrorKind::VariableAlreadyDeclared(metadata, _) => Some(metadata),
ErrorKind::InvalidToken(ref token, _) => Some(token.meta),
_ => None,
}
impl From<ConstantSolvingError> for ErrorKind {
fn from(err: ConstantSolvingError) -> Self {
ErrorKind::SemanticError(err.to_string().into())
}
}
#[derive(Debug, Error)]
#[error("{kind}")]
#[cfg_attr(test, derive(PartialEq))]
pub struct Error {
pub kind: ErrorKind,
pub meta: SourceMetadata,
}
impl Error {
pub(crate) fn wrong_function_args(
name: String,
expected: usize,
@@ -107,25 +104,9 @@ impl ErrorKind {
name, expected, got
);
ErrorKind::SemanticError(meta, msg.into())
}
}
impl From<(SourceMetadata, ConstantSolvingError)> for ErrorKind {
fn from((meta, err): (SourceMetadata, ConstantSolvingError)) -> Self {
ErrorKind::SemanticError(meta, err.to_string().into())
}
}
#[derive(Debug, Error)]
#[error("{kind}")]
#[cfg_attr(test, derive(PartialEq))]
pub struct ParseError {
pub kind: ErrorKind,
}
impl From<ErrorKind> for ParseError {
fn from(kind: ErrorKind) -> Self {
ParseError { kind }
Error {
kind: ErrorKind::SemanticError(msg.into()),
meta,
}
}
}

View File

@@ -2,9 +2,9 @@ use crate::{
front::glsl::{
ast::*,
context::Context,
error::ErrorKind,
error::{Error, ErrorKind},
types::{scalar_components, type_power},
Parser, SourceMetadata,
Parser, Result, SourceMetadata,
},
proc::ensure_block_returns,
Arena, BinaryOperator, Block, Constant, ConstantInner, EntryPoint, Expression, FastHashMap,
@@ -46,11 +46,11 @@ impl Parser {
fc: FunctionCallKind,
raw_args: &[Handle<HirExpr>],
meta: SourceMetadata,
) -> Result<Option<Handle<Expression>>, ErrorKind> {
) -> Result<Option<Handle<Expression>>> {
let args: Vec<_> = raw_args
.iter()
.map(|e| ctx.lower_expect(self, *e, false, body))
.collect::<Result<_, _>>()?;
.collect::<Result<_>>()?;
match fc {
FunctionCallKind::TypeConstructor(ty) => {
@@ -226,7 +226,14 @@ impl Parser {
},
body,
),
_ => return Err(ErrorKind::SemanticError(meta, "Bad cast".into())),
_ => {
self.errors.push(Error {
kind: ErrorKind::SemanticError("Bad cast".into()),
meta,
});
args[0].0
}
}
} else {
let mut components = Vec::with_capacity(args.len());
@@ -314,12 +321,12 @@ impl Parser {
mut args: Vec<(Handle<Expression>, SourceMetadata)>,
raw_args: &[Handle<HirExpr>],
meta: SourceMetadata,
) -> Result<Option<Handle<Expression>>, ErrorKind> {
) -> Result<Option<Handle<Expression>>> {
match name.as_str() {
"sampler1D" | "sampler1DArray" | "sampler2D" | "sampler2DArray" | "sampler2DMS"
| "sampler2DMSArray" | "sampler3D" | "samplerCube" | "samplerCubeArray" => {
if args.len() != 2 {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
ctx.samplers.insert(args[0].0, args[1].0);
Ok(Some(args[0].0))
@@ -331,16 +338,16 @@ impl Parser {
| "samplerCubeShadow"
| "samplerCubeArrayShadow" => {
if args.len() != 2 {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
sampled_to_depth(&mut self.module, ctx, args[0])?;
sampled_to_depth(&mut self.module, ctx, args[0], &mut self.errors)?;
self.invalidate_expression(ctx, args[0].0, args[0].1)?;
ctx.samplers.insert(args[0].0, args[1].0);
Ok(Some(args[0].0))
}
"texture" => {
if !(2..=3).contains(&args.len()) {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
let arg_1 = &mut args[1];
ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?;
@@ -366,12 +373,15 @@ impl Parser {
),
))
} else {
Err(ErrorKind::SemanticError(meta, "Bad call to texture".into()))
Err(Error {
kind: ErrorKind::SemanticError("Bad call to texture".into()),
meta,
})
}
}
"textureLod" => {
if args.len() != 3 {
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
return Err(Error::wrong_function_args(name, 3, args.len(), meta));
}
let arg_1 = &mut args[1];
ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?;
@@ -392,15 +402,15 @@ impl Parser {
body,
)))
} else {
Err(ErrorKind::SemanticError(
Err(Error {
kind: ErrorKind::SemanticError("Bad call to textureLod".into()),
meta,
"Bad call to textureLod".into(),
))
})
}
}
"textureProj" => {
if !(2..=3).contains(&args.len()) {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
let arg_1 = &mut args[1];
ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?;
@@ -413,10 +423,10 @@ impl Parser {
let size = match *self.resolve_type(ctx, args[1].0, args[1].1)? {
TypeInner::Vector { size, .. } => size,
_ => {
return Err(ErrorKind::SemanticError(
return Err(Error {
kind: ErrorKind::SemanticError("Bad call to textureProj".into()),
meta,
"Bad call to textureProj".into(),
))
})
}
};
let (base, base_meta) = args[1];
@@ -460,15 +470,15 @@ impl Parser {
body,
)))
} else {
Err(ErrorKind::SemanticError(
Err(Error {
kind: ErrorKind::SemanticError("Bad call to textureProj".into()),
meta,
"Bad call to textureProj".into(),
))
})
}
}
"textureGrad" => {
if args.len() != 4 {
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
return Err(Error::wrong_function_args(name, 3, args.len(), meta));
}
let arg_1 = &mut args[1];
ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?;
@@ -494,15 +504,15 @@ impl Parser {
body,
)))
} else {
Err(ErrorKind::SemanticError(
Err(Error {
kind: ErrorKind::SemanticError("Bad call to textureGrad".into()),
meta,
"Bad call to textureGrad".into(),
))
})
}
}
"textureSize" => {
if !(1..=2).contains(&args.len()) {
return Err(ErrorKind::wrong_function_args(name, 1, args.len(), meta));
return Err(Error::wrong_function_args(name, 1, args.len(), meta));
}
if let Some(&mut (ref mut expr, meta)) = args.get_mut(1) {
ctx.implicit_conversion(self, expr, meta, ScalarKind::Sint, 4)?;
@@ -519,7 +529,7 @@ impl Parser {
}
"texelFetch" => {
if args.len() != 3 {
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
return Err(Error::wrong_function_args(name, 3, args.len(), meta));
}
let arg_1 = &mut args[1];
ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Sint, 4)?;
@@ -537,10 +547,10 @@ impl Parser {
body,
)))
} else {
Err(ErrorKind::SemanticError(
Err(Error {
kind: ErrorKind::SemanticError("Bad call to texelFetch".into()),
meta,
"Bad call to texelFetch".into(),
))
})
}
}
"ceil" | "round" | "floor" | "fract" | "trunc" | "sin" | "abs" | "sqrt"
@@ -548,7 +558,7 @@ impl Parser {
| "sinh" | "cos" | "cosh" | "tan" | "tanh" | "acos" | "asin" | "log" | "log2"
| "length" | "determinant" | "bitCount" | "bitfieldReverse" => {
if args.len() != 1 {
return Err(ErrorKind::wrong_function_args(name, 1, args.len(), meta));
return Err(Error::wrong_function_args(name, 1, args.len(), meta));
}
Ok(Some(ctx.add_expression(
Expression::Math {
@@ -604,13 +614,13 @@ impl Parser {
arg1: Some(args[1].0),
arg2: None,
},
_ => return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta)),
_ => return Err(Error::wrong_function_args(name, 2, args.len(), meta)),
};
Ok(Some(ctx.add_expression(expr, body)))
}
"mod" => {
if args.len() != 2 {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
let (mut left, left_meta) = args[0];
@@ -629,7 +639,7 @@ impl Parser {
}
"min" | "max" => {
if args.len() != 2 {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
let (mut arg0, arg0_meta) = args[0];
@@ -661,7 +671,7 @@ impl Parser {
"pow" | "dot" | "reflect" | "cross" | "outerProduct" | "distance" | "step" | "modf"
| "frexp" | "ldexp" => {
if args.len() != 2 {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
let (mut arg0, arg0_meta) = args[0];
@@ -693,7 +703,7 @@ impl Parser {
}
"mix" => {
if args.len() != 3 {
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
return Err(Error::wrong_function_args(name, 3, args.len(), meta));
}
let (mut arg, arg_meta) = args[0];
@@ -763,7 +773,7 @@ impl Parser {
}
"clamp" => {
if args.len() != 3 {
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
return Err(Error::wrong_function_args(name, 3, args.len(), meta));
}
let (mut arg0, arg0_meta) = args[0];
@@ -794,7 +804,7 @@ impl Parser {
}
"faceforward" | "refract" | "fma" | "smoothstep" => {
if args.len() != 3 {
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
return Err(Error::wrong_function_args(name, 3, args.len(), meta));
}
Ok(Some(ctx.add_expression(
Expression::Math {
@@ -815,7 +825,7 @@ impl Parser {
"lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" | "equal"
| "notEqual" => {
if args.len() != 2 {
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
return Err(Error::wrong_function_args(name, 2, args.len(), meta));
}
Ok(Some(ctx.add_expression(
Expression::Binary {
@@ -848,8 +858,9 @@ impl Parser {
))
}
_ => {
let declarations = self.lookup_function.get(&name).ok_or_else(|| {
ErrorKind::SemanticError(meta, format!("Unknown function '{}'", name).into())
let declarations = self.lookup_function.get(&name).ok_or_else(|| Error {
kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()),
meta,
})?;
let mut maybe_decl = None;
@@ -866,7 +877,7 @@ impl Parser {
decl.parameters.iter().enumerate().zip(args.iter())
{
if decl.parameters_info[i].depth {
sampled_to_depth(&mut self.module, ctx, *call_arg)?;
sampled_to_depth(&mut self.module, ctx, *call_arg, &mut self.errors)?;
self.invalidate_expression(ctx, call_arg.0, call_arg.1)?
}
@@ -935,14 +946,17 @@ impl Parser {
}
if ambiguous {
return Err(ErrorKind::SemanticError(
self.errors.push(Error {
kind: ErrorKind::SemanticError(
format!("Ambiguous best function for '{}'", name).into(),
),
meta,
format!("Ambiguous best function for '{}'", name).into(),
));
})
}
let decl = maybe_decl.ok_or_else(|| {
ErrorKind::SemanticError(meta, format!("Unknown function '{}'", name).into())
let decl = maybe_decl.ok_or_else(|| Error {
kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()),
meta,
})?;
let parameters_info = decl.parameters_info.clone();
@@ -963,7 +977,7 @@ impl Parser {
*self.resolve_type(ctx, handle, meta)?
{
if parameter_info.qualifier.is_lhs()
&& matches!(*ctx.get_expression(handle), Expression::Swizzle { .. })
&& matches!(ctx[handle], Expression::Swizzle { .. })
{
let ty = self.module.types.fetch_or_append(Type {
name: None,
@@ -1047,9 +1061,9 @@ impl Parser {
args: &[(Handle<Expression>, SourceMetadata)],
fun: RelationalFunction,
meta: SourceMetadata,
) -> Result<Handle<Expression>, ErrorKind> {
) -> Result<Handle<Expression>> {
if args.len() != 1 {
return Err(ErrorKind::wrong_function_args(name, 1, args.len(), meta));
return Err(Error::wrong_function_args(name, 1, args.len(), meta));
}
Ok(ctx.add_expression(
@@ -1068,7 +1082,7 @@ impl Parser {
result: Option<FunctionResult>,
mut body: Block,
meta: SourceMetadata,
) -> Result<(), ErrorKind> {
) {
ensure_block_returns(&mut body);
let void = result.is_none();
@@ -1113,16 +1127,16 @@ impl Parser {
}
if decl.defined {
return Err(ErrorKind::SemanticError(
return self.errors.push(Error {
kind: ErrorKind::SemanticError("Function already defined".into()),
meta,
"Function already defined".into(),
));
});
}
decl.defined = true;
decl.parameters_info = parameters_info;
*self.module.functions.get_mut(decl.handle) = function;
return Ok(());
return;
}
let handle = module.functions.append(function);
@@ -1133,8 +1147,6 @@ impl Parser {
defined: true,
void,
});
Ok(())
}
pub fn add_prototype(
@@ -1143,7 +1155,7 @@ impl Parser {
name: String,
result: Option<FunctionResult>,
meta: SourceMetadata,
) -> Result<(), ErrorKind> {
) {
let void = result.is_none();
let &mut Parser {
@@ -1181,10 +1193,10 @@ impl Parser {
}
}
return Err(ErrorKind::SemanticError(
return self.errors.push(Error {
kind: ErrorKind::SemanticError("Prototype already defined".into()),
meta,
"Prototype already defined".into(),
));
});
}
let handle = module.functions.append(function);
@@ -1195,8 +1207,6 @@ impl Parser {
defined: false,
void,
});
Ok(())
}
pub fn add_entry_point(
@@ -1204,7 +1214,7 @@ impl Parser {
function: Handle<Function>,
mut global_init_body: Block,
mut expressions: Arena<Expression>,
) -> Result<(), ErrorKind> {
) {
let mut arguments = Vec::new();
let mut body = Block::with_capacity(
// global init body
@@ -1305,8 +1315,6 @@ impl Parser {
..Default::default()
},
});
Ok(())
}
/// Helper function for texture calls, splits the vector argument into it's components
@@ -1316,7 +1324,7 @@ impl Parser {
(image, image_meta): (Handle<Expression>, SourceMetadata),
(coord, coord_meta): (Handle<Expression>, SourceMetadata),
body: &mut Block,
) -> Result<CoordComponents, ErrorKind> {
) -> Result<CoordComponents> {
if let TypeInner::Image {
dim,
arrayed,
@@ -1377,10 +1385,16 @@ impl Parser {
array_index,
})
} else {
Err(ErrorKind::SemanticError(
image_meta,
"Type is not an image".into(),
))
self.errors.push(Error {
kind: ErrorKind::SemanticError("Type is not an image".into()),
meta: image_meta,
});
Ok(CoordComponents {
coordinate: coord,
depth_ref: None,
array_index: None,
})
}
}
}
@@ -1391,7 +1405,8 @@ fn sampled_to_depth(
module: &mut Module,
ctx: &mut Context,
(image, meta): (Handle<Expression>, SourceMetadata),
) -> Result<(), ErrorKind> {
errors: &mut Vec<Error>,
) -> Result<()> {
let ty = match ctx[image] {
Expression::GlobalVariable(handle) => &mut module.global_variables.get_mut(handle).ty,
Expression::FunctionArgument(i) => {
@@ -1399,10 +1414,10 @@ fn sampled_to_depth(
&mut ctx.arguments[i as usize].ty
}
_ => {
return Err(ErrorKind::SemanticError(
return Err(Error {
kind: ErrorKind::SemanticError("Not a valid texture expression".into()),
meta,
"Not a valid texture expression".into(),
))
})
}
};
match module.types[*ty].inner {
@@ -1422,9 +1437,15 @@ fn sampled_to_depth(
})
}
ImageClass::Depth { .. } => {}
_ => return Err(ErrorKind::SemanticError(meta, "Not a texture".into())),
_ => errors.push(Error {
kind: ErrorKind::SemanticError("Not a texture".into()),
meta,
}),
},
_ => return Err(ErrorKind::SemanticError(meta, "Not a texture".into())),
_ => errors.push(Error {
kind: ErrorKind::SemanticError("Not a texture".into()),
meta,
}),
};
Ok(())

View File

@@ -1,5 +1,5 @@
pub use ast::Profile;
pub use error::{ErrorKind, ParseError};
pub use error::{Error, ErrorKind};
pub use token::{SourceMetadata, Token};
use crate::{FastHashMap, FastHashSet, Handle, Module, ShaderStage, Type};
@@ -20,7 +20,7 @@ mod token;
mod types;
mod variables;
type Result<T> = std::result::Result<T, ErrorKind>;
type Result<T> = std::result::Result<T, Error>;
pub struct Options {
pub stage: ShaderStage,
@@ -74,7 +74,7 @@ pub struct Parser {
entry_args: Vec<EntryArg>,
errors: Vec<ParseError>,
errors: Vec<Error>,
module: Module,
}
@@ -97,14 +97,14 @@ impl Parser {
&mut self,
options: &Options,
source: &str,
) -> std::result::Result<Module, Vec<ParseError>> {
) -> std::result::Result<Module, Vec<Error>> {
self.reset(options.stage);
let lexer = lex::Lexer::new(source, &options.defines);
let mut ctx = ParsingContext::new(lexer);
if let Err(kind) = ctx.parse(self) {
self.errors.push(ParseError { kind });
if let Err(e) = ctx.parse(self) {
self.errors.push(e);
}
if self.errors.is_empty() {

View File

@@ -8,7 +8,11 @@
//! The OpenGl spec (the layout rules are defined by the OpenGl spec in section
//! 7.6.2.2 as opposed to the GLSL spec) uses the term basic machine units which are
//! equivalent to bytes.
use super::{ast::StructLayout, error::ErrorKind, SourceMetadata};
use super::{
ast::StructLayout,
error::{Error, ErrorKind},
SourceMetadata,
};
use crate::{Arena, Constant, Handle, Type, TypeInner};
/// Struct with information needed for defining a struct member.
@@ -37,7 +41,8 @@ pub fn calculate_offset(
layout: StructLayout,
types: &mut Arena<Type>,
constants: &Arena<Constant>,
) -> Result<TypeAlignSpan, ErrorKind> {
errors: &mut Vec<Error>,
) -> TypeAlignSpan {
// When using the std430 storage layout, shader storage blocks will be laid out in buffer storage
// identically to uniform and shader storage blocks using the std140 layout, except
// that the base alignment and stride of arrays of scalars and vectors in rule 4 and of
@@ -60,7 +65,7 @@ pub fn calculate_offset(
// to rules (1), (2), and (3), and rounded up to the base alignment of a vec4.
// TODO: Matrices array
TypeInner::Array { base, size, .. } => {
let info = calculate_offset(base, meta, layout, types, constants)?;
let info = calculate_offset(base, meta, layout, types, constants, errors);
let name = types[ty].name.clone();
let mut align = info.align;
@@ -122,7 +127,7 @@ pub fn calculate_offset(
let name = types[ty].name.clone();
for member in members.iter_mut() {
let info = calculate_offset(member.ty, meta, layout, types, constants)?;
let info = calculate_offset(member.ty, meta, layout, types, constants, errors);
span = align_up(span, info.align);
align = align.max(info.align);
@@ -145,14 +150,15 @@ pub fn calculate_offset(
(align, span)
}
_ => {
return Err(ErrorKind::SemanticError(
errors.push(Error {
kind: ErrorKind::SemanticError("Invalid struct member type".into()),
meta,
"Invalid struct member type".into(),
))
});
(0, 0)
}
};
Ok(TypeAlignSpan { ty, align, span })
TypeAlignSpan { ty, align, span }
}
/// Helper function used for aligning `value` to the next multiple of `align`

View File

@@ -9,7 +9,7 @@ use crate::{
token::{Directive, DirectiveKind},
token::{SourceMetadata, Token, TokenValue},
variables::{GlobalOrConstant, VarDeclaration},
ParseError, Parser, Result,
Error, Parser, Result,
},
Block, Constant, ConstantInner, Expression, ScalarValue, Type,
};
@@ -24,12 +24,14 @@ mod types;
pub struct ParsingContext<'source> {
lexer: Peekable<Lexer<'source>>,
last_meta: SourceMetadata,
}
impl<'source> ParsingContext<'source> {
pub fn new(lexer: Lexer<'source>) -> Self {
ParsingContext {
lexer: lexer.peekable(),
last_meta: SourceMetadata::none(),
}
}
@@ -38,10 +40,10 @@ impl<'source> ParsingContext<'source> {
match token.value {
TokenValue::Identifier(name) => Ok((name, token.meta)),
_ => Err(ErrorKind::InvalidToken(
token,
vec![ExpectedToken::Identifier],
)),
_ => Err(Error {
kind: ErrorKind::InvalidToken(token.value, vec![ExpectedToken::Identifier]),
meta: token.meta,
}),
}
}
@@ -49,7 +51,10 @@ impl<'source> ParsingContext<'source> {
let token = self.bump(parser)?;
if token.value != value {
Err(ErrorKind::InvalidToken(token, vec![value.into()]))
Err(Error {
kind: ErrorKind::InvalidToken(token.value, vec![value.into()]),
meta: token.meta,
})
} else {
Ok(token)
}
@@ -60,19 +65,26 @@ impl<'source> ParsingContext<'source> {
let res = self.lexer.next()?;
match res.kind {
LexerResultKind::Token(token) => break Some(token),
LexerResultKind::Token(token) => {
self.last_meta = token.meta;
break Some(token);
}
LexerResultKind::Directive(directive) => {
parser.handle_directive(directive, res.meta)
}
LexerResultKind::Error(error) => parser.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(res.meta, error),
LexerResultKind::Error(error) => parser.errors.push(Error {
kind: ErrorKind::PreprocessorError(error),
meta: res.meta,
}),
}
}
}
pub fn bump(&mut self, parser: &mut Parser) -> Result<Token> {
self.next(parser).ok_or(ErrorKind::EndOfFile)
self.next(parser).ok_or(Error {
kind: ErrorKind::EndOfFile,
meta: self.last_meta,
})
}
/// Returns None on the end of the file rather than an error like other methods
@@ -101,8 +113,9 @@ impl<'source> ParsingContext<'source> {
LexerResultKind::Directive(directive) => {
parser.handle_directive(directive, res.meta)
}
LexerResultKind::Error(error) => parser.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(res.meta, error),
LexerResultKind::Error(error) => parser.errors.push(Error {
kind: ErrorKind::PreprocessorError(error),
meta: res.meta,
}),
_ => unreachable!(),
}
@@ -113,7 +126,11 @@ impl<'source> ParsingContext<'source> {
}
pub fn expect_peek(&mut self, parser: &mut Parser) -> Result<&Token> {
self.peek(parser).ok_or(ErrorKind::EndOfFile)
let meta = self.last_meta;
self.peek(parser).ok_or(Error {
kind: ErrorKind::EndOfFile,
meta,
})
}
pub fn parse(&mut self, parser: &mut Parser) -> Result<()> {
@@ -125,20 +142,18 @@ impl<'source> ParsingContext<'source> {
self.parse_external_declaration(parser, &mut ctx, &mut body)?;
}
let handle = parser
.lookup_function
.get("main")
.and_then(|declarations| {
declarations
.iter()
.find(|decl| decl.defined && decl.parameters.is_empty())
.map(|decl| decl.handle)
})
.ok_or_else(|| {
ErrorKind::SemanticError(SourceMetadata::default(), "Missing entry point".into())
})?;
parser.add_entry_point(handle, body, ctx.expressions)?;
match parser.lookup_function.get("main").and_then(|declarations| {
declarations
.iter()
.find(|decl| decl.defined && decl.parameters.is_empty())
.map(|decl| decl.handle)
}) {
Some(handle) => parser.add_entry_point(handle, body, ctx.expressions),
None => parser.errors.push(Error {
kind: ErrorKind::SemanticError("Missing entry point".into()),
meta: SourceMetadata::none(),
}),
}
Ok(())
}
@@ -150,18 +165,24 @@ impl<'source> ParsingContext<'source> {
ConstantInner::Scalar {
value: ScalarValue::Uint(int),
..
} => u32::try_from(int)
.map_err(|_| ErrorKind::SemanticError(meta, "int constant overflows".into())),
} => u32::try_from(int).map_err(|_| Error {
kind: ErrorKind::SemanticError("int constant overflows".into()),
meta,
})?,
ConstantInner::Scalar {
value: ScalarValue::Sint(int),
..
} => u32::try_from(int)
.map_err(|_| ErrorKind::SemanticError(meta, "int constant overflows".into())),
_ => Err(ErrorKind::SemanticError(
} => u32::try_from(int).map_err(|_| Error {
kind: ErrorKind::SemanticError("int constant overflows".into()),
meta,
"Expected a uint constant".into(),
)),
}?;
})?,
_ => {
return Err(Error {
kind: ErrorKind::SemanticError("Expected a uint constant".into()),
meta,
})
}
};
Ok((int, meta))
}
@@ -188,11 +209,11 @@ impl Parser {
match directive.kind {
DirectiveKind::Version { is_first_directive } => {
if !is_first_directive {
self.errors.push(ParseError {
self.errors.push(Error {
kind: ErrorKind::SemanticError(
meta,
"#version must occur first in shader".into(),
),
meta,
})
}
@@ -202,21 +223,20 @@ impl Parser {
location,
}) => match int.value {
440 | 450 | 460 => self.meta.version = int.value as u16,
_ => self.errors.push(ParseError {
kind: ErrorKind::InvalidVersion(location.into(), int.value),
_ => self.errors.push(Error {
kind: ErrorKind::InvalidVersion(int.value),
meta: location.into(),
}),
},
Some(PPToken { value, location }) => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
Some(PPToken { value, location }) => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
}),
None => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
meta,
PreprocessorError::UnexpectedNewLine,
),
None => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedNewLine),
meta,
}),
};
@@ -226,25 +246,26 @@ impl Parser {
location,
}) => match name.as_str() {
"core" => self.meta.profile = Profile::Core,
_ => self.errors.push(ParseError {
kind: ErrorKind::InvalidProfile(location.into(), name),
_ => self.errors.push(Error {
kind: ErrorKind::InvalidProfile(name),
meta: location.into(),
}),
},
Some(PPToken { value, location }) => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
Some(PPToken { value, location }) => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
}),
None => {}
};
if let Some(PPToken { value, location }) = tokens.next() {
self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
})
}
}
@@ -259,21 +280,21 @@ impl Parser {
..
}) => Some(name),
Some(PPToken { value, location }) => {
self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
});
None
}
None => {
self.errors.push(ParseError {
self.errors.push(Error {
kind: ErrorKind::PreprocessorError(
meta,
PreprocessorError::UnexpectedNewLine,
),
meta,
});
None
@@ -285,17 +306,15 @@ impl Parser {
value: PPTokenValue::Punct(pp_rs::token::Punct::Colon),
..
}) => {}
Some(PPToken { value, location }) => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
Some(PPToken { value, location }) => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
}),
None => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
meta,
PreprocessorError::UnexpectedNewLine,
),
None => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedNewLine),
meta,
}),
};
@@ -309,33 +328,31 @@ impl Parser {
self.meta.extensions.insert(name);
}
}
_ => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(PPTokenValue::Ident(behavior)),
),
_ => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
PPTokenValue::Ident(behavior),
)),
meta: location.into(),
}),
},
Some(PPToken { value, location }) => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
Some(PPToken { value, location }) => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
}),
None => self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
meta,
PreprocessorError::UnexpectedNewLine,
),
None => self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedNewLine),
meta,
}),
}
if let Some(PPToken { value, location }) = tokens.next() {
self.errors.push(ParseError {
kind: ErrorKind::PreprocessorError(
location.into(),
PreprocessorError::UnexpectedToken(value),
),
self.errors.push(Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedToken(
value,
)),
meta: location.into(),
})
}
}

View File

@@ -10,7 +10,7 @@ use crate::{
token::TokenValue,
types::scalar_components,
variables::{GlobalOrConstant, VarDeclaration},
ErrorKind, Parser, SourceMetadata, Token,
Error, ErrorKind, Parser, SourceMetadata, Token,
},
Block, Expression, FunctionResult, Handle, ScalarKind, Statement, StorageClass, StructMember,
Type, TypeInner,
@@ -34,7 +34,10 @@ impl<'source> ParsingContext<'source> {
460 => vec![TokenValue::Semicolon.into(), ExpectedToken::Eof],
_ => vec![ExpectedToken::Eof],
};
Err(ErrorKind::InvalidToken(token, expected))
Err(Error {
kind: ErrorKind::InvalidToken(token.value, expected),
meta: token.meta,
})
}
}
} else {
@@ -79,10 +82,13 @@ impl<'source> ParsingContext<'source> {
break;
}
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![TokenValue::Comma.into(), TokenValue::RightBrace.into()],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![TokenValue::Comma.into(), TokenValue::RightBrace.into()],
),
meta: token.meta,
})
}
}
}
@@ -147,10 +153,13 @@ impl<'source> ParsingContext<'source> {
TokenValue::Semicolon => break,
TokenValue::Identifier(name) => name,
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![ExpectedToken::Identifier, TokenValue::Semicolon.into()],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![ExpectedToken::Identifier, TokenValue::Semicolon.into()],
),
meta: token.meta,
})
}
};
let mut meta = token.meta;
@@ -201,10 +210,13 @@ impl<'source> ParsingContext<'source> {
TokenValue::Semicolon => break,
TokenValue::Comma => {}
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![TokenValue::Comma.into(), TokenValue::Semicolon.into()],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![TokenValue::Comma.into(), TokenValue::Semicolon.into()],
),
meta: token.meta,
})
}
}
}
@@ -261,7 +273,7 @@ impl<'source> ParsingContext<'source> {
return match token.value {
TokenValue::Semicolon => {
// This branch handles function prototypes
parser.add_prototype(context, name, result, meta)?;
parser.add_prototype(context, name, result, meta);
Ok(true)
}
@@ -273,21 +285,27 @@ impl<'source> ParsingContext<'source> {
// parse the body
self.parse_compound_statement(parser, &mut context, &mut body)?;
parser.add_function(context, name, result, body, meta)?;
parser.add_function(context, name, result, body, meta);
Ok(true)
}
_ if external => Err(ErrorKind::InvalidToken(
token,
vec![
TokenValue::LeftBrace.into(),
TokenValue::Semicolon.into(),
],
)),
_ => Err(ErrorKind::InvalidToken(
token,
vec![TokenValue::Semicolon.into()],
)),
_ if external => Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![
TokenValue::LeftBrace.into(),
TokenValue::Semicolon.into(),
],
),
meta: token.meta,
}),
_ => Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![TokenValue::Semicolon.into()],
),
meta: token.meta,
}),
};
}
// Pass the token to the init_declator_list parser
@@ -313,10 +331,10 @@ impl<'source> ParsingContext<'source> {
self.parse_init_declarator_list(parser, ty, Some(token_fallthrough), &mut ctx)?;
} else {
return Err(ErrorKind::SemanticError(
parser.errors.push(Error {
kind: ErrorKind::SemanticError("Declaration cannot have void type".into()),
meta,
"Declaration cannot have void type".into(),
));
})
}
Ok(true)
@@ -341,7 +359,10 @@ impl<'source> ParsingContext<'source> {
//TODO: declaration
// type_qualifier IDENTIFIER SEMICOLON
// type_qualifier IDENTIFIER identifier_list SEMICOLON
Err(ErrorKind::NotImplemented(token.meta, "variable qualifier"))
Err(Error {
kind: ErrorKind::NotImplemented("variable qualifier"),
meta: token.meta,
})
}
}
TokenValue::Semicolon => {
@@ -359,20 +380,25 @@ impl<'source> ParsingContext<'source> {
// layout(early_fragment_tests) in;
}
_ => {
return Err(ErrorKind::SemanticError(
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
"Qualifier not supported as standalone".into(),
),
meta,
"Qualifier not supported as standalone".into(),
));
});
}
}
}
Ok(true)
}
_ => Err(ErrorKind::InvalidToken(
token,
vec![ExpectedToken::Identifier, TokenValue::Semicolon.into()],
)),
_ => Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![ExpectedToken::Identifier, TokenValue::Semicolon.into()],
),
meta: token.meta,
}),
}
}
} else {
@@ -385,14 +411,17 @@ impl<'source> ParsingContext<'source> {
let _ = match token.value {
TokenValue::PrecisionQualifier(p) => p,
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![
TokenValue::PrecisionQualifier(Precision::High).into(),
TokenValue::PrecisionQualifier(Precision::Medium).into(),
TokenValue::PrecisionQualifier(Precision::Low).into(),
],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![
TokenValue::PrecisionQualifier(Precision::High).into(),
TokenValue::PrecisionQualifier(Precision::Medium).into(),
TokenValue::PrecisionQualifier(Precision::Low).into(),
],
),
meta: token.meta,
})
}
};
@@ -407,12 +436,12 @@ impl<'source> ParsingContext<'source> {
kind: ScalarKind::Sint,
..
} => {}
_ => {
return Err(ErrorKind::SemanticError(
meta,
_ => parser.errors.push(Error {
kind: ErrorKind::SemanticError(
"Precision statement can only work on floats and ints".into(),
))
}
),
meta,
}),
}
self.expect(parser, TokenValue::Semicolon)?;
@@ -485,10 +514,13 @@ impl<'source> ParsingContext<'source> {
Some(name)
}
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![ExpectedToken::Identifier, TokenValue::Semicolon.into()],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![ExpectedToken::Identifier, TokenValue::Semicolon.into()],
),
meta: token.meta,
})
}
};
meta = meta.union(&token.meta);
@@ -555,7 +587,8 @@ impl<'source> ParsingContext<'source> {
layout,
&mut parser.module.types,
&parser.module.constants,
)?;
&mut parser.errors,
);
span = offset::align_up(span, info.align);
align = align.max(info.align);

View File

@@ -5,7 +5,7 @@ use crate::{
error::{ErrorKind, ExpectedToken},
parser::ParsingContext,
token::{Token, TokenValue},
Parser, Result, SourceMetadata,
Error, Parser, Result, SourceMetadata,
},
ArraySize, BinaryOperator, Block, Constant, ConstantInner, Handle, ScalarValue, Type,
TypeInner, UnaryOperator,
@@ -43,15 +43,18 @@ impl<'source> ParsingContext<'source> {
return Ok(expr);
}
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![
TokenValue::LeftParen.into(),
ExpectedToken::IntLiteral,
ExpectedToken::FloatLiteral,
ExpectedToken::BoolLiteral,
],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![
TokenValue::LeftParen.into(),
ExpectedToken::IntLiteral,
ExpectedToken::FloatLiteral,
ExpectedToken::BoolLiteral,
],
),
meta: token.meta,
});
}
};
@@ -89,10 +92,13 @@ impl<'source> ParsingContext<'source> {
break;
}
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![TokenValue::Comma.into(), TokenValue::RightParen.into()],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![TokenValue::Comma.into(), TokenValue::RightParen.into()],
),
meta: token.meta,
});
}
}
}
@@ -124,9 +130,14 @@ impl<'source> ParsingContext<'source> {
meta,
}
} else {
let var = match parser.lookup_variable(ctx, body, &name)? {
let var = match parser.lookup_variable(ctx, body, &name) {
Some(var) => var,
None => return Err(ErrorKind::UnknownVariable(meta, name)),
None => {
return Err(Error {
kind: ErrorKind::UnknownVariable(name),
meta,
})
}
};
HirExpr {

View File

@@ -1,7 +1,7 @@
use crate::{
front::glsl::{
ast::ParameterQualifier, context::Context, parser::ParsingContext, token::TokenValue,
variables::VarDeclaration, ErrorKind, Parser, Result, Token,
variables::VarDeclaration, Error, ErrorKind, Parser, Result, Token,
},
Block, ConstantInner, Expression, ScalarValue, Statement, SwitchCase, UnaryOperator,
};
@@ -147,10 +147,14 @@ impl<'source> ParsingContext<'source> {
..
} => int as i32,
_ => {
return Err(ErrorKind::SemanticError(
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
"Case values can only be integers".into(),
),
meta,
"Case values can only be integers".into(),
))
});
0
}
}
};
@@ -189,10 +193,13 @@ impl<'source> ParsingContext<'source> {
self.expect(parser, TokenValue::Colon)?;
if !default.is_empty() {
return Err(ErrorKind::SemanticError(
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
"Can only have one default case per switch statement"
.into(),
),
meta,
"Can only have one default case per switch statement".into(),
));
});
}
loop {
@@ -214,14 +221,18 @@ impl<'source> ParsingContext<'source> {
break;
}
_ => {
return Err(ErrorKind::InvalidToken(
self.bump(parser)?,
vec![
TokenValue::Case.into(),
TokenValue::Default.into(),
TokenValue::RightBrace.into(),
],
))
let Token { value, meta } = self.bump(parser)?;
return Err(Error {
kind: ErrorKind::InvalidToken(
value,
vec![
TokenValue::Case.into(),
TokenValue::Default.into(),
TokenValue::RightBrace.into(),
],
),
meta,
});
}
}
}

View File

@@ -4,9 +4,9 @@ use crate::{
error::ExpectedToken,
parser::ParsingContext,
token::{SourceMetadata, TokenValue},
ErrorKind, Parser, Result,
Error, ErrorKind, Parser, Result,
},
ArraySize, Handle, ResourceBinding, StorageClass, Type, TypeInner,
ArraySize, Handle, StorageClass, Type, TypeInner,
};
impl<'source> ParsingContext<'source> {
@@ -55,17 +55,25 @@ impl<'source> ParsingContext<'source> {
}
TokenValue::Identifier(ident) => match parser.lookup_type.get(&ident) {
Some(ty) => Some(*ty),
None => return Err(ErrorKind::UnknownType(token.meta, ident)),
None => {
return Err(Error {
kind: ErrorKind::UnknownType(ident),
meta: token.meta,
})
}
},
_ => {
return Err(ErrorKind::InvalidToken(
token,
vec![
TokenValue::Void.into(),
TokenValue::Struct.into(),
ExpectedToken::TypeName,
],
))
return Err(Error {
kind: ErrorKind::InvalidToken(
token.value,
vec![
TokenValue::Void.into(),
TokenValue::Struct.into(),
ExpectedToken::TypeName,
],
),
meta: token.meta,
});
}
};
@@ -78,8 +86,10 @@ impl<'source> ParsingContext<'source> {
parser: &mut Parser,
) -> Result<(Handle<Type>, SourceMetadata)> {
let (maybe_ty, meta) = self.parse_type(parser)?;
let ty =
maybe_ty.ok_or_else(|| ErrorKind::SemanticError(meta, "Type can't be void".into()))?;
let ty = maybe_ty.ok_or_else(|| Error {
kind: ErrorKind::SemanticError("Type can't be void".into()),
meta,
})?;
Ok((ty, meta))
}
@@ -148,13 +158,9 @@ impl<'source> ParsingContext<'source> {
parser: &mut Parser,
qualifiers: &mut Vec<(TypeQualifier, SourceMetadata)>,
) -> Result<()> {
// We need both of these to produce a ResourceBinding
let mut group = None;
let mut binding = None;
self.expect(parser, TokenValue::LeftParen)?;
loop {
self.parse_layout_qualifier_id(parser, qualifiers, &mut group, &mut binding)?;
self.parse_layout_qualifier_id(parser, qualifiers)?;
if self.bump_if(parser, TokenValue::Comma).is_some() {
continue;
@@ -164,27 +170,6 @@ impl<'source> ParsingContext<'source> {
}
self.expect(parser, TokenValue::RightParen)?;
match (group, binding) {
(Some((group, group_meta)), Some((binding, binding_meta))) => qualifiers.push((
TypeQualifier::ResourceBinding(ResourceBinding { group, binding }),
group_meta.union(&binding_meta),
)),
// Produce an error if we have one of group or binding but not the other
(Some((_, meta)), None) => {
return Err(ErrorKind::SemanticError(
meta,
"set specified with no binding".into(),
))
}
(None, Some((_, meta))) => {
return Err(ErrorKind::SemanticError(
meta,
"binding specified with no set".into(),
))
}
(None, None) => (),
}
Ok(())
}
@@ -192,8 +177,6 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
qualifiers: &mut Vec<(TypeQualifier, SourceMetadata)>,
group: &mut Option<(u32, SourceMetadata)>,
binding: &mut Option<(u32, SourceMetadata)>,
) -> Result<()> {
// layout_qualifier_id:
// IDENTIFIER
@@ -209,52 +192,60 @@ impl<'source> ParsingContext<'source> {
qualifiers.push((
match name.as_str() {
"location" => TypeQualifier::Location(value),
"set" => {
*group = Some((value, end_meta));
return Ok(());
}
"binding" => {
*binding = Some((value, end_meta));
return Ok(());
}
"set" => TypeQualifier::Set(value),
"binding" => TypeQualifier::Binding(value),
"local_size_x" => TypeQualifier::WorkGroupSize(0, value),
"local_size_y" => TypeQualifier::WorkGroupSize(1, value),
"local_size_z" => TypeQualifier::WorkGroupSize(2, value),
_ => return Err(ErrorKind::UnknownLayoutQualifier(token.meta, name)),
_ => {
parser.errors.push(Error {
kind: ErrorKind::UnknownLayoutQualifier(name),
meta: token.meta,
});
return Ok(());
}
},
token.meta,
))
} else {
match name.as_str() {
"push_constant" => {
qualifiers.push((
TypeQualifier::StorageQualifier(StorageQualifier::StorageClass(
StorageClass::PushConstant,
)),
token.meta,
));
qualifiers
.push((TypeQualifier::Layout(StructLayout::Std430), token.meta));
}
"std140" => qualifiers
.push((TypeQualifier::Layout(StructLayout::Std140), token.meta)),
"std430" => qualifiers
.push((TypeQualifier::Layout(StructLayout::Std430), token.meta)),
"early_fragment_tests" => {
qualifiers.push((TypeQualifier::EarlyFragmentTests, token.meta))
}
_ => return Err(ErrorKind::UnknownLayoutQualifier(token.meta, name)),
}
qualifiers.push((
match name.as_str() {
"push_constant" => {
qualifiers.push((
TypeQualifier::Layout(StructLayout::Std430),
token.meta,
));
qualifiers.push((
TypeQualifier::StorageQualifier(
StorageQualifier::StorageClass(StorageClass::PushConstant),
),
token.meta,
));
return Ok(());
}
"std140" => TypeQualifier::Layout(StructLayout::Std140),
"std430" => TypeQualifier::Layout(StructLayout::Std430),
"early_fragment_tests" => TypeQualifier::EarlyFragmentTests,
_ => {
parser.errors.push(Error {
kind: ErrorKind::UnknownLayoutQualifier(name),
meta: token.meta,
});
return Ok(());
}
},
token.meta,
));
};
Ok(())
}
// TODO: handle Shared?
_ => Err(ErrorKind::InvalidToken(
token,
vec![ExpectedToken::Identifier],
)),
_ => parser.errors.push(Error {
kind: ErrorKind::InvalidToken(token.value, vec![ExpectedToken::Identifier]),
meta: token.meta,
}),
}
Ok(())
}
pub fn peek_type_name(&mut self, parser: &mut Parser) -> bool {

View File

@@ -2,15 +2,15 @@ use crate::{
front::glsl::{
ast::Profile,
error::ExpectedToken,
error::{ErrorKind, ParseError},
error::{Error, ErrorKind},
token::TokenValue,
Options, Parser, SourceMetadata, Token,
Options, Parser, SourceMetadata,
},
Module, ShaderStage,
};
use pp_rs::token::PreprocessorError;
fn parse(parser: &mut Parser, source: &str, stage: ShaderStage) -> Result<Module, Vec<ParseError>> {
fn parse(parser: &mut Parser, source: &str, stage: ShaderStage) -> Result<Module, Vec<Error>> {
let defines = crate::FastHashMap::default();
parser.parse(&Options { stage, defines }, source)
@@ -29,8 +29,9 @@ fn version() {
)
.err()
.unwrap(),
vec![ParseError {
kind: ErrorKind::InvalidVersion(SourceMetadata { start: 9, end: 14 }, 99000)
vec![Error {
kind: ErrorKind::InvalidVersion(99000),
meta: SourceMetadata { start: 9, end: 14 }
}],
);
@@ -42,8 +43,9 @@ fn version() {
)
.err()
.unwrap(),
vec![ParseError {
kind: ErrorKind::InvalidVersion(SourceMetadata { start: 9, end: 12 }, 449)
vec![Error {
kind: ErrorKind::InvalidVersion(449),
meta: SourceMetadata { start: 9, end: 12 }
}]
);
@@ -55,8 +57,9 @@ fn version() {
)
.err()
.unwrap(),
vec![ParseError {
kind: ErrorKind::InvalidProfile(SourceMetadata { start: 13, end: 18 }, "smart".into())
vec![Error {
kind: ErrorKind::InvalidProfile("smart".into()),
meta: SourceMetadata { start: 13, end: 18 },
}]
);
@@ -69,20 +72,16 @@ fn version() {
.err()
.unwrap(),
vec![
ParseError {
kind: ErrorKind::PreprocessorError(
SourceMetadata { start: 27, end: 28 },
PreprocessorError::UnexpectedHash,
)
Error {
kind: ErrorKind::PreprocessorError(PreprocessorError::UnexpectedHash,),
meta: SourceMetadata { start: 27, end: 28 },
},
ParseError {
Error {
kind: ErrorKind::InvalidToken(
Token {
value: TokenValue::Identifier("version".into()),
meta: SourceMetadata { start: 28, end: 35 }
},
TokenValue::Identifier("version".into()),
vec![ExpectedToken::Eof]
)
),
meta: SourceMetadata { start: 28, end: 35 }
}
]
);
@@ -256,7 +255,7 @@ fn declarations() {
&mut parser,
r#"
#version 450
layout(push_constant, set = 2, binding = 0)
layout(push_constant)
uniform u_locals {
vec3 model_offs;
float load_time;
@@ -455,14 +454,12 @@ fn functions() {
)
.err()
.unwrap(),
vec![ParseError {
kind: ErrorKind::SemanticError(
SourceMetadata {
start: 134,
end: 152
},
"Function already defined".into()
)
vec![Error {
kind: ErrorKind::SemanticError("Function already defined".into()),
meta: SourceMetadata {
start: 134,
end: 152
},
}]
);
@@ -616,14 +613,12 @@ fn implicit_conversions() {
)
.err()
.unwrap(),
vec![ParseError {
kind: ErrorKind::SemanticError(
SourceMetadata {
start: 156,
end: 165
},
"Unknown function \'test\'".into()
)
vec![Error {
kind: ErrorKind::SemanticError("Unknown function \'test\'".into()),
meta: SourceMetadata {
start: 156,
end: 165
},
}]
);
@@ -643,14 +638,12 @@ fn implicit_conversions() {
)
.err()
.unwrap(),
vec![ParseError {
kind: ErrorKind::SemanticError(
SourceMetadata {
start: 158,
end: 165
},
"Ambiguous best function for \'test\'".into()
)
vec![Error {
kind: ErrorKind::SemanticError("Ambiguous best function for \'test\'".into()),
meta: SourceMetadata {
start: 158,
end: 165
},
}]
);
}

View File

@@ -3,7 +3,7 @@ pub use pp_rs::token::{Float, Integer, PreprocessorError, Token as PPToken};
use super::ast::Precision;
use crate::{Interpolation, Sampling, Type};
use std::{fmt, ops::Range};
use std::ops::Range;
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(test, derive(PartialEq))]
@@ -22,6 +22,10 @@ impl SourceMetadata {
end: self.end.max(other.end),
}
}
pub fn none() -> Self {
SourceMetadata::default()
}
}
impl From<Location> for SourceMetadata {
@@ -141,12 +145,6 @@ pub enum TokenValue {
Question,
}
impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.value)
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub struct Directive {

View File

@@ -1,6 +1,7 @@
use crate::{
front::glsl::{
constants::ConstantSolver, context::Context, ErrorKind, Parser, Result, SourceMetadata,
constants::ConstantSolver, context::Context, Error, ErrorKind, Parser, Result,
SourceMetadata,
},
proc::ResolveContext,
ArraySize, Constant, Expression, Handle, ImageClass, ImageDimension, ScalarKind, Type,
@@ -197,8 +198,9 @@ impl Parser {
ctx.typifier
.grow(handle, &ctx.expressions, &resolve_ctx)
.map_err(|error| {
ErrorKind::SemanticError(meta, format!("Can't resolve type: {:?}", error).into())
.map_err(|error| Error {
kind: ErrorKind::SemanticError(format!("Can't resolve type: {:?}", error).into()),
meta,
})
}
@@ -230,8 +232,9 @@ impl Parser {
ctx.typifier
.invalidate(handle, &ctx.expressions, &resolve_ctx)
.map_err(|error| {
ErrorKind::SemanticError(meta, format!("Can't resolve type: {:?}", error).into())
.map_err(|error| Error {
kind: ErrorKind::SemanticError(format!("Can't resolve type: {:?}", error).into()),
meta,
})
}
@@ -247,7 +250,10 @@ impl Parser {
constants: &mut self.module.constants,
};
solver.solve(root).map_err(|e| (meta, e).into())
solver.solve(root).map_err(|e| Error {
kind: e.into(),
meta,
})
}
pub fn maybe_array(&mut self, base: Handle<Type>, size: Option<ArraySize>) -> Handle<Type> {

View File

@@ -1,14 +1,22 @@
use crate::{
front::glsl::{ast::*, context::Context, error::ErrorKind, Parser, SourceMetadata},
front::glsl::{
ast::*,
context::Context,
error::{Error, ErrorKind},
Parser, Result, SourceMetadata,
},
Binding, Block, BuiltIn, Constant, Expression, GlobalVariable, Handle, Interpolation,
LocalVariable, ScalarKind, StorageAccess, StorageClass, SwizzleComponent, Type, TypeInner,
VectorSize,
LocalVariable, ResourceBinding, ScalarKind, StorageAccess, StorageClass, SwizzleComponent,
Type, TypeInner, VectorSize,
};
macro_rules! qualifier_arm {
($src:expr, $tgt:expr, $meta:expr, $msg:literal $(,)?) => {{
($src:expr, $tgt:expr, $meta:expr, $msg:literal, $errors:expr $(,)?) => {{
if $tgt.is_some() {
return Err(ErrorKind::SemanticError($meta, $msg.into()));
$errors.push(Error {
kind: ErrorKind::SemanticError($msg.into()),
meta: $meta,
})
}
$tgt = Some($src);
@@ -34,12 +42,12 @@ impl Parser {
ctx: &mut Context,
body: &mut Block,
name: &str,
) -> Result<Option<VariableReference>, ErrorKind> {
) -> Option<VariableReference> {
if let Some(local_var) = ctx.lookup_local_var(name) {
return Ok(Some(local_var));
return Some(local_var);
}
if let Some(global_var) = ctx.lookup_global_var(name) {
return Ok(Some(global_var));
return Some(global_var);
}
let mut add_builtin = |inner, builtin, mutable, storage| {
@@ -84,7 +92,7 @@ impl Parser {
},
);
Ok(ctx.lookup_global_var(name))
ctx.lookup_global_var(name)
};
match name {
"gl_Position" => add_builtin(
@@ -162,7 +170,7 @@ impl Parser {
false,
StorageQualifier::Input,
),
_ => Ok(None),
_ => None,
}
}
@@ -174,7 +182,7 @@ impl Parser {
expression: Handle<Expression>,
name: &str,
meta: SourceMetadata,
) -> Result<Handle<Expression>, ErrorKind> {
) -> Result<Handle<Expression>> {
let (ty, is_pointer) = match *self.resolve_type(ctx, expression, meta)? {
TypeInner::Pointer { base, .. } => (&self.module.types[base].inner, true),
ref ty => (ty, false),
@@ -184,7 +192,10 @@ impl Parser {
let index = members
.iter()
.position(|m| m.name == Some(name.into()))
.ok_or_else(|| ErrorKind::UnknownField(meta, name.into()))?;
.ok_or_else(|| Error {
kind: ErrorKind::UnknownField(name.into()),
meta,
})?;
Ok(ctx.add_expression(
Expression::AccessIndex {
base: expression,
@@ -215,14 +226,17 @@ impl Parser {
let not_unique = (1..components.len())
.any(|i| components[i..].contains(&components[i - 1]));
if not_unique {
return Err(ErrorKind::SemanticError(
meta,
self.errors.push(Error {
kind:
ErrorKind::SemanticError(
format!(
"swizzle cannot have duplicate components in left-hand-side expression for \"{:?}\"",
name
)
.into(),
));
),
meta ,
})
}
}
@@ -237,7 +251,7 @@ impl Parser {
size: _,
vector,
pattern: ref src_pattern,
} = *ctx.get_expression(expression)
} = ctx[expression]
{
expression = vector;
for pat in &mut pattern {
@@ -250,9 +264,7 @@ impl Parser {
// only single element swizzle, like pos.y, just return that component.
if lhs {
// Because of possible nested swizzles, like pos.xy.x, we have to unwrap the potential load expr.
if let Expression::Load { ref pointer } =
*ctx.get_expression(expression)
{
if let Expression::Load { ref pointer } = ctx[expression] {
expression = *pointer;
}
}
@@ -268,10 +280,14 @@ impl Parser {
3 => VectorSize::Tri,
4 => VectorSize::Quad,
_ => {
return Err(ErrorKind::SemanticError(
self.errors.push(Error {
kind: ErrorKind::SemanticError(
format!("Bad swizzle size for \"{:?}\"", name).into(),
),
meta,
format!("Bad swizzle size for \"{:?}\"", name).into(),
));
});
VectorSize::Quad
}
};
@@ -296,16 +312,20 @@ impl Parser {
body,
))
} else {
Err(ErrorKind::SemanticError(
Err(Error {
kind: ErrorKind::SemanticError(
format!("Invalid swizzle for vector \"{}\"", name).into(),
),
meta,
format!("Invalid swizzle for vector \"{}\"", name).into(),
))
})
}
}
_ => Err(ErrorKind::SemanticError(
_ => Err(Error {
kind: ErrorKind::SemanticError(
format!("Can't lookup field on this type \"{}\"", name).into(),
),
meta,
format!("Can't lookup field on this type \"{}\"", name).into(),
)),
}),
}
}
@@ -320,9 +340,10 @@ impl Parser {
init,
meta,
}: VarDeclaration,
) -> Result<GlobalOrConstant, ErrorKind> {
) -> Result<GlobalOrConstant> {
let mut storage = StorageQualifier::StorageClass(StorageClass::Private);
let mut interpolation = None;
let mut set = None;
let mut binding = None;
let mut location = None;
let mut sampling = None;
@@ -339,10 +360,12 @@ impl Parser {
// Ignore the Uniform qualifier if the class was already set to PushConstant
continue;
} else if StorageQualifier::StorageClass(StorageClass::Private) != storage {
return Err(ErrorKind::SemanticError(
self.errors.push(Error {
kind: ErrorKind::SemanticError(
"Cannot use more than one storage qualifier per declaration".into(),
),
meta,
"Cannot use more than one storage qualifier per declaration".into(),
));
});
}
storage = s;
@@ -351,67 +374,103 @@ impl Parser {
i,
interpolation,
meta,
"Cannot use more than one interpolation qualifier per declaration"
"Cannot use more than one interpolation qualifier per declaration",
self.errors
),
TypeQualifier::ResourceBinding(ref r) => qualifier_arm!(
r.clone(),
TypeQualifier::Binding(r) => qualifier_arm!(
r,
binding,
meta,
"Cannot use more than one binding per declaration"
"Cannot use more than one binding per declaration",
self.errors
),
TypeQualifier::Set(s) => qualifier_arm!(
s,
set,
meta,
"Cannot use more than one binding per declaration",
self.errors
),
TypeQualifier::Location(l) => qualifier_arm!(
l,
location,
meta,
"Cannot use more than one binding per declaration"
"Cannot use more than one binding per declaration",
self.errors
),
TypeQualifier::Sampling(s) => qualifier_arm!(
s,
sampling,
meta,
"Cannot use more than one sampling qualifier per declaration"
"Cannot use more than one sampling qualifier per declaration",
self.errors
),
TypeQualifier::Layout(ref l) => qualifier_arm!(
l,
layout,
meta,
"Cannot use more than one layout qualifier per declaration"
"Cannot use more than one layout qualifier per declaration",
self.errors
),
TypeQualifier::Precision(ref p) => qualifier_arm!(
p,
precision,
meta,
"Cannot use more than one precision qualifier per declaration"
"Cannot use more than one precision qualifier per declaration",
self.errors
),
TypeQualifier::StorageAccess(a) => access &= a,
_ => {
return Err(ErrorKind::SemanticError(
self.errors.push(Error {
kind: ErrorKind::SemanticError("Qualifier not supported in globals".into()),
meta,
"Qualifier not supported in globals".into(),
));
});
}
}
}
if binding.is_some() && storage != StorageQualifier::StorageClass(StorageClass::Uniform) {
match storage {
StorageQualifier::StorageClass(StorageClass::PushConstant)
| StorageQualifier::StorageClass(StorageClass::Uniform)
| StorageQualifier::StorageClass(StorageClass::Storage { .. }) => {}
_ => {
return Err(ErrorKind::SemanticError(
match storage {
StorageQualifier::StorageClass(StorageClass::PushConstant) => {
if set.is_some() {
self.errors.push(Error {
kind: ErrorKind::SemanticError(
"set cannot be used to decorate push constant".into(),
),
meta,
"binding requires uniform or buffer storage qualifier".into(),
))
})
}
}
StorageQualifier::StorageClass(StorageClass::Uniform)
| StorageQualifier::StorageClass(StorageClass::Storage { .. }) => {
if binding.is_none() {
self.errors.push(Error {
kind: ErrorKind::SemanticError(
"uniform/buffer blocks require layout(binding=X)".into(),
),
meta,
})
}
}
_ => {
if set.is_some() || binding.is_some() {
self.errors.push(Error {
kind: ErrorKind::SemanticError(
"set/binding can only be applied to uniform/buffer blocks".into(),
),
meta,
})
}
}
}
if (sampling.is_some() || interpolation.is_some()) && location.is_none() {
return Err(ErrorKind::SemanticError(
return Err(Error {
kind: ErrorKind::SemanticError(
"Sampling and interpolation qualifiers can only be used in in/out variables"
.into(),
),
meta,
"Sampling and interpolation qualifiers can only be used in in/out variables".into(),
));
});
}
if let Some(location) = location {
@@ -457,8 +516,9 @@ impl Parser {
return Ok(GlobalOrConstant::Global(handle));
} else if let StorageQualifier::Const = storage {
let init = init.ok_or_else(|| {
ErrorKind::SemanticError(meta, "const values must have an initializer".into())
let init = init.ok_or_else(|| Error {
kind: ErrorKind::SemanticError("const values must have an initializer".into()),
meta,
})?;
if let Some(name) = name {
let lookup = GlobalLookup {
@@ -491,7 +551,10 @@ impl Parser {
let handle = self.module.global_variables.append(GlobalVariable {
name: name.clone(),
class,
binding,
binding: binding.map(|binding| ResourceBinding {
group: set.unwrap_or(0),
binding,
}),
ty,
init,
});
@@ -522,11 +585,14 @@ impl Parser {
init,
meta,
}: VarDeclaration,
) -> Result<Handle<Expression>, ErrorKind> {
) -> Result<Handle<Expression>> {
#[cfg(feature = "glsl-validate")]
if let Some(ref name) = name {
if ctx.lookup_local_var_current_scope(name).is_some() {
return Err(ErrorKind::VariableAlreadyDeclared(meta, name.clone()));
self.errors.push(Error {
kind: ErrorKind::VariableAlreadyDeclared(name.clone()),
meta,
})
}
}
@@ -537,10 +603,13 @@ impl Parser {
match *qualifier {
TypeQualifier::StorageQualifier(StorageQualifier::Const) => {
if !mutable {
return Err(ErrorKind::SemanticError(
self.errors.push(Error {
kind: ErrorKind::SemanticError(
"Cannot use more than one constant qualifier per declaration"
.into(),
),
meta,
"Cannot use more than one constant qualifier per declaration".into(),
));
})
}
mutable = false;
@@ -549,14 +618,13 @@ impl Parser {
p,
precision,
meta,
"Cannot use more than one precision qualifier per declaration"
"Cannot use more than one precision qualifier per declaration",
self.errors
),
_ => {
return Err(ErrorKind::SemanticError(
meta,
"Qualifier not supported in locals".into(),
));
}
_ => self.errors.push(Error {
kind: ErrorKind::SemanticError("Qualifier not supported in locals".into()),
meta,
}),
}
}

View File

@@ -21,6 +21,5 @@ layout(location = 0) out vec4 frag_color;
void main() {
frag_color = color;
gl_Position = view_matrix * world_matrix * vec4(position, 0.0, 1.0);
// TODO: https://github.com/gfx-rs/naga/issues/901
// gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;
gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;
}

View File

@@ -28,6 +28,9 @@ fn main1() {
let _e10: mat4x4<f32> = global1.world_matrix;
let _e12: vec2<f32> = position1;
gl_Position = ((_e9 * _e10) * vec4<f32>(_e12, 0.0, 1.0));
let _e18: vec4<f32> = gl_Position;
let _e20: vec4<f32> = gl_Position;
gl_Position.z = ((_e18.z + _e20.w) / 2.0);
return;
}