float literals

This commit is contained in:
2026-06-24 18:06:58 +02:00
parent 213e3d4b37
commit e4582ec85a
6 changed files with 62 additions and 21 deletions

View File

@@ -148,6 +148,12 @@ _builtin_cvttsd2si:
cvttsd2si rax, xmm0
ret
section .text._builtin_f64_to_float
_builtin_f64_to_float:
cvtsd2ss xmm0, xmm0
movd eax, xmm0
ret
section .text._builtin_syscall
_builtin_syscall:
mov rax, rdi
@@ -603,6 +609,13 @@ _builtin_environ:
TokenType::IntLiteral => {
emit!(&mut self.output, " mov rax, {}", token.lexeme);
}
TokenType::FloatLiteral => {
emit!(
&mut self.output,
" mov rax, __float64__({})",
token.lexeme
);
}
TokenType::CharLiteral => {
emit!(
&mut self.output,
@@ -639,8 +652,13 @@ _builtin_environ:
self.compile_expr(env, right)?;
match op.token_type {
TokenType::Minus => {
if self.expr_types[&right.id] == "f64" {
emit!(&mut self.output, " mov rbx, 0x8000000000000000");
emit!(&mut self.output, " xor rax, rbx");
} else {
emit!(&mut self.output, " neg rax");
}
}
TokenType::Bang => {
emit!(&mut self.output, " test rax, rax");
emit!(&mut self.output, " sete al");

View File

@@ -675,6 +675,7 @@ impl Parser {
fn primary(&mut self) -> Result<Expr, ZernError> {
if self.match_token(&[
TokenType::IntLiteral,
TokenType::FloatLiteral,
TokenType::CharLiteral,
TokenType::StringLiteral,
TokenType::True,

View File

@@ -53,6 +53,10 @@ impl SymbolTable {
),
("_builtin_cvtsi2sd".into(), FnType::new("f64", vec!["i64"])),
("_builtin_cvttsd2si".into(), FnType::new("i64", vec!["f64"])),
(
"_builtin_f64_to_float".into(),
FnType::new("i64", vec!["f64"]),
),
("_builtin_syscall".into(), FnType::new_variadic("i64")),
("_builtin_environ".into(), FnType::new("ptr", vec![])),
("_var_arg".into(), FnType::new("any", vec!["i64"])),

View File

@@ -39,6 +39,7 @@ pub enum TokenType {
StringLiteral,
CharLiteral,
IntLiteral,
FloatLiteral,
True,
False,
@@ -338,6 +339,8 @@ impl Tokenizer {
}
fn scan_number(&mut self) -> Result<(), ZernError> {
let mut is_float = false;
if self.match_char('x') {
while self.peek().is_ascii_hexdigit() {
self.advance();
@@ -350,10 +353,24 @@ impl Tokenizer {
while self.peek().is_ascii_digit() {
self.advance();
}
if self.current + 1 < self.source.len()
&& self.peek() == '.'
&& self.source[self.current + 1] != '.'
{
is_float = true;
self.advance();
while self.peek().is_ascii_digit() {
self.advance();
}
}
}
if is_float {
self.add_token(TokenType::FloatLiteral)
} else {
self.add_token(TokenType::IntLiteral)
}
}
fn scan_identifier(&mut self) -> Result<(), ZernError> {
while self.peek().is_alphanumeric() || self.peek() == '_' || self.peek() == '.' {

View File

@@ -429,6 +429,7 @@ impl<'a> TypeChecker<'a> {
ExprKind::Grouping(expr) => self.typecheck_expr(env, expr),
ExprKind::Literal(token) => match token.token_type {
TokenType::IntLiteral => Ok("i64".into()),
TokenType::FloatLiteral => Ok("f64".into()),
TokenType::CharLiteral => Ok("u8".into()),
TokenType::StringLiteral => Ok("str".into()),
TokenType::True => Ok("bool".into()),
@@ -439,8 +440,8 @@ impl<'a> TypeChecker<'a> {
let right_type = self.typecheck_expr(env, right)?;
match op.token_type {
TokenType::Minus => {
expect_type!(right_type, "i64", op.loc);
Ok("i64".into())
expect_types!(right_type, ["f64", "i64"], op.loc);
Ok(right_type)
}
TokenType::Bang => {
expect_types!(right_type, ["bool", "i64", "ptr", "u8"], op.loc);