diff --git a/src/ast/expr/unary.rs b/src/ast/expr/unary.rs index ec41f40e..f458494f 100644 --- a/src/ast/expr/unary.rs +++ b/src/ast/expr/unary.rs @@ -13,6 +13,8 @@ pub enum UnaryOperator { BitComplement, Negate, IsNonZero, + AddressOf, + Dereference, } impl Display for UnaryOperator { @@ -22,6 +24,8 @@ impl Display for UnaryOperator { Self::BitComplement => "~", Self::Negate => "-", Self::IsNonZero => "bool()", + Self::AddressOf => "(address of) &", + Self::Dereference => "(dereference) *", }) } } diff --git a/src/lower/mod.rs b/src/lower/mod.rs index 99995f0e..62426382 100644 --- a/src/lower/mod.rs +++ b/src/lower/mod.rs @@ -736,11 +736,21 @@ fn lower_expr( resolved_ast, )?; + let inner_type = lower_type( + ir_module.target, + &unary_operation.inner.resolved_type, + resolved_ast, + )?; + Ok(builder.push(match unary_operation.operator { resolved::UnaryOperator::Not => ir::Instruction::IsZero(inner), resolved::UnaryOperator::BitComplement => ir::Instruction::BitComplement(inner), resolved::UnaryOperator::Negate => ir::Instruction::Negate(inner), resolved::UnaryOperator::IsNonZero => ir::Instruction::IsNonZero(inner), + resolved::UnaryOperator::AddressOf => { + unimplemented!("address of operator"); + } + resolved::UnaryOperator::Dereference => ir::Instruction::Load((inner, inner_type)), })) } ExprKind::Conditional(conditional) => { diff --git a/src/parser/parse_expr/primary/mod.rs b/src/parser/parse_expr/primary/mod.rs index 4650e928..62c5c52c 100644 --- a/src/parser/parse_expr/primary/mod.rs +++ b/src/parser/parse_expr/primary/mod.rs @@ -122,18 +122,24 @@ impl<'a, I: Inflow> Parser<'a, I> { } } } - TokenKind::Not | TokenKind::BitComplement | TokenKind::Subtract => { + TokenKind::Not + | TokenKind::BitComplement + | TokenKind::Subtract + | TokenKind::AddressOf + | TokenKind::Dereference => { let operator = match kind { TokenKind::Not => UnaryOperator::Not, TokenKind::BitComplement => UnaryOperator::BitComplement, TokenKind::Subtract => UnaryOperator::Negate, + TokenKind::AddressOf => UnaryOperator::AddressOf, + TokenKind::Dereference => UnaryOperator::Dereference, _ => unreachable!(), }; // Eat unary operator self.input.advance(); - let inner = self.parse_expr()?; + let inner = self.parse_expr_primary()?; Ok(Expr::new( ExprKind::UnaryOperation(Box::new(UnaryOperation { operator, inner })), diff --git a/src/parser/parse_stmt/mod.rs b/src/parser/parse_stmt/mod.rs index dd55dd23..0f18dd92 100644 --- a/src/parser/parse_stmt/mod.rs +++ b/src/parser/parse_stmt/mod.rs @@ -22,19 +22,23 @@ impl<'a, I: Inflow> Parser<'a, I> { return self.parse_declaration(); } - let lhs = self.parse_expr()?; + () + } + TokenKind::ReturnKeyword => return self.parse_return(), + TokenKind::EndOfFile => return Err(self.unexpected_token_is_next()), + _ => (), + } - if self.input.peek().is_assignment_like() { - // Assignment-Like Statement - return self.parse_assignment(lhs); - } + let lhs = self.parse_expr_primary()?; - // Plain Expression Statement - Ok(StmtKind::Expr(lhs).at(source)) - } - TokenKind::ReturnKeyword => self.parse_return(), - TokenKind::EndOfFile => Err(self.unexpected_token_is_next()), - _ => Ok(Stmt::new(StmtKind::Expr(self.parse_expr()?), source)), + if self.input.peek().is_assignment_like() { + // Assignment-Like Statement + return self.parse_assignment(lhs); } + + let lhs = self.parse_operator_expr(0, lhs)?; + + // Plain Expression Statement + Ok(StmtKind::Expr(lhs).at(source)) } } diff --git a/src/resolve/expr/unary_operation.rs b/src/resolve/expr/unary_operation.rs index 92fb3bcc..3e5afcd5 100644 --- a/src/resolve/expr/unary_operation.rs +++ b/src/resolve/expr/unary_operation.rs @@ -41,6 +41,10 @@ pub fn resolve_unary_operation_expr( let result_type = match unary_operation.operator { UnaryOperator::Not | UnaryOperator::IsNonZero => TypeKind::Boolean.at(source), UnaryOperator::BitComplement | UnaryOperator::Negate => resolved_expr.resolved_type.clone(), + UnaryOperator::AddressOf => { + TypeKind::Pointer(Box::new(resolved_expr.resolved_type.clone())).at(source) + } + UnaryOperator::Dereference => resolved_expr.resolved_type.clone(), }; let expr = Expr::new(