From 1eb637038dd15fc1dad770eca8e6943424dbc122 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Wed, 29 Jul 2020 04:48:05 +0200 Subject: [PATCH] [glsl-new] Add initial handling of stmts and exprs (#116) * [glsl-new] Add initial handling of stmts and exprs * [glsl-new] use &'static str for NotImplemented msg * [glsl-new] Don't lazy create function context --- src/front/glsl_new/ast.rs | 16 +- src/front/glsl_new/error.rs | 2 + src/front/glsl_new/parser.rs | 289 ++++++++++++++++++++++++++--------- 3 files changed, 236 insertions(+), 71 deletions(-) diff --git a/src/front/glsl_new/ast.rs b/src/front/glsl_new/ast.rs index fb6ab27d41..36938356f2 100644 --- a/src/front/glsl_new/ast.rs +++ b/src/front/glsl_new/ast.rs @@ -1,4 +1,7 @@ -use crate::{Arena, Constant, FastHashMap, Function, GlobalVariable, Handle, ShaderStage, Type}; +use crate::{ + Arena, Constant, Expression, FastHashMap, Function, GlobalVariable, Handle, LocalVariable, + ShaderStage, Type, +}; #[derive(Debug)] pub struct Program { @@ -11,6 +14,7 @@ pub struct Program { pub types: Arena, pub constants: Arena, pub global_variables: Arena, + pub context: Context, } impl Program { @@ -25,6 +29,10 @@ impl Program { types: Arena::::new(), constants: Arena::::new(), global_variables: Arena::::new(), + context: Context { + expressions: Arena::::new(), + local_variables: Arena::::new(), + }, } } } @@ -33,3 +41,9 @@ impl Program { pub enum Profile { Core, } + +#[derive(Debug)] +pub struct Context { + pub expressions: Arena, + pub local_variables: Arena, +} diff --git a/src/front/glsl_new/error.rs b/src/front/glsl_new/error.rs index bfb7d7c930..61e0ae7e67 100644 --- a/src/front/glsl_new/error.rs +++ b/src/front/glsl_new/error.rs @@ -12,6 +12,7 @@ pub enum ErrorKind { IoError(io::Error), ParserFail, ParserStackOverflow, + NotImplemented(&'static str), } impl fmt::Display for ErrorKind { @@ -29,6 +30,7 @@ impl fmt::Display for ErrorKind { ErrorKind::IoError(error) => write!(f, "IO Error {}", error), ErrorKind::ParserFail => write!(f, "Parser failed"), ErrorKind::ParserStackOverflow => write!(f, "Parser stack overflow"), + ErrorKind::NotImplemented(msg) => write!(f, "Not implemented: {}", msg), } } } diff --git a/src/front/glsl_new/parser.rs b/src/front/glsl_new/parser.rs index 55a3636a36..8760d06515 100644 --- a/src/front/glsl_new/parser.rs +++ b/src/front/glsl_new/parser.rs @@ -6,9 +6,9 @@ pomelo! { //%verbose; %include { use super::super::{error::ErrorKind, token::*, ast::*}; - use crate::{Arena, Binding, BuiltIn, Constant, ConstantInner, Expression, + use crate::{Arena, BinaryOperator, Binding, Block, BuiltIn, Constant, ConstantInner, Expression, Function, GlobalVariable, Handle, LocalVariable, ScalarKind, - ShaderStage, StorageClass, Type, TypeInner, VectorSize}; + ShaderStage, Statement, StorageClass, Type, TypeInner, VectorSize}; } %token #[derive(Debug)] pub enum Token {}; %parser pub struct Parser<'a> {}; @@ -33,20 +33,57 @@ pomelo! { %type CommentEnd (); %type Identifier String; + // constants %type IntConstant i64; %type UintConstant u64; %type FloatConstant f32; %type BoolConstant bool; %type DoubleConstant f64; %type String String; - %type arg_list Vec; - + // function %type function_prototype Function; %type function_declarator Function; %type function_header Function; - %type function_definition Function; + // statements + %type compound_statement Block; + %type compound_statement_no_new_scope Block; + %type statement_list Block; + %type statement Statement; + %type simple_statement Statement; + %type expression_statement Statement; + // expressions + %type unary_expression Handle; + %type postfix_expression Handle; + %type primary_expression Handle; + %type variable_identifier Handle; + + %type function_call Handle; + %type function_call_generic Handle; + %type function_call_header_no_parameters Handle; + %type function_call_header_with_parameters Handle; + %type function_call_header Handle; + %type function_identifier Handle; + + %type multiplicative_expression Handle; + %type additive_expression Handle; + %type shift_expression Handle; + %type relational_expression Handle; + %type equality_expression Handle; + %type and_expression Handle; + %type exclusive_or_expression Handle; + %type inclusive_or_expression Handle; + %type logical_and_expression Handle; + %type logical_xor_expression Handle; + %type logical_or_expression Handle; + %type conditional_expression Handle; + + %type assignment_expression (Statement, Handle); + %type assignment_operator BinaryOperator; + %type expression Statement; + + // types %type fully_specified_type Option>; %type type_specifier Option>; %type type_specifier_nonarray Option; @@ -77,7 +114,7 @@ pomelo! { if v.1.as_str() == "gl_Position" && (extra.shader_stage == ShaderStage::Vertex || extra.shader_stage == ShaderStage::Fragment) { - extra.global_variables.fetch_or_append( + let h = extra.global_variables.fetch_or_append( GlobalVariable { name: Some(v.1), class: match extra.shader_stage { @@ -96,6 +133,9 @@ pomelo! { }), }, ); + extra.context.expressions.append(Expression::GlobalVariable(h)) + } else { + return Err(ErrorKind::NotImplemented("var")) } } @@ -114,116 +154,222 @@ pomelo! { ty, inner: ConstantInner::Sint(i.1) }); + extra.context.expressions.append(Expression::Constant(ch)) } - primary_expression ::= UintConstant; - primary_expression ::= FloatConstant; - primary_expression ::= BoolConstant; - primary_expression ::= DoubleConstant; - primary_expression ::= LeftParen expression RightParen; + // primary_expression ::= UintConstant; + // primary_expression ::= FloatConstant; + // primary_expression ::= BoolConstant; + // primary_expression ::= DoubleConstant; + // primary_expression ::= LeftParen expression RightParen; postfix_expression ::= primary_expression; - postfix_expression ::= postfix_expression LeftBracket integer_expression RightBracket; + postfix_expression ::= postfix_expression LeftBracket integer_expression RightBracket { + // TODO + return Err(ErrorKind::NotImplemented("[]")) + } postfix_expression ::= function_call; - postfix_expression ::= postfix_expression Dot FieldSelection; - postfix_expression ::= postfix_expression IncOp; - postfix_expression ::= postfix_expression DecOp; + postfix_expression ::= postfix_expression Dot FieldSelection { + // TODO + return Err(ErrorKind::NotImplemented(".field")) + } + postfix_expression ::= postfix_expression(pe) IncOp { + // TODO + return Err(ErrorKind::NotImplemented("post++")) + } + postfix_expression ::= postfix_expression(pe) DecOp { + // TODO + return Err(ErrorKind::NotImplemented("post--")) + } integer_expression ::= expression; function_call ::= function_call_generic; - function_call_generic ::= function_call_header_with_parameters RightParen; - function_call_generic ::= function_call_header_no_parameters RightParen; - function_call_header_no_parameters ::= function_call_header Void; + function_call_generic ::= function_call_header_with_parameters(h) RightParen {h} + function_call_generic ::= function_call_header_no_parameters(h) RightParen {h} + function_call_header_no_parameters ::= function_call_header(h) Void {h} function_call_header_no_parameters ::= function_call_header; - function_call_header_with_parameters ::= function_call_header assignment_expression; - function_call_header_with_parameters ::= function_call_header_with_parameters Comma assignment_expression; - function_call_header ::= function_identifier LeftParen; + function_call_header_with_parameters ::= function_call_header(h) assignment_expression(ae) { + if let Expression::Compose{ty, components} = extra.context.expressions.get_mut(h) { + components.push(ae.1); + } + //TODO: Call + h + } + function_call_header_with_parameters ::= function_call_header_with_parameters(h) Comma assignment_expression(ae) { + if let Expression::Compose{ty, components} = extra.context.expressions.get_mut(h) { + components.push(ae.1); + } + //TODO: Call + h + } + function_call_header ::= function_identifier(i) LeftParen {i} // Grammar Note: Constructors look like functions, but lexical analysis recognized most of them as // keywords. They are now recognized through “type_specifier”. // Methods (.length), subroutine array calls, and identifiers are recognized through postfix_expression. - function_identifier ::= type_specifier; + function_identifier ::= type_specifier(t) { + if let Some(ty) = t { + extra.context.expressions.append(Expression::Compose{ + ty, + components: vec![], + }) + } else { + return Err(ErrorKind::NotImplemented("bad type ctor")) + } + } function_identifier ::= postfix_expression; unary_expression ::= postfix_expression; - unary_expression ::= IncOp unary_expression; - unary_expression ::= DecOp unary_expression; - unary_expression ::= unary_operator unary_expression; + unary_expression ::= IncOp unary_expression { + // TODO + return Err(ErrorKind::NotImplemented("++pre")) + } + unary_expression ::= DecOp unary_expression { + // TODO + return Err(ErrorKind::NotImplemented("--pre")) + } + unary_expression ::= unary_operator unary_expression { + // TODO + return Err(ErrorKind::NotImplemented("unary_op")) + } + unary_operator ::= Plus; unary_operator ::= Dash; unary_operator ::= Bang; unary_operator ::= Tilde; multiplicative_expression ::= unary_expression; - multiplicative_expression ::= multiplicative_expression Star unary_expression; - multiplicative_expression ::= multiplicative_expression Slash unary_expression; - multiplicative_expression ::= multiplicative_expression Percent unary_expression; + multiplicative_expression ::= multiplicative_expression(left) Star unary_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Multiply, left, right}) + } + multiplicative_expression ::= multiplicative_expression(left) Slash unary_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Divide, left, right}) + } + multiplicative_expression ::= multiplicative_expression(left) Percent unary_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Modulo, left, right}) + } additive_expression ::= multiplicative_expression; - additive_expression ::= additive_expression Plus multiplicative_expression; - additive_expression ::= additive_expression Dash multiplicative_expression; + additive_expression ::= additive_expression(left) Plus multiplicative_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Add, left, right}) + } + additive_expression ::= additive_expression(left) Dash multiplicative_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Subtract, left, right}) + } shift_expression ::= additive_expression; - shift_expression ::= shift_expression LeftOp additive_expression; - shift_expression ::= shift_expression RightOp additive_expression; + shift_expression ::= shift_expression(left) LeftOp additive_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::ShiftLeftLogical, left, right}) + } + shift_expression ::= shift_expression(left) RightOp additive_expression(right) { + //TODO: when to use ShiftRightArithmetic + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::ShiftRightLogical, left, right}) + } relational_expression ::= shift_expression; - relational_expression ::= relational_expression LeftAngle shift_expression; - relational_expression ::= relational_expression RightAngle shift_expression; - relational_expression ::= relational_expression LeOp shift_expression; - relational_expression ::= relational_expression GeOp shift_expression; + relational_expression ::= relational_expression(left) LeftAngle shift_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Less, left, right}) + } + relational_expression ::= relational_expression(left) RightAngle shift_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Greater, left, right}) + } + relational_expression ::= relational_expression(left) LeOp shift_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::LessEqual, left, right}) + } + relational_expression ::= relational_expression(left) GeOp shift_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::GreaterEqual, left, right}) + } equality_expression ::= relational_expression; - equality_expression ::= equality_expression EqOp relational_expression; - equality_expression ::= equality_expression NeOp relational_expression; + equality_expression ::= equality_expression(left) EqOp relational_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::Equal, left, right}) + } + equality_expression ::= equality_expression(left) NeOp relational_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::NotEqual, left, right}) + } and_expression ::= equality_expression; - and_expression ::= and_expression Ampersand equality_expression; + and_expression ::= and_expression(left) Ampersand equality_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::And, left, right}) + } exclusive_or_expression ::= and_expression; - exclusive_or_expression ::= exclusive_or_expression Caret and_expression; + exclusive_or_expression ::= exclusive_or_expression(left) Caret and_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::ExclusiveOr, left, right}) + } inclusive_or_expression ::= exclusive_or_expression; - inclusive_or_expression ::= inclusive_or_expression VerticalBar exclusive_or_expression; + inclusive_or_expression ::= inclusive_or_expression(left) VerticalBar exclusive_or_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::InclusiveOr, left, right}) + } logical_and_expression ::= inclusive_or_expression; - logical_and_expression ::= logical_and_expression AndOp inclusive_or_expression; + logical_and_expression ::= logical_and_expression(left) AndOp inclusive_or_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::LogicalAnd, left, right}) + } logical_xor_expression ::= logical_and_expression; - logical_xor_expression ::= logical_xor_expression XorOp logical_and_expression; + logical_xor_expression ::= logical_xor_expression(left) XorOp logical_and_expression(right) { + return Err(ErrorKind::NotImplemented("logical xor")) + //TODO: naga doesn't have BinaryOperator::LogicalXor + // extra.context.expressions.append(Expression::Binary{op: BinaryOperator::LogicalXor, left, right}) + } logical_or_expression ::= logical_xor_expression; - logical_or_expression ::= logical_or_expression OrOp logical_xor_expression; + logical_or_expression ::= logical_or_expression(left) OrOp logical_xor_expression(right) { + extra.context.expressions.append(Expression::Binary{op: BinaryOperator::LogicalOr, left, right}) + } conditional_expression ::= logical_or_expression; - conditional_expression ::= logical_or_expression Question expression Colon assignment_expression; + conditional_expression ::= logical_or_expression Question expression Colon assignment_expression(ae) { + //TODO: how to do ternary here in naga? + return Err(ErrorKind::NotImplemented("ternary exp")) + } - assignment_expression ::= conditional_expression; - assignment_expression ::= unary_expression assignment_operator assignment_expression; + assignment_expression ::= conditional_expression(ce) { + (Statement::Empty, ce) + } + assignment_expression ::= unary_expression(pointer) assignment_operator(op) assignment_expression(value) { + match op { + BinaryOperator::Equal => (Statement::Store{pointer, value: value.1}, pointer), + //TODO: op != Equal + _ => {return Err(ErrorKind::NotImplemented("assign op"))} + } + } - assignment_operator ::= Equal; - assignment_operator ::= MulAssign; - assignment_operator ::= DivAssign; - assignment_operator ::= ModAssign; - assignment_operator ::= AddAssign; - assignment_operator ::= SubAssign; - assignment_operator ::= LeftAssign; - assignment_operator ::= RightAssign; - assignment_operator ::= AndAssign; - assignment_operator ::= XorAssign; - assignment_operator ::= OrAssign; + assignment_operator ::= Equal {BinaryOperator::Equal} + assignment_operator ::= MulAssign {BinaryOperator::Multiply} + assignment_operator ::= DivAssign {BinaryOperator::Divide} + assignment_operator ::= ModAssign {BinaryOperator::Modulo} + assignment_operator ::= AddAssign {BinaryOperator::Add} + assignment_operator ::= SubAssign {BinaryOperator::Subtract} + assignment_operator ::= LeftAssign {BinaryOperator::ShiftLeftLogical} + assignment_operator ::= RightAssign {BinaryOperator::ShiftRightLogical} + assignment_operator ::= AndAssign {BinaryOperator::And} + assignment_operator ::= XorAssign {BinaryOperator::ExclusiveOr} + assignment_operator ::= OrAssign {BinaryOperator::InclusiveOr} - expression ::= assignment_expression; - expression ::= expression Comma assignment_expression; + expression ::= assignment_expression(ae) {ae.0} + expression ::= expression(e) Comma assignment_expression(ae) { + match e { + Statement::Block(mut b) => { b.push(ae.0); Statement::Block(b) }, + e => Statement::Block(vec![e, ae.0]), + } + } // statement - statement ::= compound_statement; + statement ::= compound_statement(cs) {Statement::Block(cs)} statement ::= simple_statement; // Grammar Note: labeled statements for SWITCH only; 'goto' is not supported. //simple_statement ::= declaration_statement; simple_statement ::= expression_statement; + //simple_statement ::= selection_statement; + //simple_statement ::= switch_statement; + //simple_statement ::= case_label; + //simple_statement ::= iteration_statement; + //simple_statement ::= jump_statement; - compound_statement ::= LeftBrace RightBrace; - compound_statement ::= LeftBrace statement_list RightBrace; + compound_statement ::= LeftBrace RightBrace {vec![]} + compound_statement ::= LeftBrace statement_list(sl) RightBrace {sl} - compound_statement_no_new_scope ::= LeftBrace RightBrace; - compound_statement_no_new_scope ::= LeftBrace statement_list RightBrace; + compound_statement_no_new_scope ::= LeftBrace RightBrace {vec![]} + compound_statement_no_new_scope ::= LeftBrace statement_list(sl) RightBrace {sl} - statement_list ::= statement(s) { /*vec![s]*/ } - statement_list ::= statement_list/*(mut ss)*/ statement(s) { /*ss.push(s); ss*/ } + statement_list ::= statement(s) { vec![s] } + statement_list ::= statement_list(mut ss) statement(s) { ss.push(s); ss } - expression_statement ::= Semicolon; - expression_statement ::= expression Semicolon; + expression_statement ::= Semicolon {Statement::Empty} + expression_statement ::= expression(e) Semicolon {e} @@ -280,7 +426,10 @@ pomelo! { } } - function_definition ::= function_prototype(f) compound_statement_no_new_scope { + function_definition ::= function_prototype(mut f) compound_statement_no_new_scope(cs) { + std::mem::swap(&mut f.expressions, &mut extra.context.expressions); + std::mem::swap(&mut f.local_variables, &mut extra.context.local_variables); + f.body = cs; f }; }