[glsl-in] Implement Copy on SourceMetadata

This commit is contained in:
João Capucho
2021-05-17 11:43:19 +01:00
committed by Dzmitry Malyshau
parent 9390515595
commit a081567923
8 changed files with 62 additions and 46 deletions

View File

@@ -316,7 +316,7 @@ impl<'function> Context<'function> {
HirExprKind::Select { base, field } => {
let base = self.lower(program, base, lhs, body)?.0;
program.field_selection(self, base, &field, meta.clone())?
program.field_selection(self, base, &field, meta)?
}
HirExprKind::Constant(constant) if !lhs => {
self.expressions.append(Expression::Constant(constant))
@@ -383,7 +383,7 @@ impl<'function> Context<'function> {
}
}
HirExprKind::Call(call) if !lhs => {
program.function_call(self, body, call.kind, &call.args, meta.clone())?
program.function_call(self, body, call.kind, &call.args, meta)?
}
HirExprKind::Conditional {
condition,

View File

@@ -33,15 +33,15 @@ pub enum ErrorKind {
impl ErrorKind {
/// Returns the TokenMetadata if available
pub fn metadata(&self) -> Option<&SourceMetadata> {
pub fn metadata(&self) -> Option<SourceMetadata> {
match *self {
ErrorKind::UnknownVariable(ref metadata, _)
| ErrorKind::InvalidProfile(ref metadata, _)
| ErrorKind::InvalidVersion(ref metadata, _)
| ErrorKind::UnknownLayoutQualifier(ref metadata, _)
| ErrorKind::SemanticError(ref metadata, _)
| ErrorKind::UnknownField(ref metadata, _) => Some(metadata),
ErrorKind::InvalidToken(ref token) => Some(&token.meta),
ErrorKind::UnknownVariable(metadata, _)
| ErrorKind::InvalidProfile(metadata, _)
| ErrorKind::InvalidVersion(metadata, _)
| ErrorKind::UnknownLayoutQualifier(metadata, _)
| ErrorKind::SemanticError(metadata, _)
| ErrorKind::UnknownField(metadata, _) => Some(metadata),
ErrorKind::InvalidToken(ref token) => Some(token.meta),
_ => None,
}
}

View File

@@ -24,7 +24,7 @@ impl Program<'_> {
match fc {
FunctionCallKind::TypeConstructor(ty) => {
let h = if args.len() == 1 {
let is_vec = match *self.resolve_type(ctx, args[0].0, args[0].1.clone())? {
let is_vec = match *self.resolve_type(ctx, args[0].0, args[0].1)? {
TypeInner::Vector { .. } => true,
_ => false,
};
@@ -291,7 +291,7 @@ impl Program<'_> {
let name = function
.name
.clone()
.ok_or_else(|| ErrorKind::SemanticError(meta.clone(), "Unnamed function".into()))?;
.ok_or_else(|| ErrorKind::SemanticError(meta, "Unnamed function".into()))?;
let stage = self.entry_points.get(&name);
if let Some(&stage) = stage {

View File

@@ -30,13 +30,14 @@ impl<'a> Lexer<'a> {
impl<'a> Iterator for Lexer<'a> {
type Item = Token;
fn next(&mut self) -> Option<Self::Item> {
let mut meta = SourceMetadata { chars: 0..0 };
let mut meta = SourceMetadata::default();
let pp_token = match self.tokens.pop_front() {
Some(t) => t,
None => match self.pp.next()? {
Ok(t) => t,
Err((err, loc)) => {
meta.chars = loc.into();
meta.start = loc.start as usize;
meta.end = loc.end as usize;
return Some(Token {
value: TokenValue::Unknown(err),
meta,
@@ -45,7 +46,8 @@ impl<'a> Iterator for Lexer<'a> {
},
};
meta.chars = pp_token.location.into();
meta.start = pp_token.location.start as usize;
meta.end = pp_token.location.end as usize;
let value = match pp_token.value {
PPTokenValue::Extension(extension) => {
for t in extension.tokens {
@@ -186,7 +188,7 @@ mod tests {
lex.next().unwrap(),
Token {
value: TokenValue::Version,
meta: SourceMetadata { chars: 1..8 }
meta: SourceMetadata { start: 1, end: 8 }
}
);
assert_eq!(
@@ -197,49 +199,49 @@ mod tests {
value: 450,
width: 32
}),
meta: SourceMetadata { chars: 9..12 },
meta: SourceMetadata { start: 9, end: 12 },
}
);
assert_eq!(
lex.next().unwrap(),
Token {
value: TokenValue::Void,
meta: SourceMetadata { chars: 13..17 }
meta: SourceMetadata { start: 13, end: 17 }
}
);
assert_eq!(
lex.next().unwrap(),
Token {
value: TokenValue::Identifier("main".into()),
meta: SourceMetadata { chars: 18..22 }
meta: SourceMetadata { start: 18, end: 22 }
}
);
assert_eq!(
lex.next().unwrap(),
Token {
value: TokenValue::LeftParen,
meta: SourceMetadata { chars: 23..24 }
meta: SourceMetadata { start: 23, end: 24 }
}
);
assert_eq!(
lex.next().unwrap(),
Token {
value: TokenValue::RightParen,
meta: SourceMetadata { chars: 24..25 }
meta: SourceMetadata { start: 24, end: 25 }
}
);
assert_eq!(
lex.next().unwrap(),
Token {
value: TokenValue::LeftBrace,
meta: SourceMetadata { chars: 26..27 }
meta: SourceMetadata { start: 26, end: 27 }
}
);
assert_eq!(
lex.next().unwrap(),
Token {
value: TokenValue::RightBrace,
meta: SourceMetadata { chars: 27..28 }
meta: SourceMetadata { start: 27, end: 28 }
}
);
assert_eq!(lex.next(), None);

View File

@@ -143,7 +143,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
fn parse_type_non_void(&mut self) -> Result<(Handle<Type>, SourceMetadata)> {
let (maybe_ty, meta) = self.parse_type()?;
let ty = maybe_ty
.ok_or_else(|| ErrorKind::SemanticError(meta.clone(), "Type can't be void".into()))?;
.ok_or_else(|| ErrorKind::SemanticError(meta, "Type can't be void".into()))?;
Ok((ty, meta))
}
@@ -260,16 +260,16 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
value: ScalarValue::Uint(int),
..
} => u32::try_from(int).map_err(|_| {
ErrorKind::SemanticError(meta.clone(), "int constant overflows".into())
ErrorKind::SemanticError(meta, "int constant overflows".into())
}),
ConstantInner::Scalar {
value: ScalarValue::Sint(int),
..
} => u32::try_from(int).map_err(|_| {
ErrorKind::SemanticError(meta.clone(), "int constant overflows".into())
ErrorKind::SemanticError(meta, "int constant overflows".into())
}),
_ => Err(ErrorKind::SemanticError(
meta.clone(),
meta,
"Expected a uint constant".into(),
)),
}?;
@@ -329,7 +329,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
Ok((
self.program
.solve_constant(&expressions, root, meta.clone())?,
.solve_constant(&expressions, root, meta)?,
meta,
))
}
@@ -980,7 +980,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
let Token { value, meta } = self.bump()?;
let expr = self.parse_unary(ctx)?;
let end_meta = ctx.hir_exprs[expr].meta.clone();
let end_meta = ctx.hir_exprs[expr].meta;
let kind = match value {
TokenValue::Dash => HirExprKind::Unary {
@@ -1012,7 +1012,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
let mut left = passtrough
.ok_or(ErrorKind::EndOfFile /* Dummy error */)
.or_else(|_| self.parse_unary(ctx))?;
let start_meta = ctx.hir_exprs[left].meta.clone();
let start_meta = ctx.hir_exprs[left].meta;
while let Some((l_bp, r_bp)) = binding_power(&self.expect_peek()?.value) {
if l_bp < min_bp {
@@ -1022,7 +1022,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
let Token { value, .. } = self.bump()?;
let right = self.parse_binary(ctx, None, r_bp)?;
let end_meta = ctx.hir_exprs[right].meta.clone();
let end_meta = ctx.hir_exprs[right].meta;
left = ctx.hir_exprs.append(HirExpr {
kind: HirExprKind::Binary {
@@ -1064,13 +1064,13 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
passtrough: Option<Handle<HirExpr>>,
) -> Result<Handle<HirExpr>> {
let mut condition = self.parse_binary(ctx, passtrough, 0)?;
let start_meta = ctx.hir_exprs[condition].meta.clone();
let start_meta = ctx.hir_exprs[condition].meta;
if self.bump_if(TokenValue::Question).is_some() {
let accept = self.parse_expression(ctx)?;
self.expect(TokenValue::Colon)?;
let reject = self.parse_assignment(ctx)?;
let end_meta = ctx.hir_exprs[reject].meta.clone();
let end_meta = ctx.hir_exprs[reject].meta;
condition = ctx.hir_exprs.append(HirExpr {
kind: HirExprKind::Conditional {
@@ -1087,13 +1087,13 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
fn parse_assignment(&mut self, ctx: &mut Context) -> Result<Handle<HirExpr>> {
let tgt = self.parse_unary(ctx)?;
let start_meta = ctx.hir_exprs[tgt].meta.clone();
let start_meta = ctx.hir_exprs[tgt].meta;
Ok(match self.expect_peek()?.value {
TokenValue::Assign => {
self.bump()?;
let value = self.parse_assignment(ctx)?;
let end_meta = ctx.hir_exprs[value].meta.clone();
let end_meta = ctx.hir_exprs[value].meta;
ctx.hir_exprs.append(HirExpr {
kind: HirExprKind::Assign { tgt, value },
@@ -1112,7 +1112,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
| TokenValue::XorAssign => {
let token = self.bump()?;
let right = self.parse_assignment(ctx)?;
let end_meta = ctx.hir_exprs[right].meta.clone();
let end_meta = ctx.hir_exprs[right].meta;
let value = ctx.hir_exprs.append(HirExpr {
meta: start_meta.union(&end_meta),
@@ -1236,7 +1236,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
let constant = self.program.solve_constant(
&ctx.expressions,
root,
meta.clone(),
meta,
)?;
match self.program.module.constants[constant].inner {

View File

@@ -31,19 +31,19 @@ fn version() {
parse_program("#version 99000", &entry_points)
.err()
.unwrap(),
ErrorKind::InvalidVersion(SourceMetadata { chars: 9..14 }, 99000),
ErrorKind::InvalidVersion(SourceMetadata { start: 9, end: 14 }, 99000),
);
assert_eq!(
parse_program("#version 449", &entry_points).err().unwrap(),
ErrorKind::InvalidVersion(SourceMetadata { chars: 9..12 }, 449)
ErrorKind::InvalidVersion(SourceMetadata { start: 9, end: 12 }, 449)
);
assert_eq!(
parse_program("#version 450 smart", &entry_points)
.err()
.unwrap(),
ErrorKind::InvalidProfile(SourceMetadata { chars: 13..18 }, "smart".into())
ErrorKind::InvalidProfile(SourceMetadata { start: 13, end: 18 }, "smart".into())
);
assert_eq!(
@@ -52,7 +52,7 @@ fn version() {
.unwrap(),
ErrorKind::InvalidToken(Token {
value: TokenValue::Unknown(PreprocessorError::UnexpectedHash),
meta: SourceMetadata { chars: 24..25 }
meta: SourceMetadata { start: 24, end: 25 }
})
);
@@ -330,7 +330,10 @@ fn functions() {
.err()
.unwrap(),
ErrorKind::SemanticError(
SourceMetadata { chars: 134..152 },
SourceMetadata {
start: 134,
end: 152
},
"Function already defined".into()
)
);

View File

@@ -3,20 +3,31 @@ pub use pp_rs::token::{Float, Integer, PreprocessorError};
use crate::{Interpolation, Sampling, Type};
use std::{fmt, ops::Range};
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(test, derive(PartialEq))]
pub struct SourceMetadata {
pub chars: Range<usize>,
/// Byte offset into the source where the first char starts
pub start: usize,
/// Byte offset into the source where the first char not belonging to this
/// source metadata starts
pub end: usize,
}
impl SourceMetadata {
pub fn union(&self, other: &Self) -> Self {
SourceMetadata {
chars: (self.chars.start.min(other.chars.start))..(self.chars.end.max(other.chars.end)),
start: self.start.min(other.start),
end: self.end.max(other.end),
}
}
}
impl From<SourceMetadata> for Range<usize> {
fn from(meta: SourceMetadata) -> Self {
meta.start..meta.end
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub struct Token {

View File

@@ -121,7 +121,7 @@ impl Program<'_> {
name: &str,
meta: SourceMetadata,
) -> Result<Handle<Expression>, ErrorKind> {
match *self.resolve_type(context, expression, meta.clone())? {
match *self.resolve_type(context, expression, meta)? {
TypeInner::Struct { ref members, .. } => {
let index = members
.iter()