use super::*;
impl Parser {
pub(super) fn parse_generic_parameters(&mut self) -> Result<Vec<GenericParameter>> {
if !self.at(&Token::LeftBracket) {
return Ok(vec![]);
}
self.advance();
let mut parameters = Vec::new();
if !self.at(&Token::RightBracket) {
loop {
let name = self.expect_identifier()?;
parameters.push(GenericParameter {
name,
kind: GenericParameterKind::Type,
});
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
}
self.expect(Token::RightBracket)?;
if let Token::Identifier(name) = self.peek().clone()
&& self.context.newtypes.contains_key(&name)
&& !matches!(self.peek_at(1), Token::LeftBracket)
{
self.advance();
parameters.push(GenericParameter {
name: name.clone(),
kind: GenericParameterKind::Const(Type::Named(name, vec![])),
});
}
Ok(parameters)
}
pub(super) fn parse_generic_arguments(
&mut self,
target_name: &str,
) -> Result<Vec<GenericArgument>> {
self.advance();
let mut arguments = Vec::new();
if !self.at(&Token::RightBracket) {
loop {
arguments.push(GenericArgument::Type(self.parse_type()?));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
}
self.expect(Token::RightBracket)?;
let has_const_param = self
.context
.generic_parameter_kinds
.get(target_name)
.is_some_and(|kinds| {
kinds
.last()
.is_some_and(|kind| matches!(kind, GenericParameterKind::Const(_)))
});
if has_const_param
&& matches!(
self.peek(),
Token::Integer(_) | Token::Identifier(_) | Token::LeftParen | Token::LeftBrace
)
{
arguments.push(GenericArgument::Const(self.parse_const_suffix()?));
}
Ok(arguments)
}
pub(super) fn parse_const_suffix(&mut self) -> Result<ConstExpression> {
match self.peek().clone() {
Token::Integer(value) => {
self.advance();
Ok(ConstExpression::Integer(value))
}
Token::Identifier(name) => {
self.advance();
if self.at(&Token::Dot) {
self.advance();
let field = self.expect_identifier()?;
Ok(ConstExpression::Field(
Box::new(ConstExpression::Named(name)),
field,
))
} else {
Ok(ConstExpression::Named(name))
}
}
Token::LeftParen => {
self.advance();
if matches!(self.peek(), Token::Identifier(_))
&& matches!(self.peek_at(1), Token::Colon)
{
return self.parse_const_construction();
}
let expression = self.parse_const_expression()?;
self.expect(Token::RightParen)?;
Ok(expression)
}
Token::LeftBrace => self.parse_const_construction_braces(),
_ => Err(Error {
message: "expected const suffix (integer, identifier, or parenthesized expression)"
.into(),
span: Some(self.span()),
}),
}
}
fn parse_const_construction(&mut self) -> Result<ConstExpression> {
let mut fields = Vec::new();
loop {
let name = self.expect_identifier()?;
self.expect(Token::Colon)?;
let value = self.parse_const_expression()?;
fields.push((name, value));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
self.expect(Token::RightParen)?;
Ok(ConstExpression::Construction(fields))
}
fn parse_const_construction_braces(&mut self) -> Result<ConstExpression> {
self.advance();
let mut fields = Vec::new();
while !self.at(&Token::RightBrace) {
let name = self.expect_identifier()?;
self.expect(Token::Colon)?;
let value = self.parse_const_expression()?;
fields.push((name, value));
if !self.at(&Token::Comma) {
break;
}
self.advance();
}
self.expect(Token::RightBrace)?;
Ok(ConstExpression::Construction(fields))
}
fn parse_const_expression(&mut self) -> Result<ConstExpression> {
self.parse_const_bitwise_or()
}
fn parse_const_bitwise_or(&mut self) -> Result<ConstExpression> {
let mut left = self.parse_const_bitwise_xor()?;
while self.at(&Token::Pipe) {
self.advance();
let right = self.parse_const_bitwise_xor()?;
left = ConstExpression::BitwiseOr(Box::new(left), Box::new(right));
}
Ok(left)
}
fn parse_const_bitwise_xor(&mut self) -> Result<ConstExpression> {
let mut left = self.parse_const_bitwise_and()?;
while self.at(&Token::Caret) {
self.advance();
let right = self.parse_const_bitwise_and()?;
left = ConstExpression::BitwiseXor(Box::new(left), Box::new(right));
}
Ok(left)
}
fn parse_const_bitwise_and(&mut self) -> Result<ConstExpression> {
let mut left = self.parse_const_shift()?;
while self.at(&Token::Amp) {
self.advance();
let right = self.parse_const_shift()?;
left = ConstExpression::BitwiseAnd(Box::new(left), Box::new(right));
}
Ok(left)
}
fn parse_const_shift(&mut self) -> Result<ConstExpression> {
let mut left = self.parse_const_additive()?;
loop {
if self.at(&Token::LessLess) {
self.advance();
let right = self.parse_const_additive()?;
left = ConstExpression::ShiftLeft(Box::new(left), Box::new(right));
} else if self.at(&Token::GreaterGreater) {
self.advance();
let right = self.parse_const_additive()?;
left = ConstExpression::ShiftRight(Box::new(left), Box::new(right));
} else {
break;
}
}
Ok(left)
}
fn parse_const_additive(&mut self) -> Result<ConstExpression> {
let mut left = self.parse_const_multiplicative()?;
loop {
if self.at(&Token::Plus) {
self.advance();
let right = self.parse_const_multiplicative()?;
left = ConstExpression::Add(Box::new(left), Box::new(right));
} else if self.at(&Token::Minus) {
self.advance();
let right = self.parse_const_multiplicative()?;
left = ConstExpression::Subtract(Box::new(left), Box::new(right));
} else {
break;
}
}
Ok(left)
}
fn parse_const_multiplicative(&mut self) -> Result<ConstExpression> {
let mut left = self.parse_const_atom()?;
loop {
if self.at(&Token::Star) {
self.advance();
let right = self.parse_const_atom()?;
left = ConstExpression::Multiply(Box::new(left), Box::new(right));
} else if self.at(&Token::Slash) {
self.advance();
let right = self.parse_const_atom()?;
left = ConstExpression::Divide(Box::new(left), Box::new(right));
} else if self.at(&Token::Percent) {
self.advance();
let right = self.parse_const_atom()?;
left = ConstExpression::Modulo(Box::new(left), Box::new(right));
} else {
break;
}
}
Ok(left)
}
fn parse_const_atom(&mut self) -> Result<ConstExpression> {
match self.peek().clone() {
Token::Integer(value) => {
self.advance();
Ok(ConstExpression::Integer(value))
}
Token::Identifier(name) => {
self.advance();
if self.at(&Token::LeftParen) {
self.advance();
let mut arguments = Vec::new();
if !self.at(&Token::RightParen) {
arguments.push(self.parse_const_expression()?);
while self.at(&Token::Comma) {
self.advance();
arguments.push(self.parse_const_expression()?);
}
}
self.expect(Token::RightParen)?;
Ok(ConstExpression::Call(name, arguments))
} else if self.at(&Token::Dot) {
self.advance();
let field = self.expect_identifier()?;
Ok(ConstExpression::Field(
Box::new(ConstExpression::Named(name)),
field,
))
} else {
Ok(ConstExpression::Named(name))
}
}
Token::LeftParen => {
self.advance();
let expression = self.parse_const_expression()?;
self.expect(Token::RightParen)?;
Ok(expression)
}
_ => Err(Error {
message: "expected constant expression".into(),
span: Some(self.span()),
}),
}
}
pub(super) fn parse_type(&mut self) -> Result<Type> {
match self.peek().clone() {
Token::Amp => {
self.advance();
let inner = self.parse_type()?;
Ok(Type::Pointer(
Mutability::Shared,
Lifetime::Inferred,
Box::new(inner),
))
}
Token::Pipe => {
self.advance();
let inner = self.parse_type()?;
Ok(Type::Pointer(
Mutability::Mutable,
Lifetime::Inferred,
Box::new(inner),
))
}
Token::LeftBracket => {
self.advance();
let element = self.parse_type()?;
self.expect(Token::RightBracket)?;
if matches!(
self.peek(),
Token::Integer(_) | Token::Identifier(_) | Token::LeftParen
) {
let size = self.parse_const_expression()?;
Ok(Type::Array(Box::new(element), size))
} else {
Ok(Type::Slice(Mutability::Shared, Box::new(element)))
}
}
Token::LeftBrace => {
self.advance();
let element = self.parse_type()?;
self.expect(Token::RightBrace)?;
let size = self.parse_const_expression()?;
Ok(Type::Vector(Box::new(element), size))
}
Token::LeftParen => {
self.advance();
if self.at(&Token::RightParen) {
self.advance();
return Ok(Type::unit());
}
let inner = self.parse_type()?;
self.expect(Token::RightParen)?;
Ok(inner)
}
Token::Fn => {
self.advance();
self.expect(Token::LeftParen)?;
let mut parameter_types = Vec::new();
if !self.at(&Token::RightParen) {
parameter_types.push(self.parse_type()?);
while self.at(&Token::Comma) {
self.advance();
parameter_types.push(self.parse_type()?);
}
}
self.expect(Token::RightParen)?;
let return_type = if self.at(&Token::Arrow) {
self.advance();
self.parse_type()?
} else {
Type::unit()
};
Ok(Type::Function(FunctionSignature {
parameters: parameter_types,
return_type: Box::new(return_type),
}))
}
Token::Identifier(name) => {
self.advance();
let base = parse_type_name(&name);
if let Type::Named(_, _) = &base
&& self.at(&Token::LeftBracket)
{
let arguments = self.parse_generic_arguments(&name)?;
return Ok(Type::Named(name, arguments));
}
if let Type::Named(ref type_name, _) = base
&& !self.context.newtypes.contains_key(type_name)
&& !self.context.generic_parameter_kinds.contains_key(type_name)
&& !self.context.constants.contains_key(type_name)
&& !self.is_generic_param(type_name)
{
return Err(Error {
message: format!("unknown type '{type_name}'"),
span: Some(self.span()),
});
}
Ok(base)
}
_ => Err(Error {
message: format!("expected type, got {}", self.peek()),
span: Some(self.span()),
}),
}
}
fn parse_type_product_raw(&mut self) -> Result<Type> {
let first = self.parse_type()?;
if self.at(&Token::Amp) {
let mut fields = vec![first];
while self.at(&Token::Amp) {
self.advance();
fields.push(self.parse_type()?);
}
Ok(Type::Tuple(fields))
} else {
Ok(first)
}
}
pub(super) fn parse_type_expression_raw(&mut self) -> Result<Type> {
let first = self.parse_type_product_raw()?;
if self.at(&Token::Pipe) {
let mut variants = vec![first];
while self.at(&Token::Pipe) {
self.advance();
variants.push(self.parse_type_product_raw()?);
}
Ok(Type::Enum(variants))
} else {
Ok(first)
}
}
pub(super) fn parse_type_expression(&mut self) -> Result<Type> {
let resolved_type = self.parse_type_expression_raw()?;
Ok(match resolved_type {
Type::Tuple(_) | Type::Enum(_) => self.register_anonymous_compound(resolved_type),
other => other,
})
}
fn register_anonymous_compound(&mut self, compound: Type) -> Type {
for (name, inner) in &self.context.newtypes {
if *inner == compound {
return Type::Named(name.clone(), vec![]);
}
}
let name = anonymous_compound_name(&compound);
self.context.newtypes.insert(name.clone(), compound.clone());
self.anonymous_types.push(Declaration::Type(Newtype {
name: name.clone(),
generic_parameters: vec![],
inner_type: compound,
public: false,
}));
Type::Named(name, vec![])
}
pub(super) fn parse_generic_type_expression(
&mut self,
name: String,
generic_arguments: Vec<GenericArgument>,
) -> Result<Expression> {
let constructed_type = Type::Named(name.clone(), generic_arguments.clone());
if self.at(&Token::LeftBrace) {
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();
}
}
self.expect(Token::RightBrace)?;
Ok(Expression::new(
ExpressionKind::TypeConstruction(name, generic_arguments, fields),
constructed_type,
))
} else if self.at(&Token::Colon) {
self.advance();
let value = auto_deref(self.parse_expression()?, &self.context);
Ok(Expression::new(
ExpressionKind::Convert(Box::new(value), constructed_type.clone()),
constructed_type,
))
} else {
let inner = Expression::new(ExpressionKind::Variable(name), Type::Inferred);
Ok(Expression::new(
ExpressionKind::Specialize(Box::new(inner), generic_arguments),
constructed_type,
))
}
}
}