[glsl-in] Don't clone HirExpr when lowering

This commit is contained in:
João Capucho
2021-08-10 14:50:13 +01:00
committed by Dzmitry Malyshau
parent 07c286255d
commit e384bce771
7 changed files with 237 additions and 116 deletions

View File

@@ -240,6 +240,11 @@ impl<T> Arena<T> {
marker: PhantomData,
}
}
/// Clears the arena keeping all allocations
pub fn clear(&mut self) {
self.data.clear()
}
}
impl<T> ops::Index<Handle<T>> for Arena<T> {

View File

@@ -29,9 +29,9 @@ pub struct Context {
pub lookup_global_var_exps: FastHashMap<String, VariableReference>,
pub samplers: FastHashMap<Handle<Expression>, Handle<Expression>>,
pub hir_exprs: Arena<HirExpr>,
pub typifier: Typifier,
emitter: Emitter,
stmt_ctx: Option<StmtContext>,
}
impl Context {
@@ -51,9 +51,9 @@ impl Context {
),
samplers: FastHashMap::default(),
hir_exprs: Arena::default(),
typifier: Typifier::new(),
emitter: Emitter::default(),
stmt_ctx: Some(StmtContext::new()),
};
this.emit_start();
@@ -280,14 +280,71 @@ impl Context {
self.scopes.pop();
}
/// Returns a [`StmtContext`](StmtContext) to be used in parsing and lowering
///
/// # Panics
/// - If more than one [`StmtContext`](StmtContext) are active at the same
/// time or if the previous call didn't use it in lowering.
#[must_use]
pub fn stmt_ctx(&mut self) -> StmtContext {
self.stmt_ctx.take().unwrap()
}
/// Lowers a [`HirExpr`](HirExpr) which might produce a [`Expression`](Expression).
///
/// consumes a [`StmtContext`](StmtContext) returning it to the context so
/// that it can be used again later.
pub fn lower(
&mut self,
mut stmt: StmtContext,
parser: &mut Parser,
expr: Handle<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Option<Handle<Expression>>, SourceMetadata)> {
let res = self.lower_inner(&stmt, parser, expr, lhs, body);
stmt.hir_exprs.clear();
self.stmt_ctx = Some(stmt);
res
}
/// Similar to [`lower`](Self::lower) but returns an error if the expression
/// returns void (ie. doesn't produce a [`Expression`](Expression)).
///
/// consumes a [`StmtContext`](StmtContext) returning it to the context so
/// that it can be used again later.
pub fn lower_expect(
&mut self,
mut stmt: StmtContext,
parser: &mut Parser,
expr: Handle<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Handle<Expression>, SourceMetadata)> {
let (maybe_expr, meta) = self.lower(parser, expr, lhs, body)?;
let res = self.lower_expect_inner(&stmt, parser, expr, lhs, body);
stmt.hir_exprs.clear();
self.stmt_ctx = Some(stmt);
res
}
/// internal implementation of [`lower_expect`](Self::lower_expect)
///
/// this method is only public because it's used in
/// [`function_call`](Parser::function_call), unless you know what
/// you're doing use [`lower_expect`](Self::lower_expect)
pub fn lower_expect_inner(
&mut self,
stmt: &StmtContext,
parser: &mut Parser,
expr: Handle<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Handle<Expression>, SourceMetadata)> {
let (maybe_expr, meta) = self.lower_inner(stmt, parser, expr, lhs, body)?;
let expr = match maybe_expr {
Some(e) => e,
@@ -302,19 +359,22 @@ impl Context {
Ok((expr, meta))
}
pub fn lower(
/// Internal implementation of [`lower`](Self::lower)
fn lower_inner(
&mut self,
stmt: &StmtContext,
parser: &mut Parser,
expr: Handle<HirExpr>,
lhs: bool,
body: &mut Block,
) -> Result<(Option<Handle<Expression>>, SourceMetadata)> {
let HirExpr { kind, meta } = self.hir_exprs[expr].clone();
let HirExpr { ref kind, meta } = stmt.hir_exprs[expr];
let handle = match kind {
let handle = match *kind {
HirExprKind::Access { base, index } => {
let base = self.lower_expect(parser, base, true, body)?.0;
let (index, index_meta) = self.lower_expect(parser, index, false, body)?;
let base = self.lower_expect_inner(stmt, parser, base, true, body)?.0;
let (index, index_meta) =
self.lower_expect_inner(stmt, parser, index, false, body)?;
let pointer = parser
.solve_constant(self, index, index_meta)
@@ -354,17 +414,19 @@ impl Context {
pointer
}
HirExprKind::Select { base, field } => {
let base = self.lower_expect(parser, base, lhs, body)?.0;
HirExprKind::Select { base, ref field } => {
let base = self.lower_expect_inner(stmt, parser, base, lhs, body)?.0;
parser.field_selection(self, lhs, body, base, &field, meta)?
parser.field_selection(self, lhs, body, base, field, meta)?
}
HirExprKind::Constant(constant) if !lhs => {
self.add_expression(Expression::Constant(constant), body)
}
HirExprKind::Binary { left, op, right } if !lhs => {
let (mut left, left_meta) = self.lower_expect(parser, left, false, body)?;
let (mut right, right_meta) = self.lower_expect(parser, right, false, body)?;
let (mut left, left_meta) =
self.lower_expect_inner(stmt, parser, left, false, body)?;
let (mut right, right_meta) =
self.lower_expect_inner(stmt, parser, right, false, body)?;
match op {
BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight => self
@@ -439,11 +501,11 @@ impl Context {
}
}
HirExprKind::Unary { op, expr } if !lhs => {
let expr = self.lower_expect(parser, expr, false, body)?.0;
let expr = self.lower_expect_inner(stmt, parser, expr, false, body)?.0;
self.add_expression(Expression::Unary { op, expr }, body)
}
HirExprKind::Variable(var) => {
HirExprKind::Variable(ref var) => {
if lhs {
if !var.mutable {
parser.errors.push(Error {
@@ -461,9 +523,15 @@ impl Context {
var.expr
}
}
HirExprKind::Call(call) if !lhs => {
let maybe_expr =
parser.function_or_constructor_call(self, body, call.kind, &call.args, meta)?;
HirExprKind::Call(ref call) if !lhs => {
let maybe_expr = parser.function_or_constructor_call(
self,
stmt,
body,
call.kind.clone(),
&call.args,
meta,
)?;
return Ok((maybe_expr, meta));
}
HirExprKind::Conditional {
@@ -471,9 +539,13 @@ impl Context {
accept,
reject,
} if !lhs => {
let condition = self.lower_expect(parser, condition, false, body)?.0;
let (mut accept, accept_meta) = self.lower_expect(parser, accept, false, body)?;
let (mut reject, reject_meta) = self.lower_expect(parser, reject, false, body)?;
let condition = self
.lower_expect_inner(stmt, parser, condition, false, body)?
.0;
let (mut accept, accept_meta) =
self.lower_expect_inner(stmt, parser, accept, false, body)?;
let (mut reject, reject_meta) =
self.lower_expect_inner(stmt, parser, reject, false, body)?;
self.binary_implicit_conversion(
parser,
@@ -493,8 +565,9 @@ impl Context {
)
}
HirExprKind::Assign { tgt, value } if !lhs => {
let (pointer, ptr_meta) = self.lower_expect(parser, tgt, true, body)?;
let (mut value, value_meta) = self.lower_expect(parser, value, false, body)?;
let (pointer, ptr_meta) = self.lower_expect_inner(stmt, parser, tgt, true, body)?;
let (mut value, value_meta) =
self.lower_expect_inner(stmt, parser, value, false, body)?;
let scalar_components = self.expr_scalar_components(parser, pointer, ptr_meta)?;
@@ -564,7 +637,7 @@ impl Context {
false => BinaryOperator::Subtract,
};
let pointer = self.lower_expect(parser, expr, true, body)?.0;
let pointer = self.lower_expect_inner(stmt, parser, expr, true, body)?.0;
let left = self.add_expression(Expression::Load { pointer }, body);
let uint = match parser.resolve_type(self, left, meta)?.scalar_kind() {
@@ -641,7 +714,7 @@ impl Context {
_ => {
return Err(Error {
kind: ErrorKind::SemanticError(
format!("{:?} cannot be in the left hand side", self.hir_exprs[expr])
format!("{:?} cannot be in the left hand side", stmt.hir_exprs[expr])
.into(),
),
meta,
@@ -779,3 +852,22 @@ impl Index<Handle<Expression>> for Context {
&self.expressions[index]
}
}
/// Helper struct passed when parsing expressions
///
/// This struct should only be obtained trough [`stmt_ctx`](Context::stmt_ctx)
/// and only one of these may be active at any time per context.
#[derive(Debug)]
pub struct StmtContext {
/// A arena of high level expressions which can be lowered trough a
/// [`Context`](Context) to naga's [`Expression`](crate::Expression)s
pub hir_exprs: Arena<HirExpr>,
}
impl StmtContext {
fn new() -> Self {
StmtContext {
hir_exprs: Arena::new(),
}
}
}

View File

@@ -1,6 +1,6 @@
use super::{
ast::*,
context::Context,
context::{Context, StmtContext},
error::{Error, ErrorKind},
types::{scalar_components, type_power},
Parser, Result, SourceMetadata,
@@ -41,6 +41,7 @@ impl Parser {
pub(crate) fn function_or_constructor_call(
&mut self,
ctx: &mut Context,
stmt: &StmtContext,
body: &mut Block,
fc: FunctionCallKind,
raw_args: &[Handle<HirExpr>],
@@ -48,7 +49,7 @@ impl Parser {
) -> Result<Option<Handle<Expression>>> {
let args: Vec<_> = raw_args
.iter()
.map(|e| ctx.lower_expect(self, *e, false, body))
.map(|e| ctx.lower_expect_inner(stmt, self, *e, false, body))
.collect::<Result<_>>()?;
match fc {
@@ -307,14 +308,16 @@ impl Parser {
Ok(Some(h))
}
FunctionCallKind::Function(name) => {
self.function_call(ctx, body, name, args, raw_args, meta)
self.function_call(ctx, stmt, body, name, args, raw_args, meta)
}
}
}
#[allow(clippy::too_many_arguments)]
fn function_call(
&mut self,
ctx: &mut Context,
stmt: &StmtContext,
body: &mut Block,
name: String,
mut args: Vec<(Handle<Expression>, SourceMetadata)>,
@@ -969,8 +972,13 @@ impl Parser {
.iter()
.zip(raw_args.iter().zip(parameters.iter()))
{
let (mut handle, meta) =
ctx.lower_expect(self, *expr, parameter_info.qualifier.is_lhs(), body)?;
let (mut handle, meta) = ctx.lower_expect_inner(
stmt,
self,
*expr,
parameter_info.qualifier.is_lhs(),
body,
)?;
if let TypeInner::Vector { size, kind, width } =
*self.resolve_type(ctx, handle, meta)?
@@ -1025,27 +1033,16 @@ impl Parser {
ctx.emit_start();
for (tgt, pointer) in proxy_writes {
let temp_ref = ctx.hir_exprs.append(HirExpr {
kind: HirExprKind::Variable(VariableReference {
expr: pointer,
load: true,
mutable: true,
entry_arg: None,
}),
meta,
});
let assign = ctx.hir_exprs.append(HirExpr {
kind: HirExprKind::Assign {
tgt,
value: temp_ref,
},
meta,
});
let value = ctx.add_expression(Expression::Load { pointer }, body);
let target = ctx.lower_expect_inner(stmt, self, tgt, true, body)?.0;
let _ = ctx.lower_expect(self, assign, false, body)?;
ctx.emit_flush(body);
body.push(Statement::Store {
pointer: target,
value,
});
ctx.emit_start();
}
ctx.emit_flush(body);
ctx.emit_start();
Ok(result)
}

View File

@@ -192,8 +192,9 @@ impl<'source> ParsingContext<'source> {
let mut ctx = Context::new(parser, &mut block);
let expr = self.parse_conditional(parser, &mut ctx, &mut block, None)?;
let (root, meta) = ctx.lower_expect(parser, expr, false, &mut block)?;
let mut stmt_ctx = ctx.stmt_ctx();
let expr = self.parse_conditional(parser, &mut ctx, &mut stmt_ctx, &mut block, None)?;
let (root, meta) = ctx.lower_expect(stmt_ctx, parser, expr, false, &mut block)?;
Ok((parser.solve_constant(&ctx, root, meta)?, meta))
}

View File

@@ -98,8 +98,9 @@ impl<'source> ParsingContext<'source> {
meta,
))
} else {
let expr = self.parse_assignment(parser, ctx, body)?;
let (mut init, init_meta) = ctx.lower_expect(parser, expr, false, body)?;
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_assignment(parser, ctx, &mut stmt, body)?;
let (mut init, init_meta) = ctx.lower_expect(stmt, parser, expr, false, body)?;
let scalar_components = scalar_components(&parser.module.types[ty].inner);
if let Some((kind, width)) = scalar_components {

View File

@@ -1,7 +1,7 @@
use crate::{
front::glsl::{
ast::{FunctionCall, FunctionCallKind, HirExpr, HirExprKind},
context::Context,
context::{Context, StmtContext},
error::{ErrorKind, ExpectedToken},
parser::ParsingContext,
token::{Token, TokenValue},
@@ -16,6 +16,7 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
) -> Result<Handle<HirExpr>> {
let mut token = self.bump(parser)?;
@@ -35,7 +36,7 @@ impl<'source> ParsingContext<'source> {
),
TokenValue::BoolConstant(value) => (1, ScalarValue::Bool(value)),
TokenValue::LeftParen => {
let expr = self.parse_expression(parser, ctx, body)?;
let expr = self.parse_expression(parser, ctx, stmt, body)?;
let meta = self.expect(parser, TokenValue::RightParen)?.meta;
token.meta = token.meta.union(&meta);
@@ -64,7 +65,7 @@ impl<'source> ParsingContext<'source> {
inner: ConstantInner::Scalar { width, value },
});
Ok(ctx.hir_exprs.append(HirExpr {
Ok(stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Constant(handle),
meta: token.meta,
}))
@@ -74,6 +75,7 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
meta: &mut SourceMetadata,
) -> Result<Vec<Handle<HirExpr>>> {
@@ -82,7 +84,7 @@ impl<'source> ParsingContext<'source> {
*meta = meta.union(&token.meta);
} else {
loop {
args.push(self.parse_assignment(parser, ctx, body)?);
args.push(self.parse_assignment(parser, ctx, stmt, body)?);
let token = self.bump(parser)?;
match token.value {
@@ -111,6 +113,7 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
) -> Result<Handle<HirExpr>> {
let mut base = match self.expect_peek(parser)?.value {
@@ -118,7 +121,7 @@ impl<'source> ParsingContext<'source> {
let (name, mut meta) = self.expect_ident(parser)?;
let expr = if self.bump_if(parser, TokenValue::LeftParen).is_some() {
let args = self.parse_function_call_args(parser, ctx, body, &mut meta)?;
let args = self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?;
let kind = match parser.lookup_type.get(&name) {
Some(ty) => FunctionCallKind::TypeConstructor(*ty),
@@ -146,7 +149,7 @@ impl<'source> ParsingContext<'source> {
}
};
ctx.hir_exprs.append(expr)
stmt.hir_exprs.append(expr)
}
TokenValue::TypeName(_) => {
let Token { value, mut meta } = self.bump(parser)?;
@@ -160,7 +163,7 @@ impl<'source> ParsingContext<'source> {
let maybe_size = self.parse_array_specifier(parser)?;
self.expect(parser, TokenValue::LeftParen)?;
let args = self.parse_function_call_args(parser, ctx, body, &mut meta)?;
let args = self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?;
if let Some(array_size) = maybe_size {
let stride = parser.module.types[handle]
@@ -193,7 +196,7 @@ impl<'source> ParsingContext<'source> {
})
}
ctx.hir_exprs.append(HirExpr {
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Call(FunctionCall {
kind: FunctionCallKind::TypeConstructor(handle),
args,
@@ -201,7 +204,7 @@ impl<'source> ParsingContext<'source> {
meta,
})
}
_ => self.parse_primary(parser, ctx, body)?,
_ => self.parse_primary(parser, ctx, stmt, body)?,
};
while let TokenValue::LeftBracket
@@ -213,10 +216,10 @@ impl<'source> ParsingContext<'source> {
match value {
TokenValue::LeftBracket => {
let index = self.parse_expression(parser, ctx, body)?;
let index = self.parse_expression(parser, ctx, stmt, body)?;
let end_meta = self.expect(parser, TokenValue::RightBracket)?.meta;
base = ctx.hir_exprs.append(HirExpr {
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Access { base, index },
meta: meta.union(&end_meta),
})
@@ -224,13 +227,13 @@ impl<'source> ParsingContext<'source> {
TokenValue::Dot => {
let (field, end_meta) = self.expect_ident(parser)?;
base = ctx.hir_exprs.append(HirExpr {
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Select { base, field },
meta: meta.union(&end_meta),
})
}
TokenValue::Increment => {
base = ctx.hir_exprs.append(HirExpr {
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::IncDec {
increment: true,
postfix: true,
@@ -240,7 +243,7 @@ impl<'source> ParsingContext<'source> {
})
}
TokenValue::Decrement => {
base = ctx.hir_exprs.append(HirExpr {
base = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::IncDec {
increment: false,
postfix: true,
@@ -260,6 +263,7 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
) -> Result<Handle<HirExpr>> {
// TODO: prefix inc/dec
@@ -267,8 +271,8 @@ impl<'source> ParsingContext<'source> {
TokenValue::Plus | TokenValue::Dash | TokenValue::Bang | TokenValue::Tilde => {
let Token { value, meta } = self.bump(parser)?;
let expr = self.parse_unary(parser, ctx, body)?;
let end_meta = ctx.hir_exprs[expr].meta;
let expr = self.parse_unary(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[expr].meta;
let kind = match value {
TokenValue::Dash => HirExprKind::Unary {
@@ -282,7 +286,7 @@ impl<'source> ParsingContext<'source> {
_ => return Ok(expr),
};
ctx.hir_exprs.append(HirExpr {
stmt.hir_exprs.append(HirExpr {
kind,
meta: meta.union(&end_meta),
})
@@ -290,9 +294,9 @@ impl<'source> ParsingContext<'source> {
TokenValue::Increment | TokenValue::Decrement => {
let Token { value, meta } = self.bump(parser)?;
let expr = self.parse_unary(parser, ctx, body)?;
let expr = self.parse_unary(parser, ctx, stmt, body)?;
ctx.hir_exprs.append(HirExpr {
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::IncDec {
increment: match value {
TokenValue::Increment => true,
@@ -305,7 +309,7 @@ impl<'source> ParsingContext<'source> {
meta,
})
}
_ => self.parse_postfix(parser, ctx, body)?,
_ => self.parse_postfix(parser, ctx, stmt, body)?,
})
}
@@ -313,14 +317,15 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
passtrough: Option<Handle<HirExpr>>,
min_bp: u8,
) -> Result<Handle<HirExpr>> {
let mut left = passtrough
.ok_or(ErrorKind::EndOfFile /* Dummy error */)
.or_else(|_| self.parse_unary(parser, ctx, body))?;
let start_meta = ctx.hir_exprs[left].meta;
.or_else(|_| self.parse_unary(parser, ctx, stmt, body))?;
let start_meta = stmt.hir_exprs[left].meta;
while let Some((l_bp, r_bp)) = binding_power(&self.expect_peek(parser)?.value) {
if l_bp < min_bp {
@@ -329,10 +334,10 @@ impl<'source> ParsingContext<'source> {
let Token { value, .. } = self.bump(parser)?;
let right = self.parse_binary(parser, ctx, body, None, r_bp)?;
let end_meta = ctx.hir_exprs[right].meta;
let right = self.parse_binary(parser, ctx, stmt, body, None, r_bp)?;
let end_meta = stmt.hir_exprs[right].meta;
left = ctx.hir_exprs.append(HirExpr {
left = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Binary {
left,
op: match value {
@@ -370,19 +375,20 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
passtrough: Option<Handle<HirExpr>>,
) -> Result<Handle<HirExpr>> {
let mut condition = self.parse_binary(parser, ctx, body, passtrough, 0)?;
let start_meta = ctx.hir_exprs[condition].meta;
let mut condition = self.parse_binary(parser, ctx, stmt, body, passtrough, 0)?;
let start_meta = stmt.hir_exprs[condition].meta;
if self.bump_if(parser, TokenValue::Question).is_some() {
let accept = self.parse_expression(parser, ctx, body)?;
let accept = self.parse_expression(parser, ctx, stmt, body)?;
self.expect(parser, TokenValue::Colon)?;
let reject = self.parse_assignment(parser, ctx, body)?;
let end_meta = ctx.hir_exprs[reject].meta;
let reject = self.parse_assignment(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[reject].meta;
condition = ctx.hir_exprs.append(HirExpr {
condition = stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Conditional {
condition,
accept,
@@ -399,18 +405,19 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
) -> Result<Handle<HirExpr>> {
let tgt = self.parse_unary(parser, ctx, body)?;
let start_meta = ctx.hir_exprs[tgt].meta;
let tgt = self.parse_unary(parser, ctx, stmt, body)?;
let start_meta = stmt.hir_exprs[tgt].meta;
Ok(match self.expect_peek(parser)?.value {
TokenValue::Assign => {
self.bump(parser)?;
let value = self.parse_assignment(parser, ctx, body)?;
let end_meta = ctx.hir_exprs[value].meta;
let value = self.parse_assignment(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[value].meta;
ctx.hir_exprs.append(HirExpr {
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Assign { tgt, value },
meta: start_meta.union(&end_meta),
})
@@ -426,10 +433,10 @@ impl<'source> ParsingContext<'source> {
| TokenValue::RightShiftAssign
| TokenValue::XorAssign => {
let token = self.bump(parser)?;
let right = self.parse_assignment(parser, ctx, body)?;
let end_meta = ctx.hir_exprs[right].meta;
let right = self.parse_assignment(parser, ctx, stmt, body)?;
let end_meta = stmt.hir_exprs[right].meta;
let value = ctx.hir_exprs.append(HirExpr {
let value = stmt.hir_exprs.append(HirExpr {
meta: start_meta.union(&end_meta),
kind: HirExprKind::Binary {
left: tgt,
@@ -450,12 +457,12 @@ impl<'source> ParsingContext<'source> {
},
});
ctx.hir_exprs.append(HirExpr {
stmt.hir_exprs.append(HirExpr {
kind: HirExprKind::Assign { tgt, value },
meta: start_meta.union(&end_meta),
})
}
_ => self.parse_conditional(parser, ctx, body, Some(tgt))?,
_ => self.parse_conditional(parser, ctx, stmt, body, Some(tgt))?,
})
}
@@ -463,13 +470,14 @@ impl<'source> ParsingContext<'source> {
&mut self,
parser: &mut Parser,
ctx: &mut Context,
stmt: &mut StmtContext,
body: &mut Block,
) -> Result<Handle<HirExpr>> {
let mut expr = self.parse_assignment(parser, ctx, body)?;
let mut expr = self.parse_assignment(parser, ctx, stmt, body)?;
while let TokenValue::Comma = self.expect_peek(parser)?.value {
self.bump(parser)?;
expr = self.parse_assignment(parser, ctx, body)?;
expr = self.parse_assignment(parser, ctx, stmt, body)?;
}
Ok(expr)

View File

@@ -71,9 +71,10 @@ impl<'source> ParsingContext<'source> {
}
_ => {
// TODO: Implicit conversions
let expr = self.parse_expression(parser, ctx, body)?;
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
self.expect(parser, TokenValue::Semicolon)?;
Some(ctx.lower_expect(parser, expr, false, body)?.0)
Some(ctx.lower_expect(stmt, parser, expr, false, body)?.0)
}
};
@@ -92,8 +93,9 @@ impl<'source> ParsingContext<'source> {
self.expect(parser, TokenValue::LeftParen)?;
let condition = {
let expr = self.parse_expression(parser, ctx, body)?;
ctx.lower_expect(parser, expr, false, body)?.0
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
ctx.lower_expect(stmt, parser, expr, false, body)?.0
};
self.expect(parser, TokenValue::RightParen)?;
@@ -120,8 +122,9 @@ impl<'source> ParsingContext<'source> {
self.expect(parser, TokenValue::LeftParen)?;
// TODO: Implicit conversions
let selector = {
let expr = self.parse_expression(parser, ctx, body)?;
ctx.lower_expect(parser, expr, false, body)?.0
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
ctx.lower_expect(stmt, parser, expr, false, body)?.0
};
self.expect(parser, TokenValue::RightParen)?;
@@ -137,8 +140,10 @@ impl<'source> ParsingContext<'source> {
TokenValue::Case => {
self.bump(parser)?;
let value = {
let expr = self.parse_expression(parser, ctx, body)?;
let (root, meta) = ctx.lower_expect(parser, expr, false, body)?;
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
let (root, meta) =
ctx.lower_expect(stmt, parser, expr, false, body)?;
let constant = parser.solve_constant(ctx, root, meta)?;
match parser.module.constants[constant].inner {
@@ -252,11 +257,14 @@ impl<'source> ParsingContext<'source> {
let mut loop_body = Block::new();
let mut stmt = ctx.stmt_ctx();
self.expect(parser, TokenValue::LeftParen)?;
let root = self.parse_expression(parser, ctx, &mut loop_body)?;
let root = self.parse_expression(parser, ctx, &mut stmt, &mut loop_body)?;
self.expect(parser, TokenValue::RightParen)?;
let expr = ctx.lower_expect(parser, root, false, &mut loop_body)?.0;
let expr = ctx
.lower_expect(stmt, parser, root, false, &mut loop_body)?
.0;
let condition = ctx.add_expression(
Expression::Unary {
op: UnaryOperator::Not,
@@ -287,12 +295,16 @@ impl<'source> ParsingContext<'source> {
let mut loop_body = Block::new();
self.parse_statement(parser, ctx, &mut loop_body)?;
let mut stmt = ctx.stmt_ctx();
self.expect(parser, TokenValue::While)?;
self.expect(parser, TokenValue::LeftParen)?;
let root = self.parse_expression(parser, ctx, &mut loop_body)?;
let root = self.parse_expression(parser, ctx, &mut stmt, &mut loop_body)?;
self.expect(parser, TokenValue::RightParen)?;
let expr = ctx.lower_expect(parser, root, false, &mut loop_body)?.0;
let expr = ctx
.lower_expect(stmt, parser, root, false, &mut loop_body)?
.0;
let condition = ctx.add_expression(
Expression::Unary {
op: UnaryOperator::Not,
@@ -325,8 +337,9 @@ impl<'source> ParsingContext<'source> {
if self.peek_type_name(parser) || self.peek_type_qualifier(parser) {
self.parse_declaration(parser, ctx, body, false)?;
} else {
let expr = self.parse_expression(parser, ctx, body)?;
ctx.lower(parser, expr, false, body)?;
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
ctx.lower(stmt, parser, expr, false, body)?;
self.expect(parser, TokenValue::Semicolon)?;
}
}
@@ -361,8 +374,9 @@ impl<'source> ParsingContext<'source> {
value
} else {
let root = self.parse_expression(parser, ctx, &mut block)?;
ctx.lower_expect(parser, root, false, &mut block)?.0
let mut stmt = ctx.stmt_ctx();
let root = self.parse_expression(parser, ctx, &mut stmt, &mut block)?;
ctx.lower_expect(stmt, parser, root, false, &mut block)?.0
};
let condition = ctx.add_expression(
@@ -388,8 +402,10 @@ impl<'source> ParsingContext<'source> {
match self.expect_peek(parser)?.value {
TokenValue::RightParen => {}
_ => {
let rest = self.parse_expression(parser, ctx, &mut continuing)?;
ctx.lower(parser, rest, false, &mut continuing)?;
let mut stmt = ctx.stmt_ctx();
let rest =
self.parse_expression(parser, ctx, &mut stmt, &mut continuing)?;
ctx.lower(stmt, parser, rest, false, &mut continuing)?;
}
}
@@ -425,8 +441,9 @@ impl<'source> ParsingContext<'source> {
| TokenValue::IntConstant(_)
| TokenValue::BoolConstant(_)
| TokenValue::FloatConstant(_) => {
let expr = self.parse_expression(parser, ctx, body)?;
ctx.lower(parser, expr, false, body)?;
let mut stmt = ctx.stmt_ctx();
let expr = self.parse_expression(parser, ctx, &mut stmt, body)?;
ctx.lower(stmt, parser, expr, false, body)?;
self.expect(parser, TokenValue::Semicolon)?;
}
TokenValue::Semicolon => {