i dont think this is the right way to do this, in hindsight

This commit is contained in:
Janis 2025-03-05 15:49:19 +01:00
parent 028c74753e
commit 51aa119af2

View file

@ -484,6 +484,48 @@ impl Data {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum PlaceOrValue {
Value(index::Index),
Place(index::Index),
}
impl PlaceOrValue {
fn into_index(self) -> index::Index {
match self {
PlaceOrValue::Value(index) => index,
PlaceOrValue::Place(index) => index,
}
}
fn is_value(&self) -> bool {
matches!(self, &Self::Value(_))
}
fn is_place(&self) -> bool {
!self.is_value()
}
fn into_value(self) -> PlaceOrValue {
Self::Value(self.into_index())
}
fn into_place(self) -> PlaceOrValue {
Self::Place(self.into_index())
}
fn eq_discriminant(&self, other: &Self) -> bool {
core::mem::discriminant(self).eq(&core::mem::discriminant(other))
}
fn with_index(self, index: Index) -> PlaceOrValue {
match self {
PlaceOrValue::Value(_) => Self::Value(index),
PlaceOrValue::Place(_) => Self::Place(index),
}
}
}
impl From<index::Index> for PlaceOrValue {
fn from(value: index::Index) -> Self {
Self::Value(value)
}
}
mod index {
use std::num::NonZero;
@ -968,10 +1010,39 @@ impl Ast {
i
}
fn push_unary(&mut self, tag: Tag, lhs: Index, loc: SourceLocation) -> Index {
fn push_unary(&mut self, tag: Tag, lhs: Index, loc: SourceLocation) -> PlaceOrValue {
let i = self.reserve_node_other();
self.set_tag_data_source_loc(i, tag, Data::index(lhs), loc);
match tag {
Tag::Deref => PlaceOrValue::Place(i),
_ => PlaceOrValue::Value(i),
}
}
/// converts from a place expression to a value expression.
fn push_place_to_value_conversion(&mut self, rvalue: Index, loc: SourceLocation) -> Index {
let i = self.reserve_node_other();
self.set_tag_data_source_loc(
rvalue,
Tag::PlaceToValueConversion,
Data::index(rvalue),
loc,
);
i
}
/// converts from a value expression to a place expression.
fn push_value_to_place_conversion(&mut self, rvalue: Index, loc: SourceLocation) -> Index {
let i = self.reserve_node_other();
self.set_tag_data_source_loc(
rvalue,
Tag::ValueToPlaceConversion,
Data::index(rvalue),
loc,
);
i
}
@ -1098,11 +1169,11 @@ impl Ast {
expr: Index,
name: intern::Index,
loc: SourceLocation,
) -> Index {
) -> PlaceOrValue {
let i = self.reserve_node_other();
self.set_tag_data_source_loc(i, Tag::FieldAccess, Data::index_and_intern(expr, name), loc);
i
PlaceOrValue::Place(i)
}
fn push_interend_type(&mut self, ty: intern::Index, loc: SourceLocation) -> Index {
@ -2786,7 +2857,7 @@ pub mod ast_gen {
fn parse_array_type(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
let loc = tokens.current_source_location();
let length_expr = self.parse_bracketed(tokens, |this, tokens| {
this.parse_expr(tokens)
this.parse_value_expr(tokens)
// let next = tokens.peek_token().ok_or(ErrorInfo {
// error: ParseError::UnexpectedEndOfTokens,
// loc: tokens.current_source_location(),
@ -3069,7 +3140,7 @@ pub mod ast_gen {
};
};
let expr = match self.parse_expr(tokens) {
let expr = match self.parse_value_expr(tokens) {
Ok(i) => i,
Err(err) => {
break 'blk err;
@ -3147,10 +3218,13 @@ pub mod ast_gen {
self.pop_scope();
e
})?;
let body = self.parse_block(tokens).map_err(|e| {
self.pop_scope();
e
})?;
let body = self
.parse_block(tokens)
.map(|pv| self.convert_to_value_expr(pv))
.map_err(|e| {
self.pop_scope();
e
})?;
self.pop_scope();
@ -3184,7 +3258,7 @@ pub mod ast_gen {
let expr = if tokens.eat_token(Token::Semi).is_some() {
self.ast.push_ret(None, loc)
} else {
match self.parse_expr(tokens) {
match self.parse_value_expr(tokens) {
Ok(i) => {
tokens.eat_token(Token::Semi).ok_or(ErrorInfo {
error: ParseError::ExpectedToken(Token::Semi),
@ -3243,7 +3317,7 @@ pub mod ast_gen {
};
let assignment = if tokens.eat_token(Token::Equal).is_some() {
Some(self.parse_expr(tokens)?)
Some(self.parse_value_expr(tokens)?)
} else {
None
};
@ -3263,7 +3337,7 @@ pub mod ast_gen {
&mut self,
block: Index,
tokens: &mut TokenIterator,
) -> ParseResult<Index> {
) -> ParseResult<PlaceOrValue> {
let loc = tokens.current_source_location();
let mut statements = Vec::new();
@ -3291,7 +3365,7 @@ pub mod ast_gen {
// expr -> statements
let expr = self
.parse_with_trailing_semi(tokens, |this, tokens| {
this.parse_expr(tokens)
Ok(this.parse_expr(tokens)?.into_index())
})?;
statements.push(expr);
@ -3312,13 +3386,22 @@ pub mod ast_gen {
}
};
self.ast.set_block(block, statements, trailing, loc);
self.ast.set_block(
block,
statements,
trailing.map(PlaceOrValue::into_index),
loc,
);
let block = trailing
.map(|pv| pv.with_index(block))
.unwrap_or(PlaceOrValue::Value(block));
Ok(block)
}
/// BLOCK <-
/// { STATEMENT* EXPRESSION? }
fn parse_block(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_block(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
let block = self.parse_braced(tokens, |this, tokens| {
let block = this.ast.reserve_node_other();
this.push_scope(block, intern::Index::invalid());
@ -3388,7 +3471,7 @@ pub mod ast_gen {
} else {
None
};
let expr = self.parse_expr(tokens)?;
let expr = self.parse_value_expr(tokens)?;
let i = match name {
Some(name) => self.ast.push_named_argument(name, expr, loc),
@ -3425,7 +3508,7 @@ pub mod ast_gen {
/// FLOATING_CONSTANT
/// ( EXPRESSION )
/// BLOCK
fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
let loc = tokens.current_source_location();
let Some(next) = tokens.peek_token() else {
@ -3441,14 +3524,18 @@ pub mod ast_gen {
| Token::IntegerOctConstant
| Token::IntegerConstant => {
_ = tokens.next();
return Ok(self.parse_integral_constant(&next, next.source_location()));
return Ok(PlaceOrValue::Value(
self.parse_integral_constant(&next, next.source_location()),
));
}
Token::FloatingConstant
| Token::FloatingExpConstant
| Token::DotFloatingConstant
| Token::DotFloatingExpConstant => {
_ = tokens.next();
return Ok(self.parse_floating_constant(&next, next.source_location()));
return Ok(PlaceOrValue::Value(
self.parse_floating_constant(&next, next.source_location()),
));
}
Token::OpenParens => {
@ -3458,7 +3545,7 @@ pub mod ast_gen {
return Ok(expr);
}
Token::OpenBrace => {
return self.parse_block(tokens);
return Ok(self.parse_block(tokens)?);
}
Token::Ident => {
_ = tokens.next();
@ -3466,9 +3553,12 @@ pub mod ast_gen {
let ident = self
.intern
.get_or_insert(intern::Key::String { str: ident });
return Ok(self
.ast
.push_decl_ref_unresolved(self.current_scope(), ident, loc));
return Ok(PlaceOrValue::Place(self.ast.push_decl_ref_unresolved(
self.current_scope(),
ident,
loc,
)));
}
// TODO: eventually handle paths
_ => {
@ -3486,7 +3576,7 @@ pub mod ast_gen {
/// PRIMARY_EXPR ( ARGUMENT_LIST )
/// PRIMARY_EXPR [ EXPR ]
/// POSTFIX_EXPR . IDENTIFIER
fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
let mut lhs = self.parse_primary_expr(tokens)?;
while let Some(postfix) = self.try_parse_postfix_expr_inner(tokens, lhs)? {
lhs = postfix;
@ -3498,8 +3588,8 @@ pub mod ast_gen {
fn try_parse_postfix_expr_inner(
&mut self,
tokens: &mut TokenIterator,
lhs: Index,
) -> ParseResult<Option<Index>> {
lhs: PlaceOrValue,
) -> ParseResult<Option<PlaceOrValue>> {
let lhs = if let Some(next) = tokens.peek_token() {
let loc = next.source_location();
match next.token() {
@ -3511,21 +3601,30 @@ pub mod ast_gen {
this.parse_argument_list(tokens)
}
})?;
let lhs = self.convert_to_value_expr(lhs);
Some(self.ast.push_call_expr(lhs, arguments, loc))
Some(PlaceOrValue::Value(
self.ast.push_call_expr(lhs, arguments, loc),
))
}
Token::OpenSquareBracket => {
let subscript =
self.parse_bracketed(tokens, |this, tokens| this.parse_expr(tokens))?;
let subscript = self.parse_bracketed(tokens, |this, tokens| {
this.parse_value_expr(tokens)
})?;
Some(
self.ast
.push_binary(Tag::SubscriptExpr, lhs, subscript, loc),
)
let lhs = self.convert_to_value_expr(lhs);
Some(PlaceOrValue::Place(self.ast.push_binary(
Tag::SubscriptExpr,
lhs,
subscript,
loc,
)))
}
Token::Dot if tokens.is_next_token2(Token::Ident) => {
_ = tokens.next();
let loc = tokens.current_source_location();
let lhs = self.convert_to_place_expr(lhs);
let name = self.parse_ident(tokens)?;
Some(self.ast.push_field_access(lhs, name, loc))
@ -3544,13 +3643,31 @@ pub mod ast_gen {
self.ast.push_error(error, loc)
}
/// converts the expression to a value expression, if it isn't one already.
fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
let loc = self.ast.get_loc(lrvalue.into_index());
match lrvalue {
PlaceOrValue::Value(index) => index,
PlaceOrValue::Place(index) => self.ast.push_place_to_value_conversion(index, loc),
}
}
/// converts the expression to a place expression, if it isn't one already.
fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
let loc = self.ast.get_loc(lrvalue.into_index());
match lrvalue {
PlaceOrValue::Place(index) => index,
PlaceOrValue::Value(index) => self.ast.push_value_to_place_conversion(index, loc),
}
}
/// PREFIX_EXPR <-
/// POSTFIX_EXPR
/// ! POSTFIX_EXPR
/// - POSTFIX_EXPR
/// & POSTFIX_EXPR
/// * POSTFIX_EXPR
fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
let next = tokens.peek_token().ok_or(ErrorInfo {
error: ParseError::ExpectedPrefixExpression,
loc: tokens.current_source_location(),
@ -3561,23 +3678,31 @@ pub mod ast_gen {
let expr = match next.token() {
Token::Bang => {
_ = tokens.next();
let lhs = self.parse_postfix_expr(tokens)?;
let lhs = self.parse_prefix_expr(tokens)?;
let lhs = self.convert_to_value_expr(lhs);
self.ast.push_unary(Tag::Not, lhs, loc)
}
Token::Minus => {
_ = tokens.next();
let lhs = self.parse_postfix_expr(tokens)?;
let lhs = self.parse_prefix_expr(tokens)?;
let lhs = self.convert_to_value_expr(lhs);
self.ast.push_unary(Tag::Negate, lhs, loc)
}
Token::Ampersand => {
_ = tokens.next();
let lhs = self.parse_postfix_expr(tokens)?;
// the address-of operator requires lhs to be a place
// expression. not all expressions that might be the lhs
// are automatically place expressions: the construct `let a
// = &3;` has `3`, which is a value expression, as the lhs
// of the address-of operator.
let lhs = self.parse_prefix_expr(tokens)?;
let lhs = self.convert_to_place_expr(lhs);
self.ast.push_unary(Tag::AddressOf, lhs, loc)
}
Token::Star => {
_ = tokens.next();
let lhs = self.parse_postfix_expr(tokens)?;
self.ast.push_unary(Tag::Deref, lhs, loc)
let lhs = self.parse_prefix_expr(tokens)?;
self.ast.push_unary(Tag::Deref, lhs.into_index(), loc)
}
_ => self.parse_postfix_expr(tokens)?,
};
@ -3590,7 +3715,8 @@ pub mod ast_gen {
/// PREFIX_EXPR as TYPENAME
fn parse_as_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
let loc = tokens.current_source_location();
let expr = self.parse_prefix_expr(tokens)?;
let maybe_rvalue = self.parse_prefix_expr(tokens)?;
let expr = self.convert_to_value_expr(maybe_rvalue);
if tokens.eat_token(Token::As).is_some() {
let typename = self.parse_type(tokens)?;
@ -3691,7 +3817,7 @@ pub mod ast_gen {
// SAFETY: we peeked
let op = tokens.next().unwrap();
let loc = op.source_location();
let rhs = self.parse_expr(tokens)?;
let rhs = self.parse_place_expr(tokens)?;
let rhs = if op.token() == Token::Equal {
rhs
@ -3722,7 +3848,7 @@ pub mod ast_gen {
/// ELSE_EXPR <-
/// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK)
fn parse_else_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_else_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
// SAFETY: function invariance
let _else_ = tokens.eat_token(Token::Else).unwrap();
@ -3735,27 +3861,33 @@ pub mod ast_gen {
/// IF_EXPR <-
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
// SAFETY: function invariance
let iff = tokens.eat_token(Token::If).unwrap();
let loc = iff.source_location();
let cond = self.parse_parenthesised(tokens, |this, tokens| this.parse_expr(tokens))?;
let cond =
self.parse_parenthesised(tokens, |this, tokens| this.parse_value_expr(tokens))?;
let body = self.parse_expr_or_block_as_block(tokens)?;
if tokens.is_next_token(Token::Else) {
let else_expr = self.parse_else_expr(tokens)?;
Ok(self.ast.push_if_else(cond, body, else_expr, loc))
Ok(body.with_index(self.ast.push_if_else(
cond,
body.into_index(),
else_expr.into_index(),
loc,
)))
} else {
Ok(self.ast.push_if(cond, body, loc))
Ok(body.with_index(self.ast.push_if(cond, body.into_index(), loc)))
}
}
fn parse_expr_or_block_as_block(
&mut self,
tokens: &mut TokenIterator,
) -> ParseResult<Index> {
) -> ParseResult<PlaceOrValue> {
let Some(next) = tokens.peek_token() else {
return Err(ErrorInfo {
error: ParseError::ExpectedExpression,
@ -3768,12 +3900,12 @@ pub mod ast_gen {
_ => {
let loc = tokens.current_source_location();
let expr = self.parse_expr(tokens)?;
Ok(self.ast.push_block([], Some(expr), loc))
Ok(expr.with_index(self.ast.push_block([], Some(expr.into_index()), loc)))
}
}
}
fn parse_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
fn parse_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<PlaceOrValue> {
let loc = tokens.current_source_location();
let Some(next) = tokens.peek_token() else {
return Err(ErrorInfo {
@ -3782,10 +3914,27 @@ pub mod ast_gen {
});
};
match next.token() {
Token::If => self.parse_if_expr(tokens),
_ => self.parse_assignment_expr(tokens),
}
let expr = match next.token() {
Token::If => self.parse_if_expr(tokens)?,
_ => PlaceOrValue::Value(self.parse_assignment_expr(tokens)?),
};
Ok(expr)
}
fn parse_place_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
// TODO: panic if not place expr
let expr = self.parse_expr(tokens)?;
let expr = self.convert_to_place_expr(expr);
Ok(expr)
}
fn parse_value_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
// TODO: convert from place to value (lvalue-to-rvalue)
let expr = self.parse_expr(tokens)?;
let expr = self.convert_to_value_expr(expr);
Ok(expr)
}
/// TYPE_DECL <-
@ -3925,13 +4074,14 @@ pub mod ast_gen {
Ok(decl)
}
fn parse_with_trailing_semi<F>(
fn parse_with_trailing_semi<F, I>(
&mut self,
tokens: &mut TokenIterator,
parse: F,
) -> ParseResult<Index>
) -> ParseResult<I>
where
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<I>,
Index: Into<I>,
{
match parse(self, tokens) {
Ok(i) => {
@ -3947,22 +4097,22 @@ pub mod ast_gen {
error: ParseError::ExpectedToken(Token::Semi),
loc: tokens.current_source_location(),
})?;
Ok(self.push_error(err.error, err.loc))
Ok(self.push_error(err.error, err.loc).into())
}
}
}
fn parse_inner<F, E>(
fn parse_inner<F, I, E>(
&mut self,
tokens: &mut TokenIterator,
open: Token,
close: Token,
parse: F,
on_err: E,
) -> ParseResult<Index>
) -> ParseResult<I>
where
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
E: FnOnce(&mut Self, &mut TokenIterator, ErrorInfo, TokenItem) -> ParseResult<Index>,
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<I>,
E: FnOnce(&mut Self, &mut TokenIterator, ErrorInfo, TokenItem) -> ParseResult<I>,
{
let Some(start) = tokens.eat_token(open) else {
return Err(ErrorInfo {
@ -3993,15 +4143,17 @@ pub mod ast_gen {
}
}
fn parse_inner2<F>(
fn parse_inner2<F, I>(
&mut self,
tokens: &mut TokenIterator,
open: Token,
close: Token,
parse: F,
) -> ParseResult<Index>
) -> ParseResult<I>
where
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<I>,
Index: Into<I>,
// I: From<Index>,
{
self.parse_inner(tokens, open, close, parse, |this, tokens, err, start| {
match close {
@ -4031,13 +4183,14 @@ pub mod ast_gen {
}
_ => unimplemented!(),
}
Ok(this.push_error(err.error, err.loc))
Ok(this.push_error(err.error, err.loc).into())
})
}
fn parse_bracketed<F>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<Index>
fn parse_bracketed<F, I>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<I>
where
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<I>,
Index: Into<I>,
{
self.parse_inner2(
tokens,
@ -4047,20 +4200,22 @@ pub mod ast_gen {
)
}
fn parse_braced<F>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<Index>
fn parse_braced<F, I>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<I>
where
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<I>,
Index: Into<I>,
{
self.parse_inner2(tokens, Token::OpenBrace, Token::CloseBrace, parse)
}
fn parse_parenthesised<F>(
fn parse_parenthesised<F, I>(
&mut self,
tokens: &mut TokenIterator,
parse: F,
) -> ParseResult<Index>
) -> ParseResult<I>
where
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<I>,
Index: Into<I>,
{
self.parse_inner2(tokens, Token::OpenParens, Token::CloseParens, parse)
}