mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-in] Don't clone HirExpr when lowering
This commit is contained in:
committed by
Dzmitry Malyshau
parent
07c286255d
commit
e384bce771
@@ -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> {
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
Reference in New Issue
Block a user