diff --git a/src/ast/expr/unary.rs b/src/ast/expr/unary.rs index f458494f..de30e2e9 100644 --- a/src/ast/expr/unary.rs +++ b/src/ast/expr/unary.rs @@ -1,4 +1,5 @@ use super::Expr; +use derive_more::IsVariant; use std::fmt::Display; #[derive(Clone, Debug)] @@ -7,7 +8,7 @@ pub struct UnaryOperation { pub inner: Expr, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, IsVariant)] pub enum UnaryOperator { Not, BitComplement, diff --git a/src/lower/mod.rs b/src/lower/mod.rs index 62426382..fc2aa7c3 100644 --- a/src/lower/mod.rs +++ b/src/lower/mod.rs @@ -437,6 +437,15 @@ fn lower_destination( index, })) } + DestinationKind::Dereference(pointer_lvalue) => { + let pointer_rvalue = + lower_expr(builder, ir_module, pointer_lvalue, function, resolved_ast)?; + + let result_pointer_type = + lower_type(&ir_module.target, &destination.resolved_type, resolved_ast)?; + + Ok(builder.push(ir::Instruction::Load((pointer_rvalue, result_pointer_type)))) + } } } diff --git a/src/parser/parse_expr/primary/mod.rs b/src/parser/parse_expr/primary/mod.rs index 62c5c52c..5a65d9dd 100644 --- a/src/parser/parse_expr/primary/mod.rs +++ b/src/parser/parse_expr/primary/mod.rs @@ -82,26 +82,23 @@ impl<'a, I: Inflow> Parser<'a, I> { self.parse_enum_member_literal(name, source) } TokenKind::OpenCurly => { - let ast_type = self.parse_type_from_parts(name, generics, source)?; let peek = &self.input.peek_nth(1).kind; if peek.is_extend() || peek.is_colon() { + let ast_type = self.parse_type_from_parts(name, generics, source)?; self.parse_structure_literal_with(ast_type) } else { let next_three = - array_last::<3, 5, _>(self.input.peek_n()).map(|token| &token.kind); + array_last::<2, 4, _>(self.input.peek_n()).map(|token| &token.kind); match &next_three[..] { - [TokenKind::Identifier(_), TokenKind::Colon, ..] - | [TokenKind::Newline, TokenKind::Identifier(_), TokenKind::Colon, ..] => { + [TokenKind::Colon, ..] + | [TokenKind::Identifier(_), TokenKind::Colon, ..] => { + let ast_type = + self.parse_type_from_parts(name, generics, source)?; self.parse_structure_literal_with(ast_type) } - _ => Ok(Expr::new( - ExprKind::Variable( - self.input.advance().kind.unwrap_identifier(), - ), - source, - )), + _ => Ok(Expr::new(ExprKind::Variable(name), source)), } } } diff --git a/src/resolve/destination.rs b/src/resolve/destination.rs index b78caafb..5b6270c5 100644 --- a/src/resolve/destination.rs +++ b/src/resolve/destination.rs @@ -24,6 +24,11 @@ pub fn resolve_expr_to_destination(typed_expr: TypedExpr) -> Result DestinationKind::ArrayAccess(array_access), + ExprKind::UnaryOperation(unary_operation) + if unary_operation.operator.is_dereference() => + { + DestinationKind::Dereference(unary_operation.inner.expr) + } _ => { return Err(ResolveErrorKind::CannotMutate { bad_type: typed_expr.resolved_type.to_string(), diff --git a/src/resolve/expr/unary_operation.rs b/src/resolve/expr/unary_operation.rs index 3e5afcd5..70dd37a0 100644 --- a/src/resolve/expr/unary_operation.rs +++ b/src/resolve/expr/unary_operation.rs @@ -23,6 +23,43 @@ pub fn resolve_unary_operation_expr( Initialized::Require, )?; + let operator = &unary_operation.operator; + + if operator.is_address_of() || operator.is_dereference() { + if resolved_expr.resolved_type.kind.is_ambiguous_type() { + return Err(ResolveErrorKind::CannotPerformUnaryOperationForType { + operator: unary_operation.operator.to_string(), + bad_type: resolved_expr.resolved_type.to_string(), + } + .at(source)); + } + + let mut result_type = resolved_expr.resolved_type.clone(); + if operator.is_dereference() { + if let TypeKind::Pointer(inner) = result_type.kind { + result_type = *inner; + } else { + return Err(ResolveErrorKind::CannotPerformUnaryOperationForType { + operator: unary_operation.operator.to_string(), + bad_type: resolved_expr.resolved_type.to_string(), + } + .at(source)); + } + } else if operator.is_address_of() { + result_type = TypeKind::Pointer(Box::new(result_type)).at(source); + } + + let expr = Expr::new( + ExprKind::UnaryOperation(Box::new(UnaryOperation { + operator: unary_operation.operator.clone(), + inner: resolved_expr, + })), + source, + ); + + return Ok(TypedExpr::new(result_type, expr)); + } + let resolved_expr = match &resolved_expr.resolved_type.kind { TypeKind::Boolean => resolved_expr, TypeKind::Integer(..) => resolved_expr, diff --git a/src/resolve/stmt.rs b/src/resolve/stmt.rs index 79e3c399..1bd0d1a9 100644 --- a/src/resolve/stmt.rs +++ b/src/resolve/stmt.rs @@ -205,6 +205,7 @@ pub fn resolve_stmt( resolved::DestinationKind::GlobalVariable(..) => (), resolved::DestinationKind::Member { .. } => (), resolved::DestinationKind::ArrayAccess { .. } => (), + resolved::DestinationKind::Dereference { .. } => (), } let operator = assignment diff --git a/src/resolved/mod.rs b/src/resolved/mod.rs index f2d9af05..97b9d272 100644 --- a/src/resolved/mod.rs +++ b/src/resolved/mod.rs @@ -207,6 +207,10 @@ impl TypeKind { Self::Integer(..) | Self::IntegerLiteral(..) | Self::CInteger(..) ) } + + pub fn is_ambiguous_type(&self) -> bool { + self.is_integer_literal() + } } #[derive(Clone, Debug)] @@ -543,6 +547,7 @@ pub enum DestinationKind { field_type: Type, }, ArrayAccess(Box), + Dereference(Expr), } #[derive(Copy, Clone, Debug)]