diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index fe89e6b..43c574a 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -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 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 { 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 { + ) -> ParseResult { 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 { + fn parse_block(&mut self, tokens: &mut TokenIterator) -> ParseResult { 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 { + fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { 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 { + fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { 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> { + lhs: PlaceOrValue, + ) -> ParseResult> { 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 { + fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { 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 { 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 { + fn parse_else_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { // 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 { + fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { // 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 { + ) -> ParseResult { 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 { + fn parse_expr(&mut self, tokens: &mut TokenIterator) -> ParseResult { 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 { + // 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 { + // 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( + fn parse_with_trailing_semi( &mut self, tokens: &mut TokenIterator, parse: F, - ) -> ParseResult + ) -> ParseResult where - F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + Index: Into, { 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( + fn parse_inner( &mut self, tokens: &mut TokenIterator, open: Token, close: Token, parse: F, on_err: E, - ) -> ParseResult + ) -> ParseResult where - F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, - E: FnOnce(&mut Self, &mut TokenIterator, ErrorInfo, TokenItem) -> ParseResult, + F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + E: FnOnce(&mut Self, &mut TokenIterator, ErrorInfo, TokenItem) -> ParseResult, { let Some(start) = tokens.eat_token(open) else { return Err(ErrorInfo { @@ -3993,15 +4143,17 @@ pub mod ast_gen { } } - fn parse_inner2( + fn parse_inner2( &mut self, tokens: &mut TokenIterator, open: Token, close: Token, parse: F, - ) -> ParseResult + ) -> ParseResult where - F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + Index: Into, + // I: From, { 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(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult + fn parse_bracketed(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult where - F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + Index: Into, { self.parse_inner2( tokens, @@ -4047,20 +4200,22 @@ pub mod ast_gen { ) } - fn parse_braced(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult + fn parse_braced(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult where - F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + Index: Into, { self.parse_inner2(tokens, Token::OpenBrace, Token::CloseBrace, parse) } - fn parse_parenthesised( + fn parse_parenthesised( &mut self, tokens: &mut TokenIterator, parse: F, - ) -> ParseResult + ) -> ParseResult where - F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult, + Index: Into, { self.parse_inner2(tokens, Token::OpenParens, Token::CloseParens, parse) }