From e4582ec85abbaab8bf32c41f159f7c8bd44e8485 Mon Sep 17 00:00:00 2001 From: Toni Date: Wed, 24 Jun 2026 18:06:58 +0200 Subject: [PATCH] float literals --- src/codegen_x86_64.rs | 20 +++++++++++++++++++- src/parser.rs | 1 + src/std/linux_constants.zr | 34 +++++++++++++++++----------------- src/symbol_table.rs | 4 ++++ src/tokenizer.rs | 19 ++++++++++++++++++- src/typechecker.rs | 5 +++-- 6 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 675b41c..b34a1e2 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -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,7 +652,12 @@ _builtin_environ: self.compile_expr(env, right)?; match op.token_type { TokenType::Minus => { - emit!(&mut self.output, " neg rax"); + 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"); diff --git a/src/parser.rs b/src/parser.rs index e3d3ced..b115c1f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -675,6 +675,7 @@ impl Parser { fn primary(&mut self) -> Result { if self.match_token(&[ TokenType::IntLiteral, + TokenType::FloatLiteral, TokenType::CharLiteral, TokenType::StringLiteral, TokenType::True, diff --git a/src/std/linux_constants.zr b/src/std/linux_constants.zr index 76a093c..3513e42 100644 --- a/src/std/linux_constants.zr +++ b/src/std/linux_constants.zr @@ -1,28 +1,28 @@ -const STDIN = 0 -const STDOUT = 1 +const STDIN = 0 +const STDOUT = 1 -const SIGABRT = 6 +const SIGABRT = 6 -const AT_FDCWD = -100 +const AT_FDCWD = -100 -const S_IFDIR = 0o040000 -const S_IFMT = 0o170000 +const S_IFDIR = 0o040000 +const S_IFMT = 0o170000 -const PROT_READ = 1 -const PROT_WRITE = 2 +const PROT_READ = 1 +const PROT_WRITE = 2 -const MAP_PRIVATE = 2 -const MAP_ANONYMOUS = 32 +const MAP_PRIVATE = 2 +const MAP_ANONYMOUS = 32 -const O_RDONLY = 0 -const O_WRONLY = 1 -const O_CREAT = 64 -const O_TRUNC = 512 +const O_RDONLY = 0 +const O_WRONLY = 1 +const O_CREAT = 64 +const O_TRUNC = 512 -const SEEK_SET = 0 -const SEEK_END = 2 +const SEEK_SET = 0 +const SEEK_END = 2 -const F_OK = 0 +const F_OK = 0 const SYS_read = 0 const SYS_write = 1 diff --git a/src/symbol_table.rs b/src/symbol_table.rs index 3261704..26b9456 100644 --- a/src/symbol_table.rs +++ b/src/symbol_table.rs @@ -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"])), diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 583e790..7aab9a7 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -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,9 +353,23 @@ 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(); + } + } } - self.add_token(TokenType::IntLiteral) + if is_float { + self.add_token(TokenType::FloatLiteral) + } else { + self.add_token(TokenType::IntLiteral) + } } fn scan_identifier(&mut self) -> Result<(), ZernError> { diff --git a/src/typechecker.rs b/src/typechecker.rs index 9186683..caea63e 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -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);