mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[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
This commit is contained in:
@@ -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<Type>,
|
||||
pub constants: Arena<Constant>,
|
||||
pub global_variables: Arena<GlobalVariable>,
|
||||
pub context: Context,
|
||||
}
|
||||
|
||||
impl Program {
|
||||
@@ -25,6 +29,10 @@ impl Program {
|
||||
types: Arena::<Type>::new(),
|
||||
constants: Arena::<Constant>::new(),
|
||||
global_variables: Arena::<GlobalVariable>::new(),
|
||||
context: Context {
|
||||
expressions: Arena::<Expression>::new(),
|
||||
local_variables: Arena::<LocalVariable>::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,3 +41,9 @@ impl Program {
|
||||
pub enum Profile {
|
||||
Core,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Context {
|
||||
pub expressions: Arena<Expression>,
|
||||
pub local_variables: Arena<LocalVariable>,
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String>;
|
||||
|
||||
// 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<Expression>;
|
||||
%type postfix_expression Handle<Expression>;
|
||||
%type primary_expression Handle<Expression>;
|
||||
%type variable_identifier Handle<Expression>;
|
||||
|
||||
%type function_call Handle<Expression>;
|
||||
%type function_call_generic Handle<Expression>;
|
||||
%type function_call_header_no_parameters Handle<Expression>;
|
||||
%type function_call_header_with_parameters Handle<Expression>;
|
||||
%type function_call_header Handle<Expression>;
|
||||
%type function_identifier Handle<Expression>;
|
||||
|
||||
%type multiplicative_expression Handle<Expression>;
|
||||
%type additive_expression Handle<Expression>;
|
||||
%type shift_expression Handle<Expression>;
|
||||
%type relational_expression Handle<Expression>;
|
||||
%type equality_expression Handle<Expression>;
|
||||
%type and_expression Handle<Expression>;
|
||||
%type exclusive_or_expression Handle<Expression>;
|
||||
%type inclusive_or_expression Handle<Expression>;
|
||||
%type logical_and_expression Handle<Expression>;
|
||||
%type logical_xor_expression Handle<Expression>;
|
||||
%type logical_or_expression Handle<Expression>;
|
||||
%type conditional_expression Handle<Expression>;
|
||||
|
||||
%type assignment_expression (Statement, Handle<Expression>);
|
||||
%type assignment_operator BinaryOperator;
|
||||
%type expression Statement;
|
||||
|
||||
// types
|
||||
%type fully_specified_type Option<Handle<Type>>;
|
||||
%type type_specifier Option<Handle<Type>>;
|
||||
%type type_specifier_nonarray Option<Type>;
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user