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 cvttsd2si rax, xmm0
ret ret
section .text._builtin_f64_to_float
_builtin_f64_to_float:
cvtsd2ss xmm0, xmm0
movd eax, xmm0
ret
section .text._builtin_syscall section .text._builtin_syscall
_builtin_syscall: _builtin_syscall:
mov rax, rdi mov rax, rdi
@@ -603,6 +609,13 @@ _builtin_environ:
TokenType::IntLiteral => { TokenType::IntLiteral => {
emit!(&mut self.output, " mov rax, {}", token.lexeme); emit!(&mut self.output, " mov rax, {}", token.lexeme);
} }
TokenType::FloatLiteral => {
emit!(
&mut self.output,
" mov rax, __float64__({})",
token.lexeme
);
}
TokenType::CharLiteral => { TokenType::CharLiteral => {
emit!( emit!(
&mut self.output, &mut self.output,
@@ -639,7 +652,12 @@ _builtin_environ:
self.compile_expr(env, right)?; self.compile_expr(env, right)?;
match op.token_type { match op.token_type {
TokenType::Minus => { 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 => { TokenType::Bang => {
emit!(&mut self.output, " test rax, rax"); emit!(&mut self.output, " test rax, rax");

View File

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

View File

@@ -1,28 +1,28 @@
const STDIN = 0 const STDIN = 0
const STDOUT = 1 const STDOUT = 1
const SIGABRT = 6 const SIGABRT = 6
const AT_FDCWD = -100 const AT_FDCWD = -100
const S_IFDIR = 0o040000 const S_IFDIR = 0o040000
const S_IFMT = 0o170000 const S_IFMT = 0o170000
const PROT_READ = 1 const PROT_READ = 1
const PROT_WRITE = 2 const PROT_WRITE = 2
const MAP_PRIVATE = 2 const MAP_PRIVATE = 2
const MAP_ANONYMOUS = 32 const MAP_ANONYMOUS = 32
const O_RDONLY = 0 const O_RDONLY = 0
const O_WRONLY = 1 const O_WRONLY = 1
const O_CREAT = 64 const O_CREAT = 64
const O_TRUNC = 512 const O_TRUNC = 512
const SEEK_SET = 0 const SEEK_SET = 0
const SEEK_END = 2 const SEEK_END = 2
const F_OK = 0 const F_OK = 0
const SYS_read = 0 const SYS_read = 0
const SYS_write = 1 const SYS_write = 1

View File

@@ -53,6 +53,10 @@ impl SymbolTable {
), ),
("_builtin_cvtsi2sd".into(), FnType::new("f64", vec!["i64"])), ("_builtin_cvtsi2sd".into(), FnType::new("f64", vec!["i64"])),
("_builtin_cvttsd2si".into(), FnType::new("i64", vec!["f64"])), ("_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_syscall".into(), FnType::new_variadic("i64")),
("_builtin_environ".into(), FnType::new("ptr", vec![])), ("_builtin_environ".into(), FnType::new("ptr", vec![])),
("_var_arg".into(), FnType::new("any", vec!["i64"])), ("_var_arg".into(), FnType::new("any", vec!["i64"])),

View File

@@ -39,6 +39,7 @@ pub enum TokenType {
StringLiteral, StringLiteral,
CharLiteral, CharLiteral,
IntLiteral, IntLiteral,
FloatLiteral,
True, True,
False, False,
@@ -338,6 +339,8 @@ impl Tokenizer {
} }
fn scan_number(&mut self) -> Result<(), ZernError> { fn scan_number(&mut self) -> Result<(), ZernError> {
let mut is_float = false;
if self.match_char('x') { if self.match_char('x') {
while self.peek().is_ascii_hexdigit() { while self.peek().is_ascii_hexdigit() {
self.advance(); self.advance();
@@ -350,9 +353,23 @@ impl Tokenizer {
while self.peek().is_ascii_digit() { while self.peek().is_ascii_digit() {
self.advance(); 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> { fn scan_identifier(&mut self) -> Result<(), ZernError> {

View File

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