From 5deb585054e9fedfa6926fe79fc0522fbe0345b6 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 19 Sep 2024 13:20:19 -0500 Subject: [PATCH] cl-ast: Add float support - Smuggle floats as integers to maintain `eq` - This is bad, but not terrible for spec-compliant floats. Might have issues with NaN. cl_parser: Smuggle floats cl_interpret: unpack smuggled floats in float literal node --- compiler/cl-ast/src/ast.rs | 1 + compiler/cl-ast/src/ast_impl.rs | 1 + compiler/cl-ast/src/ast_visitor/fold.rs | 4 ++++ compiler/cl-ast/src/ast_visitor/visit.rs | 2 ++ compiler/cl-interpret/src/interpret.rs | 2 +- compiler/cl-parser/src/parser.rs | 2 +- 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index b7275d0..d07c9cd 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -36,6 +36,7 @@ pub enum Literal { Bool(bool), Char(char), Int(u128), + Float(u64), String(String), } diff --git a/compiler/cl-ast/src/ast_impl.rs b/compiler/cl-ast/src/ast_impl.rs index 1e717bd..679a0bf 100644 --- a/compiler/cl-ast/src/ast_impl.rs +++ b/compiler/cl-ast/src/ast_impl.rs @@ -50,6 +50,7 @@ mod display { Literal::Bool(v) => v.fmt(f), Literal::Char(v) => write!(f, "'{}'", v.escape_debug()), Literal::Int(v) => v.fmt(f), + Literal::Float(v) => f64::from_bits(*v).fmt(f), Literal::String(v) => write!(f, "\"{}\"", v.escape_debug()), } } diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index ce16d7d..1252a4f 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -37,6 +37,9 @@ pub trait Fold { fn fold_int(&mut self, i: u128) -> u128 { i } + fn fold_smuggled_float(&mut self, f: u64) -> u64 { + f + } fn fold_string(&mut self, s: String) -> String { s } @@ -384,6 +387,7 @@ pub fn or_fold_literal(folder: &mut F, lit: Literal) -> Litera Literal::Bool(b) => Literal::Bool(folder.fold_bool(b)), Literal::Char(c) => Literal::Char(folder.fold_char(c)), Literal::Int(i) => Literal::Int(folder.fold_int(i)), + Literal::Float(f) => Literal::Float(folder.fold_smuggled_float(f)), Literal::String(s) => Literal::String(folder.fold_string(s)), } } diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index 59754a8..df4b74d 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -23,6 +23,7 @@ pub trait Visit<'a>: Sized { fn visit_bool(&mut self, _b: &'a bool) {} fn visit_char(&mut self, _c: &'a char) {} fn visit_int(&mut self, _i: &'a u128) {} + fn visit_smuggled_float(&mut self, _f: &'a u64) {} fn visit_string(&mut self, _s: &'a str) {} fn visit_file(&mut self, f: &'a File) { let File { items } = f; @@ -339,6 +340,7 @@ pub fn or_visit_literal<'a, V: Visit<'a>>(visitor: &mut V, l: &'a Literal) { Literal::Bool(b) => visitor.visit_bool(b), Literal::Char(c) => visitor.visit_char(c), Literal::Int(i) => visitor.visit_int(i), + Literal::Float(f) => visitor.visit_smuggled_float(f), Literal::String(s) => visitor.visit_string(s), } } diff --git a/compiler/cl-interpret/src/interpret.rs b/compiler/cl-interpret/src/interpret.rs index 6cb3c7d..52977cc 100644 --- a/compiler/cl-interpret/src/interpret.rs +++ b/compiler/cl-interpret/src/interpret.rs @@ -453,7 +453,7 @@ impl Interpret for Literal { Literal::String(value) => ConValue::from(value.as_str()), Literal::Char(value) => ConValue::Char(*value), Literal::Bool(value) => ConValue::Bool(*value), - // Literal::Float(value) => todo!("Float values in interpreter: {value:?}"), + Literal::Float(value) => ConValue::Float(f64::from_bits(*value)), Literal::Int(value) => ConValue::Int(*value as _), }) } diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index afe86fe..939f472 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -245,7 +245,7 @@ impl Parse<'_> for Literal { TokenData::String(v) => Literal::String(v), TokenData::Character(v) => Literal::Char(v), TokenData::Integer(v) => Literal::Int(v), - TokenData::Float(v) => todo!("Literal::Float({v})"), + TokenData::Float(v) => Literal::Float(v.to_bits()), _ => panic!("Expected token data for {ty:?}"), }) }