Skip to content

Commit

Permalink
Added support for generic character literals
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacShelton committed Sep 27, 2024
1 parent 35da9bb commit 3acd1af
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/ast/expr/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum ExprKind {
Boolean(bool),
Integer(Integer),
Float(f64),
Char(String),
String(String),
NullTerminatedString(CString),
CharLiteral(u8),
Expand Down
14 changes: 13 additions & 1 deletion src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,16 @@ impl<T: Text + Send> Lexer<T> {
});
Waiting
}
'\'' => {
// Rune Literal
self.state = State::String(StringState {
value: String::new(),
closing_char: '\'',
modifier: StringModifier::RuneLiteral,
start_source: source,
});
Waiting
}
_ if c.is_alphabetic() || c == '_' => {
self.state = State::Identifier(IdentifierState {
identifier: String::from(c),
Expand Down Expand Up @@ -370,7 +380,9 @@ impl<T: Text + Send> Lexer<T> {
StringModifier::Normal | StringModifier::NullTerminated => {
"Unclosed string literal"
}
StringModifier::CharLiteral => "Unclosed character literal",
StringModifier::RuneLiteral | StringModifier::CharLiteral => {
"Unclosed character literal"
}
};

return Has(TokenKind::Error(message.into()).at(state.start_source));
Expand Down
7 changes: 7 additions & 0 deletions src/parser/parse_expr/primary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
source,
))
}
TokenKind::String(StringLiteral {
modifier: StringModifier::RuneLiteral,
..
}) => {
let content = self.input.advance().kind.unwrap_string().value;
Ok(Expr::new(ExprKind::Char(content), source))
}
TokenKind::OpenParen => {
self.input.advance().kind.unwrap_open_paren();
let inner = self.parse_expr()?;
Expand Down
7 changes: 7 additions & 0 deletions src/resolve/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub enum ResolveErrorKind {
AmbiguousSymbol {
name: String,
},
UndeterminedCharacterLiteral,
Other {
message: String,
},
Expand Down Expand Up @@ -418,6 +419,12 @@ impl Display for ResolveErrorKind {
ResolveErrorKind::AmbiguousSymbol { name } => {
write!(f, "Ambiguous symbol '{name}'")?;
}
ResolveErrorKind::UndeterminedCharacterLiteral => {
write!(
f,
"Undetermined character literal, consider using c'A' if you want a 'char'"
)?;
}
ResolveErrorKind::Other { message } => {
write!(f, "{}", message)?;
}
Expand Down
24 changes: 23 additions & 1 deletion src/resolve/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl<'a> PreferredType<'a> {
}

pub fn resolve_expr(
ctx: &mut ResolveExprCtx<'_, '_>,
ctx: &mut ResolveExprCtx,
ast_expr: &ast::Expr,
preferred_type: Option<PreferredType>,
initialized: Initialized,
Expand All @@ -140,6 +140,28 @@ pub fn resolve_expr(
ast::ExprKind::Variable(name) => {
resolve_variable_expr(ctx, name, preferred_type, initialized, source)
}
ast::ExprKind::Char(content) => {
if content.len() == 1 {
if let Some(preferred_type) = preferred_type {
if let TypeKind::CInteger(CInteger::Char, _) =
preferred_type.view(ctx.resolved_ast).kind
{
let expr = resolved::ExprKind::IntegerKnown(Box::new(IntegerKnown {
rigidity: ast::IntegerRigidity::Loose(CInteger::Char, None),
value: content.as_bytes()[0].into(),
}))
.at(source);

return Ok(TypedExpr::new(
resolved::TypeKind::CInteger(CInteger::Char, None).at(source),
expr,
));
}
}
}

Err(ResolveErrorKind::UndeterminedCharacterLiteral.at(source))
}
ast::ExprKind::Integer(value) => {
let (resolved_type, expr) = match value {
ast::Integer::Known(known) => (
Expand Down
1 change: 1 addition & 0 deletions src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub enum StringModifier {
Normal,
NullTerminated,
CharLiteral,
RuneLiteral,
}

#[derive(Clone, Debug, PartialEq)]
Expand Down
12 changes: 12 additions & 0 deletions tests/character_literals/main.adept
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

#[foreign]
func printf(format ptr<char>, ...) int

func main {
letter char = 'A' // Generic character literal
another_letter := c'B' // C `char` literal

printf(c"letter = %c\n", letter)
printf(c"another_letter = %c\n", another_letter)
}

1 change: 1 addition & 0 deletions tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ compile annotation_groups
compile array_access
compile bitwise_operators
compile c_printf
compile character_literals
compile comparison_operators
compile defines
compile enums
Expand Down

0 comments on commit 3acd1af

Please sign in to comment.