mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-in] Improve error api and make more errors deferred
This commit is contained in:
committed by
Dzmitry Malyshau
parent
f6e35f5b66
commit
1aaf77489b
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user