use super::*;
impl Parser {
pub(super) fn parse_expression(&mut self) -> Result<Expression> {
self.parse_precedence(0)
}
fn parse_precedence(&mut self, min_binding_power: u8) -> Result<Expression> {
let mut left = self.parse_prefix()?;
loop {
let token = self.peek().clone();
if let Some(left_binding_power) = postfix_binding_power(&token) {
if left_binding_power < min_binding_power {
break;
}
match token {
Token::Dot => {
self.advance();
let field = self.expect_identifier()?;
left = self.resolve_field(left, field);
}
Token::LeftParen => {
self.advance();
left = self.parse_call(left)?;
}
Token::LeftBracket => {
self.advance();
let index = auto_deref(self.parse_expression()?, &self.context);
self.expect(Token::RightBracket)?;
left = self.resolve_index(left, index);
}
Token::As => {
self.advance();
let target_type = self.parse_type()?;
left = Expression::new(
ExpressionKind::Convert(Box::new(left), target_type.clone()),
target_type,
);
}
Token::Bang => {
self.advance();
let result_type = left.resolved_type.clone();
left = Expression::new(ExpressionKind::Eval(Box::new(left)), result_type);
}
_ => break,
}
continue;
}
if token == Token::ColonEqual {
if 0 < min_binding_power {
break;
}
self.advance();
let is_place = matches!(
self.context.resolve_named(&left.resolved_type),
Type::Pointer(Mutability::Mutable, _, _)
) || matches!(
left.kind,
ExpressionKind::Index(..) | ExpressionKind::Field(..)
);
if !is_place {
return Err(Error {
message: format!(
"left side of := must be a mutable pointer (|T), got {:?}",
left.resolved_type
),
span: Some(self.span()),
});
}
let result_type = left.resolved_type.clone();
let value = auto_deref(self.parse_precedence(0)?, &self.context);
if let ExpressionKind::BinaryOperation(op, ref lhs, _) = value.kind {
let same_target = extract_variable_name(&left)
.zip(extract_variable_name(lhs))
.is_some_and(|(a, b)| a == b);
if same_target {
let symbol = match op {
BinaryOperator::Arithmetic(ArithmeticOperator::Add) => Some("+="),
BinaryOperator::Arithmetic(ArithmeticOperator::Subtract) => Some("-="),
BinaryOperator::Arithmetic(ArithmeticOperator::Multiply) => Some("*="),
BinaryOperator::Arithmetic(ArithmeticOperator::Divide) => Some("/="),
_ => None,
};
if let Some(symbol) = symbol {
return Err(Error {
message: format!("use '{symbol}' instead of ':= ... {op} ...'"),
span: Some(self.span()),
});
}
}
}
left = Expression::new(
ExpressionKind::Replace(Box::new(left), Box::new(value)),
result_type,
);
continue;
}
if let Some(compound_op) = match &token {
Token::PlusEqual => Some(BinaryOperator::Arithmetic(ArithmeticOperator::Add)),
Token::MinusEqual => Some(BinaryOperator::Arithmetic(ArithmeticOperator::Subtract)),
Token::StarEqual => Some(BinaryOperator::Arithmetic(ArithmeticOperator::Multiply)),
Token::SlashEqual => Some(BinaryOperator::Arithmetic(ArithmeticOperator::Divide)),
_ => None,
} {
if 0 < min_binding_power {
break;
}
self.advance();
let derefed = auto_deref(left.clone(), &self.context);
let value = auto_deref(self.parse_precedence(0)?, &self.context);
let result_type = left.resolved_type.clone();
let combined = Expression::new(
ExpressionKind::BinaryOperation(
compound_op,
Box::new(derefed),
Box::new(value),
),
result_type.clone(),
);
left = Expression::new(
ExpressionKind::Replace(Box::new(left), Box::new(combined)),
result_type,
);
continue;
}
if token == Token::Equal {
return Err(Error {
message: "unexpected `=`. If you want comparison, use `==`. If you want assignment, use `:=`.".into(),
span: Some(self.span()),
});
}
if let Some((left_binding_power, right_binding_power)) = infix_binding_power(&token) {
if left_binding_power < min_binding_power {
break;
}
self.advance();
let operator = token_to_binary_operator(&token).unwrap();
let left_derefed = auto_deref(left, &self.context);
let right = auto_deref(self.parse_precedence(right_binding_power)?, &self.context);
let result_type = operator_result_type(&operator, &left_derefed.resolved_type);
left = Expression::new(
ExpressionKind::BinaryOperation(
operator,
Box::new(left_derefed),
Box::new(right),
),
result_type,
);
continue;
}
break;
}
Ok(left)
}
fn parse_prefix(&mut self) -> Result<Expression> {
match self.peek().clone() {
Token::Integer(value) => {
self.advance();
Ok(Expression::new(
ExpressionKind::Literal(Literal::Integer(value)),
Type::Int(IntWidth::W32, Signedness::Signed),
))
}
Token::Float(value) => {
self.advance();
Ok(Expression::new(
ExpressionKind::Literal(Literal::Float(value)),
Type::Float(FloatWidth::W64),
))
}
Token::String(bytes) => {
self.advance();
let string_type = Type::Pointer(
Mutability::Shared,
Lifetime::Inferred,
Box::new(Type::Int(IntWidth::W8, Signedness::Unsigned)),
);
Ok(Expression::new(
ExpressionKind::Literal(Literal::String(bytes)),
string_type,
))
}
Token::True => {
self.advance();
Ok(Expression::new(
ExpressionKind::Literal(Literal::Bool(true)),
Type::Bool,
))
}
Token::False => {
self.advance();
Ok(Expression::new(
ExpressionKind::Literal(Literal::Bool(false)),
Type::Bool,
))
}
Token::Identifier(name) => {
self.advance();
let is_generic_bracket = self.at(&Token::LeftBracket)
&& (self.context.lookup_variable(&name).is_none()
|| matches!(self.peek_at(1), Token::RightBracket));
if is_generic_bracket && self.context.newtypes.contains_key(&name) {
let generic_arguments = self.parse_generic_arguments(&name)?;
return self.parse_generic_type_expression(name, generic_arguments);
}
if is_generic_bracket && self.context.generic_functions.contains(&name) {
let generic_arguments = self.parse_generic_arguments(&name)?;
let inner = Expression::new(ExpressionKind::Variable(name), Type::Inferred);
return Ok(Expression::new(
ExpressionKind::Specialize(Box::new(inner), generic_arguments),
Type::Inferred,
));
}
if self.at(&Token::LeftBrace) && self.is_type_construction_ahead(&name) {
return self.parse_type_construction(name);
}
if self.at(&Token::Colon) && self.context.newtypes.contains_key(&name) {
return self.parse_simple_type_construction(name);
}
let resolved_type = self
.context
.lookup_variable(&name)
.cloned()
.unwrap_or(Type::Inferred);
Ok(Expression::new(
ExpressionKind::Variable(name),
resolved_type,
))
}
Token::Minus => {
self.advance();
let operand = auto_deref(self.parse_precedence(21)?, &self.context);
let result_type = operand.resolved_type.clone();
Ok(Expression::new(
ExpressionKind::UnaryOperation(UnaryOperator::Negate, Box::new(operand)),
result_type,
))
}
Token::Bang => {
self.advance();
let operand = auto_deref(self.parse_precedence(21)?, &self.context);
Ok(Expression::new(
ExpressionKind::UnaryOperation(UnaryOperator::LogicalNot, Box::new(operand)),
Type::Bool,
))
}
Token::Tilde => {
self.advance();
let operand = auto_deref(self.parse_precedence(21)?, &self.context);
let result_type = operand.resolved_type.clone();
Ok(Expression::new(
ExpressionKind::UnaryOperation(UnaryOperator::BitwiseNot, Box::new(operand)),
result_type,
))
}
Token::Star => {
self.advance();
let operand = self.parse_precedence(21)?;
let inner_type = if let Type::Pointer(_, _, inner) =
self.context.resolve_named(&operand.resolved_type)
{
*inner
} else {
Type::Inferred
};
Ok(Expression::new(
ExpressionKind::Dereference(Box::new(operand)),
inner_type,
))
}
Token::LeftParen => {
self.advance();
let expression = self.parse_expression()?;
self.expect(Token::RightParen)?;
Ok(expression)
}
Token::LeftBracket => {
self.advance();
let mut elements = Vec::new();
if !self.at(&Token::RightBracket) {
elements.push(auto_deref(self.parse_expression()?, &self.context));
while self.at(&Token::Comma) {
self.advance();
if self.at(&Token::RightBracket) {
break;
}
elements.push(auto_deref(self.parse_expression()?, &self.context));
}
}
self.expect(Token::RightBracket)?;
if elements.len() == 1
&& matches!(
self.peek(),
Token::Integer(_) | Token::Identifier(_) | Token::LeftParen
)
{
let count = self.parse_const_suffix()?;
let value = elements.remove(0);
let element_type = value.resolved_type.clone();
if let ConstExpression::Integer(n) = &count {
let expanded: Vec<Expression> =
std::iter::repeat_n(value, *n as usize).collect();
return Ok(Expression::new(
ExpressionKind::ArrayLiteral(expanded),
Type::Array(Box::new(element_type), count),
));
}
return Ok(Expression::new(
ExpressionKind::ArrayRepeat(Box::new(value), count.clone()),
Type::Array(Box::new(element_type), count),
));
}
let element_type = elements
.first()
.map_or(Type::Inferred, |element| element.resolved_type.clone());
let length = elements.len();
Ok(Expression::new(
ExpressionKind::ArrayLiteral(elements),
Type::Array(
Box::new(element_type),
ConstExpression::Integer(length as u128),
),
))
}
Token::If => self.parse_if_expression(),
Token::Match => self.parse_match_expression(),
Token::Print => {
self.advance();
self.expect(Token::LeftParen)?;
let mut arguments = Vec::new();
if !self.at(&Token::RightParen) {
arguments.push(auto_deref(self.parse_expression()?, &self.context));
while self.at(&Token::Comma) {
self.advance();
arguments.push(auto_deref(self.parse_expression()?, &self.context));
}
}
self.expect(Token::RightParen)?;
Ok(Expression::new(
ExpressionKind::Print(arguments),
Type::unit(),
))
}
Token::Call => {
self.advance();
self.expect(Token::LeftParen)?;
let callee = auto_deref(self.parse_expression()?, &self.context);
let callee_type = self.context.resolve_named(&callee.resolved_type);
let (parameter_types, return_type) = if let Type::Function(signature) = callee_type
{
(Some(signature.parameters.clone()), *signature.return_type)
} else {
(None, Type::Inferred)
};
let mut arguments = Vec::new();
while self.at(&Token::Comma) {
self.advance();
let argument = self.parse_expression()?;
let expects_pointer = parameter_types.as_ref().is_some_and(|parameters| {
arguments.len() < parameters.len()
&& matches!(
self.context.resolve_named(¶meters[arguments.len()]),
Type::Pointer(..)
)
});
arguments.push(if expects_pointer {
argument
} else {
auto_deref(argument, &self.context)
});
}
self.expect(Token::RightParen)?;
Ok(Expression::new(
ExpressionKind::Call(Box::new(callee), arguments),
return_type,
))
}
Token::At => {
self.advance();
let Token::Integer(index) = self.peek().clone() else {
return Err(Error {
message: "expected integer after '@'".into(),
span: Some(self.span()),
});
};
self.advance();
let it = Expression::new(ExpressionKind::Variable("it".into()), Type::Inferred);
Ok(Expression::new(
ExpressionKind::Index(
Box::new(it),
Box::new(Expression::new(
ExpressionKind::Literal(Literal::Integer(index)),
Type::Int(IntWidth::W64, Signedness::Unsigned),
)),
),
Type::Inferred,
))
}
Token::Sizeof => {
self.advance();
self.expect(Token::LeftParen)?;
let target_type = self.parse_type()?;
self.expect(Token::RightParen)?;
Ok(Expression::new(
ExpressionKind::SizeOf(target_type),
Type::Int(IntWidth::W64, Signedness::Unsigned),
))
}
Token::LeftBrace => {
self.advance();
if self.at(&Token::RightBrace) {
self.advance();
return Ok(Expression::new(
ExpressionKind::Block(Block::empty()),
Type::unit(),
));
}
if !self.is_statement_start() {
let first = self.parse_expression()?;
if self.at(&Token::Comma) {
self.advance();
let mut elements = vec![auto_deref(first, &self.context)];
while !self.at(&Token::RightBrace) && !self.at(&Token::End) {
elements.push(auto_deref(self.parse_expression()?, &self.context));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
self.expect(Token::RightBrace)?;
let element_type = elements
.first()
.map_or(Type::Inferred, |element| element.resolved_type.clone());
let length = elements.len();
return Ok(Expression::new(
ExpressionKind::ArrayLiteral(elements),
Type::Vector(
Box::new(element_type),
ConstExpression::Integer(length as u128),
),
));
}
let block = self.finish_block_after_expression(first)?;
let result_type = block_result_type(&block);
return Ok(Expression::new(ExpressionKind::Block(block), result_type));
}
let block = self.finish_block()?;
let result_type = block_result_type(&block);
Ok(Expression::new(ExpressionKind::Block(block), result_type))
}
_ => Err(Error {
message: format!("expected expression, got {}", self.peek()),
span: Some(self.span()),
}),
}
}
fn is_type_construction_ahead(&self, name: &str) -> bool {
let is_tuple_newtype = self
.context
.newtypes
.get(name)
.is_some_and(|inner| matches!(inner, Type::Tuple(fields) if !fields.is_empty()));
if !is_tuple_newtype {
return false;
}
matches!(self.peek_at(1), Token::RightBrace)
|| matches!(self.peek_at(1), Token::Identifier(_))
}
fn parse_if_expression(&mut self) -> Result<Expression> {
self.advance();
let condition = auto_deref(self.parse_expression()?, &self.context);
let then_branch = self.parse_block()?;
let else_branch = if self.at(&Token::Else) {
self.advance();
if self.at(&Token::If) {
let if_expression = self.parse_if_expression()?;
Some(Block::expression(if_expression))
} else {
Some(self.parse_block()?)
}
} else {
None
};
let result_type = block_result_type(&then_branch);
Ok(Expression::new(
ExpressionKind::If {
condition: Box::new(condition),
then_branch,
else_branch,
},
result_type,
))
}
fn parse_match_expression(&mut self) -> Result<Expression> {
self.advance();
let value = auto_deref(self.parse_expression()?, &self.context);
self.expect(Token::LeftBrace)?;
let mut arms = Vec::new();
while !self.at(&Token::RightBrace) && !self.at(&Token::End) {
let pattern = self.parse_match_pattern()?;
self.expect(Token::FatArrow)?;
if let MatchPattern::Variant(ref variant_name, ref binding_name) = pattern {
let variant_type = Type::Named(variant_name.clone(), vec![]);
self.context.push_scope();
self.context
.define_variable(binding_name.clone(), variant_type);
}
let body = if self.at(&Token::LeftBrace) {
let block = self.parse_block()?;
if self.at(&Token::Comma) {
self.advance();
}
block
} else {
let expression = auto_deref(self.parse_expression()?, &self.context);
if self.at(&Token::Comma) {
self.advance();
}
Block::expression(expression)
};
if matches!(pattern, MatchPattern::Variant(..)) {
self.context.pop_scope();
}
arms.push(MatchArm { pattern, body });
}
self.expect(Token::RightBrace)?;
let result_type = arms
.first()
.map_or_else(Type::unit, |arm| block_result_type(&arm.body));
Ok(Expression::new(
ExpressionKind::Match {
value: Box::new(value),
arms,
},
result_type,
))
}
fn parse_match_pattern(&mut self) -> Result<MatchPattern> {
match self.peek().clone() {
Token::Integer(value) => {
self.advance();
Ok(MatchPattern::Integer(value))
}
Token::Identifier(name) if name == "_" => {
self.advance();
Ok(MatchPattern::Wildcard)
}
Token::Identifier(name) => {
self.advance();
if self.at(&Token::LeftParen) {
self.advance();
let binding = self.expect_identifier()?;
self.expect(Token::RightParen)?;
Ok(MatchPattern::Variant(name, binding))
} else {
Ok(MatchPattern::Variable(name))
}
}
_ => Err(Error {
message: format!("expected match pattern, got {}", self.peek()),
span: Some(self.span()),
}),
}
}
fn parse_call(&mut self, callee: Expression) -> Result<Expression> {
let mut arguments = Vec::new();
if !self.at(&Token::RightParen) {
arguments.push(self.parse_expression()?);
while self.at(&Token::Comma) {
self.advance();
arguments.push(self.parse_expression()?);
}
}
self.expect(Token::RightParen)?;
let parameter_types = if let ExpressionKind::Variable(ref name) = callee.kind {
self.context.function_params.get(name).map(Vec::as_slice)
} else {
None
};
let arguments: Vec<Expression> = arguments
.into_iter()
.enumerate()
.map(|(index, argument)| {
let expects_pointer = parameter_types.is_some_and(|parameters| {
index < parameters.len()
&& matches!(
self.context.resolve_named(¶meters[index]),
Type::Pointer(..)
)
});
if expects_pointer {
argument
} else {
auto_deref(argument, &self.context)
}
})
.collect();
let return_type = if let ExpressionKind::Variable(ref name) = callee.kind {
self.context
.lookup_function(name)
.cloned()
.unwrap_or(Type::Inferred)
} else {
Type::Inferred
};
Ok(Expression::new(
ExpressionKind::Call(Box::new(callee), arguments),
return_type,
))
}
fn parse_type_construction(&mut self, name: String) -> Result<Expression> {
self.advance();
let named_fields = matches!(
(self.peek(), self.peek_at(1)),
(Token::Identifier(_), Token::Colon)
);
let mut fields = Vec::new();
if named_fields {
while !self.at(&Token::RightBrace) {
let field_name = self.expect_identifier()?;
self.expect(Token::Colon)?;
let value = auto_deref(self.parse_expression()?, &self.context);
fields.push((field_name, value));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
} else {
let mut values = Vec::new();
while !self.at(&Token::RightBrace) {
values.push(auto_deref(self.parse_expression()?, &self.context));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
fields = self.match_fields_by_type(&name, values)?;
}
self.expect(Token::RightBrace)?;
let constructed_type = Type::Named(name.clone(), vec![]);
Ok(Expression::new(
ExpressionKind::TypeConstruction(name, vec![], fields),
constructed_type,
))
}
fn match_fields_by_type(
&self,
type_name: &str,
values: Vec<Expression>,
) -> Result<Vec<(String, Expression)>> {
let Some(Type::Tuple(field_types)) = self.context.newtypes.get(type_name) else {
return Err(Error {
span: Some(self.span()),
message: format!("'{type_name}' is not a tuple type"),
});
};
let mut fields = Vec::new();
let mut used = vec![false; values.len()];
for field_type in field_types {
let Type::Named(field_name, _) = field_type else {
return Err(Error {
span: Some(self.span()),
message: format!("'{type_name}': cannot match unnamed field by type"),
});
};
let position = values.iter().enumerate().find_map(|(index, value)| {
if !used[index] && Self::types_match(&value.resolved_type, field_name) {
Some(index)
} else {
None
}
});
let Some(position) = position else {
return Err(Error {
span: Some(self.span()),
message: format!("'{type_name}': no value matches field '{field_name}'"),
});
};
used[position] = true;
fields.push((field_name.clone(), values[position].clone()));
}
Ok(fields)
}
fn types_match(resolved: &Type, field_name: &str) -> bool {
matches!(resolved, Type::Named(name, _) if name == field_name)
}
fn parse_simple_type_construction(&mut self, name: String) -> Result<Expression> {
self.advance();
let is_tuple = self
.context
.newtypes
.get(&name)
.is_some_and(|inner| matches!(inner, Type::Tuple(_)));
let constructed_type = Type::Named(name.clone(), vec![]);
if is_tuple && self.at(&Token::LeftParen) {
self.advance();
let mut values = Vec::new();
while !self.at(&Token::RightParen) {
values.push(auto_deref(self.parse_expression()?, &self.context));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
self.expect(Token::RightParen)?;
let fields = self.match_fields_by_type(&name, values)?;
Ok(Expression::new(
ExpressionKind::TypeConstruction(name, vec![], fields),
constructed_type,
))
} else {
let value = auto_deref(self.parse_expression()?, &self.context);
Ok(Expression::new(
ExpressionKind::Convert(Box::new(value), constructed_type.clone()),
constructed_type,
))
}
}
fn resolve_field(&self, object: Expression, field: String) -> Expression {
let field_type = match &object.resolved_type {
Type::Named(type_name, _) => self
.context
.lookup_field(type_name, &field)
.unwrap_or(Type::Inferred),
Type::Pointer(mutability, lifetime, inner) => {
if let Type::Named(type_name, _) = inner.as_ref() {
let base = self
.context
.lookup_field(type_name, &field)
.unwrap_or(Type::Inferred);
Type::Pointer(*mutability, lifetime.clone(), Box::new(base))
} else {
Type::Inferred
}
}
_ => Type::Inferred,
};
Expression::new(ExpressionKind::Field(Box::new(object), field), field_type)
}
fn resolve_index(&self, array: Expression, index: Expression) -> Expression {
let resolved = self.context.resolve_named(&array.resolved_type);
let element_type = match &resolved {
Type::Array(inner, _) | Type::Vector(inner, _) => (**inner).clone(),
Type::Pointer(mutability, lifetime, inner) => match self.context.resolve_named(inner) {
Type::Array(element, _) => Type::Pointer(*mutability, lifetime.clone(), element),
other => other,
},
Type::Slice(_, inner) => (**inner).clone(),
_ => Type::Inferred,
};
Expression::new(
ExpressionKind::Index(Box::new(array), Box::new(index)),
element_type,
)
}
}