feat: implement type classes / traits
Add support for type classes (traits) with full parsing, type checking, and
validation. The implementation includes:
- Trait declarations: trait Show { fn show(x: T): String }
- Trait implementations: impl Show for Int { fn show(x: Int) = ... }
- Super traits: trait Ord: Eq { ... }
- Trait constraints in where clauses: where T: Show + Eq
- Type parameters on traits: trait Functor<F> { ... }
- Default method implementations
- Validation of required method implementations
This provides a foundation for ad-hoc polymorphism and enables
more expressive type-safe abstractions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
265
src/parser.rs
265
src/parser.rs
@@ -215,7 +215,9 @@ impl Parser {
|
||||
TokenKind::Handler => Ok(Declaration::Handler(self.parse_handler_decl()?)),
|
||||
TokenKind::Type => Ok(Declaration::Type(self.parse_type_decl(visibility)?)),
|
||||
TokenKind::Let => Ok(Declaration::Let(self.parse_let_decl(visibility)?)),
|
||||
_ => Err(self.error("Expected declaration (fn, effect, handler, type, or let)")),
|
||||
TokenKind::Trait => Ok(Declaration::Trait(self.parse_trait_decl(visibility)?)),
|
||||
TokenKind::Impl => Ok(Declaration::Impl(self.parse_impl_decl()?)),
|
||||
_ => Err(self.error("Expected declaration (fn, effect, handler, type, trait, impl, or let)")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,6 +505,267 @@ impl Parser {
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse trait declaration: trait Show { fn show(self): String }
|
||||
fn parse_trait_decl(&mut self, visibility: Visibility) -> Result<TraitDecl, ParseError> {
|
||||
let start = self.current_span();
|
||||
self.expect(TokenKind::Trait)?;
|
||||
|
||||
let name = self.parse_ident()?;
|
||||
|
||||
// Optional type parameters: trait Functor<F> { ... }
|
||||
let type_params = if self.check(TokenKind::Lt) {
|
||||
self.parse_type_params()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// Optional super traits: trait Ord: Eq { ... }
|
||||
let super_traits = if self.check(TokenKind::Colon) {
|
||||
self.advance();
|
||||
self.parse_trait_bounds()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.expect(TokenKind::LBrace)?;
|
||||
self.skip_newlines();
|
||||
|
||||
let mut methods = Vec::new();
|
||||
while !self.check(TokenKind::RBrace) {
|
||||
methods.push(self.parse_trait_method()?);
|
||||
self.skip_newlines();
|
||||
if self.check(TokenKind::Comma) {
|
||||
self.advance();
|
||||
}
|
||||
self.skip_newlines();
|
||||
}
|
||||
|
||||
let end = self.current_span();
|
||||
self.expect(TokenKind::RBrace)?;
|
||||
|
||||
Ok(TraitDecl {
|
||||
visibility,
|
||||
name,
|
||||
type_params,
|
||||
super_traits,
|
||||
methods,
|
||||
span: start.merge(end),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse a trait method signature
|
||||
fn parse_trait_method(&mut self) -> Result<TraitMethod, ParseError> {
|
||||
let start = self.current_span();
|
||||
self.expect(TokenKind::Fn)?;
|
||||
|
||||
let name = self.parse_ident()?;
|
||||
|
||||
// Optional type parameters
|
||||
let type_params = if self.check(TokenKind::Lt) {
|
||||
self.parse_type_params()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.expect(TokenKind::LParen)?;
|
||||
let params = self.parse_params()?;
|
||||
self.expect(TokenKind::RParen)?;
|
||||
|
||||
self.expect(TokenKind::Colon)?;
|
||||
let return_type = self.parse_type()?;
|
||||
|
||||
// Optional default implementation
|
||||
let default_impl = if self.check(TokenKind::Eq) {
|
||||
self.advance();
|
||||
self.skip_newlines();
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let span = start.merge(self.previous_span());
|
||||
Ok(TraitMethod {
|
||||
name,
|
||||
type_params,
|
||||
params,
|
||||
return_type,
|
||||
default_impl,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse trait bounds: Eq + Ord + Show
|
||||
fn parse_trait_bounds(&mut self) -> Result<Vec<TraitBound>, ParseError> {
|
||||
let mut bounds = Vec::new();
|
||||
|
||||
loop {
|
||||
bounds.push(self.parse_trait_bound()?);
|
||||
|
||||
if self.check(TokenKind::Plus) {
|
||||
self.advance();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(bounds)
|
||||
}
|
||||
|
||||
/// Parse a single trait bound: Show, Functor<F>
|
||||
fn parse_trait_bound(&mut self) -> Result<TraitBound, ParseError> {
|
||||
let start = self.current_span();
|
||||
let trait_name = self.parse_ident()?;
|
||||
|
||||
let type_args = if self.check(TokenKind::Lt) {
|
||||
self.advance();
|
||||
let mut args = Vec::new();
|
||||
while !self.check(TokenKind::Gt) {
|
||||
args.push(self.parse_type()?);
|
||||
if !self.check(TokenKind::Gt) {
|
||||
self.expect(TokenKind::Comma)?;
|
||||
}
|
||||
}
|
||||
self.expect(TokenKind::Gt)?;
|
||||
args
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let span = start.merge(self.previous_span());
|
||||
Ok(TraitBound {
|
||||
trait_name,
|
||||
type_args,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse impl declaration: impl Show for Int { ... }
|
||||
fn parse_impl_decl(&mut self) -> Result<ImplDecl, ParseError> {
|
||||
let start = self.current_span();
|
||||
self.expect(TokenKind::Impl)?;
|
||||
|
||||
// Optional type parameters: impl<T> Show for List<T> { ... }
|
||||
let type_params = if self.check(TokenKind::Lt) {
|
||||
self.parse_type_params()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// Parse the trait name
|
||||
let trait_name = self.parse_ident()?;
|
||||
|
||||
// Optional type arguments for the trait: impl Functor<List> for ...
|
||||
let trait_args = if self.check(TokenKind::Lt) {
|
||||
self.advance();
|
||||
let mut args = Vec::new();
|
||||
while !self.check(TokenKind::Gt) {
|
||||
args.push(self.parse_type()?);
|
||||
if !self.check(TokenKind::Gt) {
|
||||
self.expect(TokenKind::Comma)?;
|
||||
}
|
||||
}
|
||||
self.expect(TokenKind::Gt)?;
|
||||
args
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.expect(TokenKind::For)?;
|
||||
let target_type = self.parse_type()?;
|
||||
|
||||
// Optional where clause with trait constraints
|
||||
let constraints = if self.check(TokenKind::Where) {
|
||||
self.parse_trait_constraints()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.expect(TokenKind::LBrace)?;
|
||||
self.skip_newlines();
|
||||
|
||||
let mut methods = Vec::new();
|
||||
while !self.check(TokenKind::RBrace) {
|
||||
methods.push(self.parse_impl_method()?);
|
||||
self.skip_newlines();
|
||||
if self.check(TokenKind::Comma) {
|
||||
self.advance();
|
||||
}
|
||||
self.skip_newlines();
|
||||
}
|
||||
|
||||
let end = self.current_span();
|
||||
self.expect(TokenKind::RBrace)?;
|
||||
|
||||
Ok(ImplDecl {
|
||||
type_params,
|
||||
constraints,
|
||||
trait_name,
|
||||
trait_args,
|
||||
target_type,
|
||||
methods,
|
||||
span: start.merge(end),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse trait constraints in a where clause: where T: Show, U: Eq + Ord
|
||||
fn parse_trait_constraints(&mut self) -> Result<Vec<TraitConstraint>, ParseError> {
|
||||
let mut constraints = Vec::new();
|
||||
|
||||
while self.check(TokenKind::Where) {
|
||||
self.advance();
|
||||
let start = self.current_span();
|
||||
let type_param = self.parse_ident()?;
|
||||
self.expect(TokenKind::Colon)?;
|
||||
let bounds = self.parse_trait_bounds()?;
|
||||
let span = start.merge(self.previous_span());
|
||||
|
||||
constraints.push(TraitConstraint {
|
||||
type_param,
|
||||
bounds,
|
||||
span,
|
||||
});
|
||||
|
||||
if self.check(TokenKind::Comma) {
|
||||
self.advance();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(constraints)
|
||||
}
|
||||
|
||||
/// Parse an impl method
|
||||
fn parse_impl_method(&mut self) -> Result<ImplMethod, ParseError> {
|
||||
let start = self.current_span();
|
||||
self.expect(TokenKind::Fn)?;
|
||||
|
||||
let name = self.parse_ident()?;
|
||||
|
||||
self.expect(TokenKind::LParen)?;
|
||||
let params = self.parse_params()?;
|
||||
self.expect(TokenKind::RParen)?;
|
||||
|
||||
// Optional return type (infer if not provided)
|
||||
let return_type = if self.check(TokenKind::Colon) {
|
||||
self.advance();
|
||||
Some(self.parse_type()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.expect(TokenKind::Eq)?;
|
||||
self.skip_newlines();
|
||||
let body = self.parse_expr()?;
|
||||
|
||||
let span = start.merge(body.span());
|
||||
Ok(ImplMethod {
|
||||
name,
|
||||
params,
|
||||
return_type,
|
||||
body,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse type parameters <A, B, C>
|
||||
fn parse_type_params(&mut self) -> Result<Vec<Ident>, ParseError> {
|
||||
self.expect(TokenKind::Lt)?;
|
||||
|
||||
Reference in New Issue
Block a user