From a0815679234d324ee6e4f8aacaef3a3aa035e445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Mon, 17 May 2021 11:43:19 +0100 Subject: [PATCH] [glsl-in] Implement Copy on SourceMetadata --- src/front/glsl/ast.rs | 4 ++-- src/front/glsl/error.rs | 16 ++++++++-------- src/front/glsl/functions.rs | 4 ++-- src/front/glsl/lex.rs | 24 +++++++++++++----------- src/front/glsl/parser.rs | 28 ++++++++++++++-------------- src/front/glsl/parser_tests.rs | 13 ++++++++----- src/front/glsl/token.rs | 17 ++++++++++++++--- src/front/glsl/variables.rs | 2 +- 8 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index 845f06ac69..f54abf72e8 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -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, diff --git a/src/front/glsl/error.rs b/src/front/glsl/error.rs index 8ae98dd29c..8ad9c16aa7 100644 --- a/src/front/glsl/error.rs +++ b/src/front/glsl/error.rs @@ -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 { 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, } } diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 8f9882c3ec..d0128dc81c 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -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 { diff --git a/src/front/glsl/lex.rs b/src/front/glsl/lex.rs index bc6335abf2..b989972420 100644 --- a/src/front/glsl/lex.rs +++ b/src/front/glsl/lex.rs @@ -30,13 +30,14 @@ impl<'a> Lexer<'a> { impl<'a> Iterator for Lexer<'a> { type Item = Token; fn next(&mut self) -> Option { - 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); diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index b7448818a6..5801289902 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -143,7 +143,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { fn parse_type_non_void(&mut self) -> Result<(Handle, 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>, ) -> Result> { 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> { 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 { diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index 3a165ab331..3e3321e4ad 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -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() ) ); diff --git a/src/front/glsl/token.rs b/src/front/glsl/token.rs index 8e81de31c3..16a745e35e 100644 --- a/src/front/glsl/token.rs +++ b/src/front/glsl/token.rs @@ -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, + /// 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 for Range { + fn from(meta: SourceMetadata) -> Self { + meta.start..meta.end + } +} + #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub struct Token { diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index 7aaff1d7aa..1e572e1717 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -121,7 +121,7 @@ impl Program<'_> { name: &str, meta: SourceMetadata, ) -> Result, ErrorKind> { - match *self.resolve_type(context, expression, meta.clone())? { + match *self.resolve_type(context, expression, meta)? { TypeInner::Struct { ref members, .. } => { let index = members .iter()