[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:
Pelle Johnsen
2020-07-29 04:48:05 +02:00
committed by GitHub
parent 115c29c022
commit 1eb637038d
3 changed files with 236 additions and 71 deletions

View File

@@ -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>,
}

View File

@@ -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),
}
}
}

View File

@@ -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
};
}