Skip to content

Commit

Permalink
[glsl-in] Allow code after terminator statements (gfx-rs#1308)
Browse files Browse the repository at this point in the history
* [glsl-in] Allow code after terminator statements

* [glsl-in] Track finished state in the context

* [glsl-in] Cull statements after terminators
  • Loading branch information
JCapucho authored Aug 31, 2021
1 parent 995a775 commit bd411c2
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 23 deletions.
3 changes: 2 additions & 1 deletion src/front/glsl/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,14 +643,15 @@ impl Parser {
.0;

ctx.emit_flush(body);
ctx.emit_start();

body.push(
Statement::Store {
pointer: target,
value,
},
meta.as_span(),
);
ctx.emit_start();
}

Ok(result)
Expand Down
80 changes: 58 additions & 22 deletions src/front/glsl/parser/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ impl<'source> ParsingContext<'source> {
parser: &mut Parser,
ctx: &mut Context,
body: &mut Block,
terminator: &mut Option<usize>,
) -> Result<Option<SourceMetadata>> {
// TODO: This prevents snippets like the following from working
// ```glsl
Expand All @@ -62,11 +63,15 @@ impl<'source> ParsingContext<'source> {

let meta_rest = match *value {
TokenValue::Continue => {
body.push(Statement::Continue, self.bump(parser)?.meta.as_span());
let meta = self.bump(parser)?.meta;
body.push(Statement::Continue, meta.as_span());
terminator.get_or_insert(body.len());
self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::Break => {
body.push(Statement::Break, self.bump(parser)?.meta.as_span());
let meta = self.bump(parser)?.meta;
body.push(Statement::Break, meta.as_span());
terminator.get_or_insert(body.len());
self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::Return => {
Expand All @@ -88,10 +93,15 @@ impl<'source> ParsingContext<'source> {
ctx.emit_start();

body.push(Statement::Return { value }, meta.as_span());
terminator.get_or_insert(body.len());

meta
}
TokenValue::Discard => {
body.push(Statement::Kill, self.bump(parser)?.meta.as_span());
let meta = self.bump(parser)?.meta;
body.push(Statement::Kill, meta.as_span());
terminator.get_or_insert(body.len());

self.expect(parser, TokenValue::Semicolon)?.meta
}
TokenValue::If => {
Expand All @@ -112,13 +122,17 @@ impl<'source> ParsingContext<'source> {
ctx.emit_start();

let mut accept = Block::new();
if let Some(more_meta) = self.parse_statement(parser, ctx, &mut accept)? {
if let Some(more_meta) =
self.parse_statement(parser, ctx, &mut accept, &mut None)?
{
meta = meta.union(&more_meta)
}

let mut reject = Block::new();
if self.bump_if(parser, TokenValue::Else).is_some() {
if let Some(more_meta) = self.parse_statement(parser, ctx, &mut reject)? {
if let Some(more_meta) =
self.parse_statement(parser, ctx, &mut reject, &mut None)?
{
meta = meta.union(&more_meta);
}
}
Expand All @@ -131,6 +145,7 @@ impl<'source> ParsingContext<'source> {
},
meta.as_span(),
);

meta
}
TokenValue::Switch => {
Expand Down Expand Up @@ -190,25 +205,32 @@ impl<'source> ParsingContext<'source> {

let mut body = Block::new();

let mut case_terminator = None;
loop {
match self.expect_peek(parser)?.value {
TokenValue::Case
| TokenValue::Default
| TokenValue::RightBrace => break,
_ => {
self.parse_statement(parser, ctx, &mut body)?;
self.parse_statement(
parser,
ctx,
&mut body,
&mut case_terminator,
)?;
}
}
}

let mut fall_through = true;

for (i, stmt) in body.iter().enumerate() {
if let Statement::Break = *stmt {
if let Some(mut idx) = case_terminator {
if let Statement::Break = body[idx - 1] {
fall_through = false;
body.cull(i..);
break;
idx -= 1;
}

body.cull(idx..)
}

cases.push(SwitchCase {
Expand All @@ -231,21 +253,20 @@ impl<'source> ParsingContext<'source> {
});
}

let mut default_terminator = None;
loop {
match self.expect_peek(parser)?.value {
TokenValue::Case | TokenValue::RightBrace => break,
_ => {
self.parse_statement(parser, ctx, &mut default)?;
self.parse_statement(
parser,
ctx,
&mut default,
&mut default_terminator,
)?;
}
}
}

for (i, stmt) in default.iter().enumerate() {
if let Statement::Break = *stmt {
default.cull(i..);
break;
}
}
}
TokenValue::RightBrace => {
end_meta = self.bump(parser)?.meta;
Expand All @@ -269,6 +290,7 @@ impl<'source> ParsingContext<'source> {
}

let meta = start_meta.union(&end_meta);

body.push(
Statement::Switch {
selector,
Expand All @@ -277,6 +299,7 @@ impl<'source> ParsingContext<'source> {
},
meta.as_span(),
);

meta
}
TokenValue::While => {
Expand Down Expand Up @@ -314,7 +337,9 @@ impl<'source> ParsingContext<'source> {

let mut meta = meta.union(&expr_meta);

if let Some(body_meta) = self.parse_statement(parser, ctx, &mut loop_body)? {
if let Some(body_meta) =
self.parse_statement(parser, ctx, &mut loop_body, &mut None)?
{
meta = meta.union(&body_meta);
}

Expand All @@ -325,13 +350,15 @@ impl<'source> ParsingContext<'source> {
},
meta.as_span(),
);

meta
}
TokenValue::Do => {
let start_meta = self.bump(parser)?.meta;

let mut loop_body = Block::new();
self.parse_statement(parser, ctx, &mut loop_body)?;

self.parse_statement(parser, ctx, &mut loop_body, &mut None)?;

let mut stmt = ctx.stmt_ctx();

Expand Down Expand Up @@ -372,6 +399,7 @@ impl<'source> ParsingContext<'source> {
},
meta.as_span(),
);

meta
}
TokenValue::For => {
Expand Down Expand Up @@ -464,7 +492,7 @@ impl<'source> ParsingContext<'source> {

let mut meta = meta.union(&self.expect(parser, TokenValue::RightParen)?.meta);

if let Some(stmt_meta) = self.parse_statement(parser, ctx, &mut block)? {
if let Some(stmt_meta) = self.parse_statement(parser, ctx, &mut block, &mut None)? {
meta = meta.union(&stmt_meta);
}

Expand All @@ -489,6 +517,7 @@ impl<'source> ParsingContext<'source> {
let meta = self.parse_compound_statement(meta, parser, ctx, &mut block)?;

ctx.remove_current_scope();

body.push(Statement::Block(block), meta.as_span());

meta
Expand All @@ -515,6 +544,7 @@ impl<'source> ParsingContext<'source> {
ctx: &mut Context,
body: &mut Block,
) -> Result<SourceMetadata> {
let mut terminator = None;
loop {
if let Some(Token {
meta: brace_meta, ..
Expand All @@ -524,11 +554,17 @@ impl<'source> ParsingContext<'source> {
break;
}

if let Some(stmt_meta) = self.parse_statement(parser, ctx, body)? {
let stmt = self.parse_statement(parser, ctx, body, &mut terminator)?;

if let Some(stmt_meta) = stmt {
meta = meta.union(&stmt_meta);
}
}

if let Some(idx) = terminator {
body.cull(idx..)
}

Ok(meta)
}

Expand Down

0 comments on commit bd411c2

Please sign in to comment.