From 786194ec679ca96af48cbac75775fe66979b17e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Sat, 1 May 2021 14:06:27 +0100 Subject: [PATCH] [glsl-in][New parser] WIP support for functions --- src/front/glsl/ast.rs | 101 ++++++++----- src/front/glsl/functions.rs | 132 ++++++++--------- src/front/glsl/lex.rs | 1 + src/front/glsl/parser.rs | 255 ++++++++++++++++++++++++++++++--- src/front/glsl/parser_tests.rs | 82 ++++++----- src/front/glsl/token.rs | 1 + src/front/glsl/variables.rs | 61 ++++---- 7 files changed, 427 insertions(+), 206 deletions(-) diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index aaa8a7d80b..c31d1f9721 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -1,9 +1,9 @@ use super::{super::Typifier, constants::ConstantSolver, error::ErrorKind}; use crate::{ proc::ResolveContext, Arena, ArraySize, BinaryOperator, Binding, Constant, Expression, - FastHashMap, Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, - Module, RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass, - Type, UnaryOperator, + FastHashMap, Function, FunctionArgument, GlobalVariable, Handle, Interpolation, Module, + RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass, Type, + UnaryOperator, }; #[derive(Debug)] @@ -15,7 +15,6 @@ pub struct Program<'a> { pub lookup_type: FastHashMap>, pub lookup_global_variables: FastHashMap>, pub lookup_constants: FastHashMap>, - pub context: Context, pub module: Module, } @@ -29,34 +28,31 @@ impl<'a> Program<'a> { lookup_type: FastHashMap::default(), lookup_global_variables: FastHashMap::default(), lookup_constants: FastHashMap::default(), - context: Context { - expressions: Arena::::new(), - local_variables: Arena::::new(), - arguments: Vec::new(), - scopes: vec![FastHashMap::default()], - lookup_global_var_exps: FastHashMap::default(), - lookup_constant_exps: FastHashMap::default(), - typifier: Typifier::new(), - }, module: Module::default(), } } pub fn binary_expr( &mut self, + function: &mut Function, op: BinaryOperator, left: &ExpressionRule, right: &ExpressionRule, ) -> ExpressionRule { - ExpressionRule::from_expression(self.context.expressions.append(Expression::Binary { + ExpressionRule::from_expression(function.expressions.append(Expression::Binary { op, left: left.expression, right: right.expression, })) } - pub fn unary_expr(&mut self, op: UnaryOperator, tgt: &ExpressionRule) -> ExpressionRule { - ExpressionRule::from_expression(self.context.expressions.append(Expression::Unary { + pub fn unary_expr( + &mut self, + function: &mut Function, + op: UnaryOperator, + tgt: &ExpressionRule, + ) -> ExpressionRule { + ExpressionRule::from_expression(function.expressions.append(Expression::Unary { op, expr: tgt.expression, })) @@ -67,16 +63,17 @@ impl<'a> Program<'a> { /// represented as `all(equal(vec1, vec2))` and `any(notEqual(vec1, vec2))` pub fn equality_expr( &mut self, + context: &mut FunctionContext, equals: bool, left: &ExpressionRule, right: &ExpressionRule, ) -> Result { - let left_is_vector = match *self.resolve_type(left.expression)? { + let left_is_vector = match *self.resolve_type(context, left.expression)? { crate::TypeInner::Vector { .. } => true, _ => false, }; - let right_is_vector = match *self.resolve_type(right.expression)? { + let right_is_vector = match *self.resolve_type(context, right.expression)? { crate::TypeInner::Vector { .. } => true, _ => false, }; @@ -86,15 +83,16 @@ impl<'a> Program<'a> { false => (BinaryOperator::NotEqual, RelationalFunction::Any), }; - let expr = - ExpressionRule::from_expression(self.context.expressions.append(Expression::Binary { + let expr = ExpressionRule::from_expression(context.function.expressions.append( + Expression::Binary { op, left: left.expression, right: right.expression, - })); + }, + )); Ok(if left_is_vector && right_is_vector { - ExpressionRule::from_expression(self.context.expressions.append( + ExpressionRule::from_expression(context.function.expressions.append( Expression::Relational { fun, argument: expr.expression, @@ -105,20 +103,21 @@ impl<'a> Program<'a> { }) } - pub fn resolve_type( - &mut self, + pub fn resolve_type<'b>( + &'b mut self, + context: &'b mut FunctionContext, handle: Handle, - ) -> Result<&crate::TypeInner, ErrorKind> { + ) -> Result<&'b crate::TypeInner, ErrorKind> { let resolve_ctx = ResolveContext { constants: &self.module.constants, global_vars: &self.module.global_variables, - local_vars: &self.context.local_variables, + local_vars: &context.function.local_variables, functions: &self.module.functions, - arguments: &self.context.arguments, + arguments: &context.function.arguments, }; - match self.context.typifier.grow( + match context.typifier.grow( handle, - &self.context.expressions, + &context.function.expressions, &mut self.module.types, &resolve_ctx, ) { @@ -126,17 +125,18 @@ impl<'a> Program<'a> { Err(error) => Err(ErrorKind::SemanticError( format!("Can't resolve type: {:?}", error).into(), )), - Ok(()) => Ok(self.context.typifier.get(handle, &self.module.types)), + Ok(()) => Ok(context.typifier.get(handle, &self.module.types)), } } pub fn solve_constant( &mut self, + expressions: &Arena, root: Handle, ) -> Result, ErrorKind> { let mut solver = ConstantSolver { types: &self.module.types, - expressions: &self.context.expressions, + expressions, constants: &mut self.module.constants, }; @@ -197,10 +197,8 @@ pub enum Profile { } #[derive(Debug)] -pub struct Context { - pub expressions: Arena, - pub local_variables: Arena, - pub arguments: Vec, +pub struct FunctionContext<'function> { + pub function: &'function mut Function, //TODO: Find less allocation heavy representation pub scopes: Vec>>, pub lookup_global_var_exps: FastHashMap>, @@ -208,7 +206,17 @@ pub struct Context { pub typifier: Typifier, } -impl Context { +impl<'function> FunctionContext<'function> { + pub fn new(function: &'function mut Function) -> Self { + FunctionContext { + function, + scopes: vec![FastHashMap::default()], + lookup_global_var_exps: FastHashMap::default(), + lookup_constant_exps: FastHashMap::default(), + typifier: Typifier::new(), + } + } + pub fn lookup_local_var(&self, name: &str) -> Option> { for scope in self.scopes.iter().rev() { if let Some(var) = scope.get(name) { @@ -236,6 +244,7 @@ impl Context { pub fn add_local_var(&mut self, name: String, handle: Handle) { if let Some(current) = self.scopes.last_mut() { let expr = self + .function .expressions .append(Expression::Load { pointer: handle }); (*current).insert(name, expr); @@ -243,9 +252,22 @@ impl Context { } /// Add function argument to current scope - pub fn add_function_arg(&mut self, name: String, expr: Handle) { - if let Some(current) = self.scopes.last_mut() { - (*current).insert(name, expr); + pub fn add_function_arg(&mut self, name: Option, ty: Handle) { + let index = self.function.arguments.len(); + self.function.arguments.push(FunctionArgument { + name: name.clone(), + ty, + binding: None, + }); + + if let Some(name) = name { + if let Some(current) = self.scopes.last_mut() { + let expr = self + .function + .expressions + .append(Expression::FunctionArgument(index as u32)); + (*current).insert(name, expr); + } } } @@ -309,6 +331,7 @@ pub enum StorageQualifier { StorageClass(StorageClass), Input, Output, + InOut, Const, } diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 98033dc9b5..c1599e5898 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -1,31 +1,34 @@ -use super::super::Typifier; use crate::{ - proc::ensure_block_returns, BinaryOperator, Block, EntryPoint, Expression, Function, - MathFunction, RelationalFunction, SampleLevel, ScalarKind, TypeInner, + BinaryOperator, Expression, MathFunction, RelationalFunction, SampleLevel, ScalarKind, + TypeInner, }; use super::{ast::*, error::ErrorKind}; impl Program<'_> { - pub fn function_call(&mut self, fc: FunctionCall) -> Result { + pub fn function_call( + &mut self, + context: &mut FunctionContext, + fc: FunctionCall, + ) -> Result { match fc.kind { FunctionCallKind::TypeConstructor(ty) => { let h = if fc.args.len() == 1 { - let is_vec = match *self.resolve_type(fc.args[0].expression)? { + let is_vec = match *self.resolve_type(context, fc.args[0].expression)? { TypeInner::Vector { .. } => true, _ => false, }; match self.module.types[ty].inner { TypeInner::Vector { size, .. } if !is_vec => { - self.context.expressions.append(Expression::Splat { + context.function.expressions.append(Expression::Splat { size, value: fc.args[0].expression, }) } TypeInner::Scalar { kind, width } | TypeInner::Vector { kind, width, .. } => { - self.context.expressions.append(Expression::As { + context.function.expressions.append(Expression::As { kind, expr: fc.args[0].expression, convert: Some(width), @@ -36,7 +39,7 @@ impl Program<'_> { rows, width, } => { - let value = self.context.expressions.append(Expression::As { + let value = context.function.expressions.append(Expression::As { kind: ScalarKind::Float, expr: fc.args[0].expression, convert: Some(width), @@ -45,7 +48,8 @@ impl Program<'_> { let column = if is_vec { value } else { - self.context + context + .function .expressions .append(Expression::Splat { size: rows, value }) }; @@ -53,7 +57,7 @@ impl Program<'_> { let columns = std::iter::repeat(column).take(columns as usize).collect(); - self.context.expressions.append(Expression::Compose { + context.function.expressions.append(Expression::Compose { ty, components: columns, }) @@ -61,7 +65,7 @@ impl Program<'_> { _ => return Err(ErrorKind::SemanticError("Bad cast".into())), } } else { - self.context.expressions.append(Expression::Compose { + context.function.expressions.append(Expression::Compose { ty, components: fc.args.iter().map(|a| a.expression).collect(), }) @@ -101,7 +105,7 @@ impl Program<'_> { } if let Some(sampler) = fc.args[0].sampler { Ok(ExpressionRule { - expression: self.context.expressions.append( + expression: context.function.expressions.append( Expression::ImageSample { image: fc.args[0].expression, sampler, @@ -130,7 +134,7 @@ impl Program<'_> { } if let Some(sampler) = fc.args[0].sampler { Ok(ExpressionRule { - expression: self.context.expressions.append( + expression: context.function.expressions.append( Expression::ImageSample { image: fc.args[0].expression, sampler, @@ -160,7 +164,7 @@ impl Program<'_> { return Err(ErrorKind::WrongNumberArgs(name, 1, fc.args.len())); } Ok(ExpressionRule { - expression: self.context.expressions.append(Expression::Math { + expression: context.function.expressions.append(Expression::Math { fun: match name.as_str() { "ceil" => MathFunction::Ceil, "round" => MathFunction::Round, @@ -192,7 +196,7 @@ impl Program<'_> { return Err(ErrorKind::WrongNumberArgs(name, 2, fc.args.len())); } Ok(ExpressionRule { - expression: self.context.expressions.append(Expression::Math { + expression: context.function.expressions.append(Expression::Math { fun: match name.as_str() { "pow" => MathFunction::Pow, "dot" => MathFunction::Dot, @@ -212,7 +216,7 @@ impl Program<'_> { return Err(ErrorKind::WrongNumberArgs(name, 3, fc.args.len())); } Ok(ExpressionRule { - expression: self.context.expressions.append(Expression::Math { + expression: context.function.expressions.append(Expression::Math { fun: match name.as_str() { "mix" => MathFunction::Mix, "clamp" => MathFunction::Clamp, @@ -232,7 +236,7 @@ impl Program<'_> { return Err(ErrorKind::WrongNumberArgs(name, 2, fc.args.len())); } Ok(ExpressionRule { - expression: self.context.expressions.append(Expression::Binary { + expression: context.function.expressions.append(Expression::Binary { op: match name.as_str() { "lessThan" => BinaryOperator::Less, "greaterThan" => BinaryOperator::Greater, @@ -249,10 +253,18 @@ impl Program<'_> { statements: fc.args.into_iter().flat_map(|a| a.statements).collect(), }) } - "isinf" => self.parse_relational_fun(name, fc.args, RelationalFunction::IsInf), - "isnan" => self.parse_relational_fun(name, fc.args, RelationalFunction::IsNan), - "all" => self.parse_relational_fun(name, fc.args, RelationalFunction::All), - "any" => self.parse_relational_fun(name, fc.args, RelationalFunction::Any), + "isinf" => { + self.parse_relational_fun(context, name, fc.args, RelationalFunction::IsInf) + } + "isnan" => { + self.parse_relational_fun(context, name, fc.args, RelationalFunction::IsNan) + } + "all" => { + self.parse_relational_fun(context, name, fc.args, RelationalFunction::All) + } + "any" => { + self.parse_relational_fun(context, name, fc.args, RelationalFunction::Any) + } func_name => { let function = *self.lookup_function.get(func_name).ok_or_else(|| { ErrorKind::SemanticError( @@ -262,8 +274,10 @@ impl Program<'_> { let arguments: Vec<_> = fc.args.iter().map(|a| a.expression).collect(); let mut statements: Vec<_> = fc.args.into_iter().flat_map(|a| a.statements).collect(); - let expression = - self.context.expressions.append(Expression::Call(function)); + let expression = context + .function + .expressions + .append(Expression::Call(function)); statements.push(crate::Statement::Call { function, arguments, @@ -282,6 +296,7 @@ impl Program<'_> { pub fn parse_relational_fun( &mut self, + context: &mut FunctionContext, name: String, args: Vec, fun: RelationalFunction, @@ -290,7 +305,7 @@ impl Program<'_> { return Err(ErrorKind::WrongNumberArgs(name, 1, args.len())); } Ok(ExpressionRule { - expression: self.context.expressions.append(Expression::Relational { + expression: context.function.expressions.append(Expression::Relational { fun, argument: args[0].expression, }), @@ -299,33 +314,33 @@ impl Program<'_> { }) } - pub fn add_function_prelude(&mut self) { + pub fn add_function_prelude(&mut self, context: &mut FunctionContext) { for (var_handle, var) in self.module.global_variables.iter() { if let Some(name) = var.name.as_ref() { - let expr = self - .context + let expr = context + .function .expressions .append(Expression::GlobalVariable(var_handle)); - self.context - .lookup_global_var_exps - .insert(name.clone(), expr); + context.lookup_global_var_exps.insert(name.clone(), expr); } else { let ty = &self.module.types[var.ty]; // anonymous structs if let TypeInner::Struct { ref members, .. } = ty.inner { - let base = self - .context + let base = context + .function .expressions .append(Expression::GlobalVariable(var_handle)); for (idx, member) in members.iter().enumerate() { if let Some(name) = member.name.as_ref() { - let exp = self.context.expressions.append(Expression::AccessIndex { - base, - index: idx as u32, - }); - self.context - .lookup_global_var_exps - .insert(name.clone(), exp); + let exp = + context + .function + .expressions + .append(Expression::AccessIndex { + base, + index: idx as u32, + }); + context.lookup_global_var_exps.insert(name.clone(), exp); } } } @@ -334,45 +349,12 @@ impl Program<'_> { for (handle, constant) in self.module.constants.iter() { if let Some(name) = constant.name.as_ref() { - let expr = self - .context + let expr = context + .function .expressions .append(Expression::Constant(handle)); - self.context.lookup_constant_exps.insert(name.clone(), expr); + context.lookup_constant_exps.insert(name.clone(), expr); } } } - - pub fn function_definition(&mut self, mut f: Function, mut block: Block) -> Function { - std::mem::swap(&mut f.expressions, &mut self.context.expressions); - std::mem::swap(&mut f.local_variables, &mut self.context.local_variables); - std::mem::swap(&mut f.arguments, &mut self.context.arguments); - self.context.clear_scopes(); - self.context.lookup_global_var_exps.clear(); - self.context.typifier = Typifier::new(); - ensure_block_returns(&mut block); - f.body = block; - f - } - - pub fn declare_function(&mut self, f: Function) -> Result<(), ErrorKind> { - let name = f - .name - .clone() - .ok_or_else(|| ErrorKind::SemanticError("Unnamed function".into()))?; - let stage = self.entry_points.get(&name); - if let Some(&stage) = stage { - self.module.entry_points.push(EntryPoint { - name, - stage, - early_depth_test: None, - workgroup_size: [0; 3], //TODO - function: f, - }); - } else { - let handle = self.module.functions.append(f); - self.lookup_function.insert(name, handle); - } - Ok(()) - } } diff --git a/src/front/glsl/lex.rs b/src/front/glsl/lex.rs index c7c643df30..84e73df488 100644 --- a/src/front/glsl/lex.rs +++ b/src/front/glsl/lex.rs @@ -96,6 +96,7 @@ impl<'a> Iterator for Lexer<'a> { "for" => TokenValue::For, // types "void" => TokenValue::Void, + "struct" => TokenValue::Struct, word => match parse_type(word) { Some(t) => TokenValue::TypeName(t), None => TokenValue::Identifier(String::from(word)), diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index 499c988660..c80667eb4b 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -1,12 +1,15 @@ use super::{ - ast::Profile, + ast::{FunctionContext, Profile, StorageQualifier, TypeQualifier}, error::ErrorKind, lex::Lexer, token::{Token, TokenMetadata, TokenValue}, Program, }; +use crate::{arena::Handle, ArraySize, Function, FunctionResult, StorageClass, Type, TypeInner}; use std::iter::Peekable; +type Result = std::result::Result; + pub struct Parser<'source, 'program, 'options> { program: &'program mut Program<'options>, lexer: Peekable>, @@ -20,17 +23,44 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { } } - pub fn parse(&mut self) -> Result<(), ErrorKind> { - self.parse_version()?; + fn expect_ident(&mut self) -> Result<(String, TokenMetadata)> { + let token = self.bump()?; - if let Some(token) = self.lexer.next() { - Err(ErrorKind::InvalidToken(token)) - } else { - Ok(()) + match token.value { + TokenValue::Identifier(name) => Ok((name, token.meta)), + _ => Err(ErrorKind::InvalidToken(token)), } } - fn parse_version(&mut self) -> Result<(), ErrorKind> { + fn expect(&mut self, value: TokenValue) -> Result { + let token = self.bump()?; + + if token.value != value { + Err(ErrorKind::InvalidToken(token)) + } else { + Ok(token) + } + } + + fn bump(&mut self) -> Result { + self.lexer.next().ok_or(ErrorKind::EndOfFile) + } + + fn expect_peek(&mut self) -> Result<&Token> { + self.lexer.peek().ok_or(ErrorKind::EndOfFile) + } + + pub fn parse(&mut self) -> Result<()> { + self.parse_version()?; + + while self.lexer.peek().is_some() { + self.parse_external_declaration()?; + } + + Ok(()) + } + + fn parse_version(&mut self) -> Result<()> { self.expect(TokenValue::Version)?; let version = self.bump()?; @@ -61,26 +91,205 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { Ok(()) } - fn expect_ident(&mut self) -> Result<(String, TokenMetadata), ErrorKind> { - let token = self.bump()?; + fn parse_array_specifier(&mut self) -> Result> { + // TODO: expressions + if let Some(&TokenValue::LeftBracket) = self.lexer.peek().map(|t| &t.value) { + self.bump()?; - match token.value { - TokenValue::Identifier(name) => Ok((name, token.meta)), - _ => Err(ErrorKind::InvalidToken(token)), - } - } + self.expect(TokenValue::RightBracket)?; - fn expect(&mut self, value: TokenValue) -> Result { - let token = self.bump()?; - - if token.value != value { - Err(ErrorKind::InvalidToken(token)) + Ok(Some(ArraySize::Dynamic)) } else { - Ok(token) + Ok(None) } } - fn bump(&mut self) -> Result { - self.lexer.next().ok_or(ErrorKind::EndOfFile) + fn parse_type(&mut self) -> Result>> { + let token = self.bump()?; + let ty = match token.value { + TokenValue::Void => None, + TokenValue::TypeName(ty) => Some(ty), + TokenValue::Struct => todo!(), + _ => return Err(ErrorKind::InvalidToken(token)), + }; + let handle = ty.map(|t| self.program.module.types.append(t)); + + let size = self.parse_array_specifier()?; + Ok(handle.map(|ty| self.maybe_array(ty, size))) + } + + fn parse_type_non_void(&mut self) -> Result> { + self.parse_type()? + .ok_or_else(|| ErrorKind::SemanticError("Type can't be void".into())) + } + + fn maybe_array(&mut self, base: Handle, size: Option) -> Handle { + size.map(|size| { + self.program.module.types.append(Type { + name: None, + inner: TypeInner::Array { + base, + size, + stride: self.program.module.types[base] + .inner + .span(&self.program.module.constants), + }, + }) + }) + .unwrap_or(base) + } + + fn peek_type_qualifier(&mut self) -> bool { + self.lexer.peek().map_or(false, |t| match t.value { + TokenValue::Interpolation(_) + | TokenValue::Const + | TokenValue::In + | TokenValue::Out + | TokenValue::InOut + | TokenValue::Uniform => true, + _ => false, + }) + } + + fn parse_type_qualifiers(&mut self) -> Result> { + let mut qualifiers = Vec::new(); + + if self.peek_type_qualifier() { + let token = self.bump()?; + qualifiers.push(match token.value { + TokenValue::Interpolation(i) => TypeQualifier::Interpolation(i), + TokenValue::Const => TypeQualifier::StorageQualifier(StorageQualifier::Const), + TokenValue::In => TypeQualifier::StorageQualifier(StorageQualifier::Input), + TokenValue::Out => TypeQualifier::StorageQualifier(StorageQualifier::Output), + TokenValue::InOut => TypeQualifier::StorageQualifier(StorageQualifier::InOut), + TokenValue::Uniform => TypeQualifier::StorageQualifier( + StorageQualifier::StorageClass(StorageClass::Uniform), + ), + _ => unreachable!(), + }) + } + + Ok(qualifiers) + } + + fn parse_external_declaration(&mut self) -> Result<()> { + if !self.parse_declaration(true)? { + let token = self.bump()?; + match token.value { + TokenValue::Semicolon if self.program.version == 460 => Ok(()), + _ => Err(ErrorKind::InvalidToken(token)), + } + } else { + Ok(()) + } + } + + fn peek_type_name(&mut self) -> bool { + self.lexer.peek().map_or(false, |t| match t.value { + TokenValue::TypeName(_) | TokenValue::Void => true, + _ => false, + }) + } + + /// `external` wheter or not we are in a global or local context + fn parse_declaration(&mut self, external: bool) -> Result { + // TODO: Handle precision qualifiers + if self.peek_type_qualifier() || self.peek_type_name() { + // TODO: Use qualifiers + let _qualifiers = self.parse_type_qualifiers()?; + + if self.peek_type_name() { + // Functions and variable declarations + let ty = self.parse_type()?; + + let token = self.bump()?; + + match token.value { + TokenValue::Semicolon => Ok(true), + TokenValue::Identifier(name) => match self.expect_peek()?.value { + // Function definition/prototype + TokenValue::LeftParen => { + self.bump()?; + + let mut function = Function { + name: Some(name), + result: ty.map(|ty| FunctionResult { ty, binding: None }), + ..Default::default() + }; + let mut context = FunctionContext::new(&mut function); + + self.parse_function_args(&mut context)?; + + self.expect(TokenValue::RightParen)?; + + let token = self.bump()?; + match token.value { + // Function prototypes + TokenValue::Semicolon => todo!(), + TokenValue::LeftBrace if external => { + // TODO: body + self.expect(TokenValue::RightBrace)?; + + Ok(true) + } + _ => Err(ErrorKind::InvalidToken(token)), + } + } + // Variable Declaration + TokenValue::Semicolon => todo!(), + TokenValue::Comma => todo!(), + _ => Err(ErrorKind::InvalidToken(self.bump()?)), + }, + _ => Err(ErrorKind::InvalidToken(token)), + } + } else { + // Structs and modifiers + let token = self.bump()?; + match token.value { + TokenValue::Identifier(_) => todo!(), + TokenValue::Semicolon => Ok(true), + _ => Err(ErrorKind::InvalidToken(token)), + } + } + } else { + Ok(false) + } + } + + fn parse_function_args(&mut self, context: &mut FunctionContext) -> Result<()> { + loop { + // TODO: parameter qualifier + if self.peek_type_name() { + let ty = self.parse_type_non_void()?; + + match self.expect_peek()?.value { + TokenValue::Comma => { + self.bump()?; + context.add_function_arg(None, ty); + continue; + } + TokenValue::Identifier(_) => { + let name = self.expect_ident()?.0; + + let size = self.parse_array_specifier()?; + let ty = self.maybe_array(ty, size); + + context.add_function_arg(Some(name), ty); + + if self.expect_peek()?.value == TokenValue::Comma { + self.bump()?; + continue; + } + + break; + } + _ => break, + } + } + + break; + } + + Ok(()) } } diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index c9b31ba62e..a81edf8df8 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -50,35 +50,34 @@ fn version() { "InvalidProfile(TokenMetadata { line: 1, chars: 13..14 }, \"smart\")" //TODO: location ); - // TODO: Reenable tests later - // assert_eq!( - // format!( - // "{:?}", - // parse_program("#version 450\nvoid f(){} #version 450", &entry_points) - // .err() - // .unwrap() - // ), - // "InvalidToken(Unknown((TokenMetadata { line: 2, chars: 11..12 }, UnexpectedHash)))" - // ); + assert_eq!( + format!( + "{:?}", + parse_program("#version 450\nvoid f(){} #version 450", &entry_points) + .err() + .unwrap() + ), + "InvalidToken(Token { value: Unknown(UnexpectedHash), meta: TokenMetadata { line: 2, chars: 11..12 } })" + ); - // // valid versions - // let program = parse_program(" # version 450\nvoid main() {}", &entry_points).unwrap(); - // assert_eq!( - // format!("{:?}", (program.version, program.profile)), - // "(450, Core)" - // ); + // valid versions + let program = parse_program(" # version 450\nvoid main() {}", &entry_points).unwrap(); + assert_eq!( + format!("{:?}", (program.version, program.profile)), + "(450, Core)" + ); - // let program = parse_program("#version 450\nvoid main() {}", &entry_points).unwrap(); - // assert_eq!( - // format!("{:?}", (program.version, program.profile)), - // "(450, Core)" - // ); + let program = parse_program("#version 450\nvoid main() {}", &entry_points).unwrap(); + assert_eq!( + format!("{:?}", (program.version, program.profile)), + "(450, Core)" + ); - // let program = parse_program("#version 450 core\nvoid main() {}", &entry_points).unwrap(); - // assert_eq!( - // format!("{:?}", (program.version, program.profile)), - // "(450, Core)" - // ); + let program = parse_program("#version 450 core\nvoid main() {}", &entry_points).unwrap(); + assert_eq!( + format!("{:?}", (program.version, program.profile)), + "(450, Core)" + ); } #[test] @@ -193,9 +192,8 @@ fn textures() { #[test] fn functions() { - // TODO: Reenable tests later - // let mut entry_points = crate::FastHashMap::default(); - // entry_points.insert("".to_string(), ShaderStage::Vertex); + let mut entry_points = crate::FastHashMap::default(); + entry_points.insert("".to_string(), ShaderStage::Vertex); // TODO: Add support for function prototypes // parse_program( @@ -204,25 +202,25 @@ fn functions() { // void test1(float); // void test1(float) {} - // void main() {} - // "#, - // ShaderStage::Vertex, - // ) - // .unwrap(); - - // parse_program( - // r#" - // # version 450 - // void test2(float a) {} - // void test3(float a, float b) {} - // void test4(float, float) {} - // void main() {} // "#, // &entry_points, // ) // .unwrap(); + parse_program( + r#" + # version 450 + void test2(float a) {} + void test3(float a, float b) {} + void test4(float, float) {} + + void main() {} + "#, + &entry_points, + ) + .unwrap(); + // parse_program( // r#" // # version 450 diff --git a/src/front/glsl/token.rs b/src/front/glsl/token.rs index e6de19d4c6..bc53d61f3b 100644 --- a/src/front/glsl/token.rs +++ b/src/front/glsl/token.rs @@ -53,6 +53,7 @@ pub enum TokenValue { For, Void, + Struct, TypeName(Type), Assign, diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index 1adf259644..db4755906b 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -5,14 +5,18 @@ use super::error::ErrorKind; use super::token::TokenMetadata; impl Program<'_> { - pub fn lookup_variable(&mut self, name: &str) -> Result>, ErrorKind> { - if let Some(local_var) = self.context.lookup_local_var(name) { + pub fn lookup_variable( + &mut self, + context: &mut FunctionContext, + name: &str, + ) -> Result>, ErrorKind> { + if let Some(local_var) = context.lookup_local_var(name) { return Ok(Some(local_var)); } - if let Some(global_var) = self.context.lookup_global_var_exps.get(name) { + if let Some(global_var) = context.lookup_global_var_exps.get(name) { return Ok(Some(*global_var)); } - if let Some(constant) = self.context.lookup_constant_exps.get(name) { + if let Some(constant) = context.lookup_constant_exps.get(name) { return Ok(Some(*constant)); } match name { @@ -38,11 +42,11 @@ impl Program<'_> { .context .expressions .append(Expression::GlobalVariable(h));*/ - let exp = self - .context + let exp = context + .function .expressions .append(Expression::FunctionArgument(0)); //TODO - self.context.lookup_global_var_exps.insert(name.into(), exp); + context.lookup_global_var_exps.insert(name.into(), exp); Ok(Some(exp)) } @@ -74,13 +78,11 @@ impl Program<'_> { convert: true, }); */ - let expr = self - .context + let expr = context + .function .expressions .append(Expression::FunctionArgument(0)); //TODO - self.context - .lookup_global_var_exps - .insert(name.into(), expr); + context.lookup_global_var_exps.insert(name.into(), expr); Ok(Some(expr)) } @@ -112,13 +114,11 @@ impl Program<'_> { convert: true, }); */ - let expr = self - .context + let expr = context + .function .expressions .append(Expression::FunctionArgument(0)); //TODO - self.context - .lookup_global_var_exps - .insert(name.into(), expr); + context.lookup_global_var_exps.insert(name.into(), expr); Ok(Some(expr)) } @@ -128,20 +128,24 @@ impl Program<'_> { pub fn field_selection( &mut self, + context: &mut FunctionContext, expression: Handle, name: &str, meta: TokenMetadata, ) -> Result, ErrorKind> { - match *self.resolve_type(expression)? { + match *self.resolve_type(context, expression)? { TypeInner::Struct { ref members, .. } => { let index = members .iter() .position(|m| m.name == Some(name.into())) .ok_or_else(|| ErrorKind::UnknownField(meta, name.into()))?; - Ok(self.context.expressions.append(Expression::AccessIndex { - base: expression, - index: index as u32, - })) + Ok(context + .function + .expressions + .append(Expression::AccessIndex { + base: expression, + index: index as u32, + })) } // swizzles (xyzw, rgba, stpq) TypeInner::Vector { size, kind, width } => { @@ -170,17 +174,20 @@ impl Program<'_> { let components: Vec> = v .iter() .map(|idx| { - self.context.expressions.append(Expression::AccessIndex { - base: expression, - index: *idx as u32, - }) + context + .function + .expressions + .append(Expression::AccessIndex { + base: expression, + index: *idx as u32, + }) }) .collect(); if components.len() == 1 { // only single element swizzle, like pos.y, just return that component Ok(components[0]) } else { - Ok(self.context.expressions.append(Expression::Compose { + Ok(context.function.expressions.append(Expression::Compose { ty: self.module.types.fetch_or_append(Type { name: None, inner: TypeInner::Vector {