]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Add support for Hexadecimal floating point literals
authorwszqkzqk <wszqkzqk@qq.com>
Fri, 9 Dec 2022 12:07:59 +0000 (20:07 +0800)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 30 Jan 2023 14:04:26 +0000 (15:04 +0100)
https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html#Hex-Floats

tests/Makefile.am
tests/basic-types/floats-hexadecimal.c-expected [new file with mode: 0644]
tests/basic-types/floats-hexadecimal.vala [new file with mode: 0644]
tests/scanner/floats-hexadecimal-invalid1.test [new file with mode: 0644]
tests/scanner/floats-hexadecimal-invalid2.test [new file with mode: 0644]
tests/semantic/realliteral-exponent-has-no-digits4.test [new file with mode: 0644]
tests/semantic/realliteral-exponent-has-no-digits5.test [new file with mode: 0644]
vala/valarealliteral.vala
vala/valascanner.vala

index 844f4c2a78dc187ba7f8175f7872bddce3652e8b..f8ddab9194a8ac69daef0cee9ae83839c359e4e0 100644 (file)
@@ -58,6 +58,7 @@ TESTS = \
        basic-types/integers-octal.vala \
        basic-types/escape-chars.vala \
        basic-types/float-literals.vala \
+       basic-types/floats-hexadecimal.vala \
        basic-types/floats.vala \
        basic-types/floats-boxed-cast.vala \
        basic-types/boolean.vala \
@@ -906,6 +907,8 @@ TESTS = \
        annotations/description.vala \
        annotations/noaccessormethod.test \
        scanner/comment-not-closed.test \
+       scanner/floats-hexadecimal-invalid1.test \
+       scanner/floats-hexadecimal-invalid2.test \
        scanner/preprocessor-invalid.test \
        scanner/preprocessor-missing-paren.test \
        scanner/preprocessor-unexpected.test \
@@ -1271,6 +1274,8 @@ TESTS = \
        semantic/realliteral-exponent-has-no-digits.test \
        semantic/realliteral-exponent-has-no-digits2.test \
        semantic/realliteral-exponent-has-no-digits3.test \
+       semantic/realliteral-exponent-has-no-digits4.test \
+       semantic/realliteral-exponent-has-no-digits5.test \
        semantic/reference-transfer-not-supported.test \
        semantic/reference-transfer-unavailable.test \
        semantic/return-in-nonvoid.test \
diff --git a/tests/basic-types/floats-hexadecimal.c-expected b/tests/basic-types/floats-hexadecimal.c-expected
new file mode 100644 (file)
index 0000000..5e6f5d9
--- /dev/null
@@ -0,0 +1,73 @@
+/* basic_types_floats_hexadecimal.c generated by valac, the Vala compiler
+ * generated from basic_types_floats_hexadecimal.vala, do not modify */
+
+#include <glib.h>
+#include <float.h>
+#include <math.h>
+
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+
+static void
+_vala_main (void)
+{
+       {
+               gfloat foo = 0.0F;
+               gfloat bar = 0.0F;
+               foo = 0x1.fP1F;
+               _vala_assert (foo == 3.875f, "foo == 3.875f");
+               bar = 0xab.cdp2f;
+               _vala_assert (bar == 687.203125f, "bar == 687.203125f");
+       }
+       {
+               gdouble foo = 0.0;
+               gdouble bar = 0.0;
+               gboolean _tmp0_ = FALSE;
+               foo = 0xf.ap3;
+               _vala_assert (foo == 125.0, "foo == 125.0");
+               bar = 0xdead.beefp5;
+               if (bar > 1824183.866699) {
+                       _tmp0_ = bar < 1824183.8666993;
+               } else {
+                       _tmp0_ = FALSE;
+               }
+               _vala_assert (_tmp0_, "bar > 1824183.866699 && bar < 1824183.8666993");
+       }
+       {
+               gdouble foo = 0.0;
+               gboolean _tmp1_ = FALSE;
+               gdouble bar = 0.0;
+               foo = 0x2022.1209p4;
+               if (foo > 131617.127197) {
+                       _tmp1_ = foo < 131617.127198;
+               } else {
+                       _tmp1_ = FALSE;
+               }
+               _vala_assert (_tmp1_, "foo > 131617.127197 && foo < 131617.127198");
+               bar = 0x47.11p9;
+               _vala_assert (bar == 36386.0, "bar == 36386.0");
+       }
+       {
+               gdouble foo = 0.0;
+               foo = 0x0.8P1;
+               _vala_assert (foo == 1.0, "foo == 1.0");
+       }
+       {
+               gdouble foo = 0.0;
+               foo = 0xab.cdp20;
+               _vala_assert (foo == 180146176.0, "foo == 180146176.0");
+       }
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/basic-types/floats-hexadecimal.vala b/tests/basic-types/floats-hexadecimal.vala
new file mode 100644 (file)
index 0000000..f7f4361
--- /dev/null
@@ -0,0 +1,28 @@
+void main () {
+       {
+               float foo = 0x1.fP1F;
+               assert (foo == 3.875f);
+               var bar = 0xab.cdp2f;
+               assert (bar == 687.203125f);
+       }
+       {
+               double foo = 0xf.ap3D;
+               assert (foo == 125.0);
+               var bar = 0xdead.beefp5d;
+               assert (bar > 1824183.866699 && bar < 1824183.8666993);
+       }
+       {
+               double foo = 0x2022.1209p4;
+               assert (foo > 131617.127197 && foo < 131617.127198);
+               var bar = 0x47.11p9;
+               assert (bar == 36386.0);
+       }
+       {
+               double foo = 0x0.8P1;
+               assert (foo == 1.0);
+       }
+       {
+               double foo = 0xab.cdp20;
+               assert (foo == 180146176.0);
+       }
+}
diff --git a/tests/scanner/floats-hexadecimal-invalid1.test b/tests/scanner/floats-hexadecimal-invalid1.test
new file mode 100644 (file)
index 0000000..2cb72b1
--- /dev/null
@@ -0,0 +1,5 @@
+Invalid Code
+
+void main () {
+       double foo = 0xf.f;
+}
diff --git a/tests/scanner/floats-hexadecimal-invalid2.test b/tests/scanner/floats-hexadecimal-invalid2.test
new file mode 100644 (file)
index 0000000..9630202
--- /dev/null
@@ -0,0 +1,5 @@
+Invalid Code
+
+void main () {
+       double foo = 0xf.123d;
+}
diff --git a/tests/semantic/realliteral-exponent-has-no-digits4.test b/tests/semantic/realliteral-exponent-has-no-digits4.test
new file mode 100644 (file)
index 0000000..47590e2
--- /dev/null
@@ -0,0 +1,5 @@
+Invalid Code
+
+void main () {
+       double foo = 0xf.fp;
+}
diff --git a/tests/semantic/realliteral-exponent-has-no-digits5.test b/tests/semantic/realliteral-exponent-has-no-digits5.test
new file mode 100644 (file)
index 0000000..66cc22a
--- /dev/null
@@ -0,0 +1,5 @@
+Invalid Code
+
+void main () {
+       float foo = 0xf.fpf;
+}
index 86e7cf5c11d22a7856359aac2a7b6b27f71d4d9e..07d28dbe8bbfbdbc58297acf10450b1f221585bf 100644 (file)
@@ -65,15 +65,34 @@ public class Vala.RealLiteral : Literal {
                checked = true;
 
                string type_name;
-               if (value.has_suffix ("f") || value.has_suffix ("F")) {
-                       type_name ="float";
-               } else {
+               int suf_len = 0;
+
+               switch (value[value.length - 1]) {
+               case 'f':
+               case 'F':
+                       suf_len = 1;
+                       type_name = "float";
+                       break;
+               case 'd':
+               case 'D':
+                       suf_len = 1;
                        type_name = "double";
+                       break;
+               default:
+                       type_name = "double";
+                       break;
                }
 
-               if (value.has_suffix ("e") || value.has_suffix ("E") || value.has_suffix ("+") || value.has_suffix ("-")) {
+               switch (value[value.length - suf_len - 1]) {
+               case 'e':
+               case 'E':
+               case 'p':
+               case 'P':
+               case '+':
+               case '-':
                        Report.error (source_reference, "exponent has no digits");
                        error = true;
+                       break;
                }
 
                var st = (Struct) context.root.scope.lookup (type_name);
index f6f4cd7bfc705b3978d823e462f6183f868c1660..a198ed72a5aab0f30ce71ac9660ca29281aa7c23 100644 (file)
@@ -611,11 +611,33 @@ public class Vala.Scanner {
                        switch (current[1]) {
                        case 'x':
                        case 'X':
-                               // hexadecimal integer literal
+                               // hexadecimal literal
                                current += 2;
                                while (current < end && current[0].isxdigit ()) {
                                        current++;
                                }
+                               // fractional part
+                               // hexadecimal fractional part
+                               if (current < end - 1 && current[0] == '.' && current[1].isxdigit ()) {
+                                       type = TokenType.REAL_LITERAL;
+                                       current++;
+                                       while (current < end && current[0].isxdigit ()) {
+                                               current++;
+                                       }
+                               }
+                               // hexadecimal exponent part
+                               if (current < end && current[0].tolower () == 'p') {
+                                       type = TokenType.REAL_LITERAL;
+                                       current++;
+                                       if (current < end && (current[0] == '+' || current[0] == '-')) {
+                                               current++;
+                                       }
+                                       while (current < end && current[0].isdigit ()) {
+                                               current++;
+                                       }
+                               } else if (type == TokenType.REAL_LITERAL) {
+                                       Report.error (get_source_reference (1), "hexadecimal floating constants require an exponent");
+                               }
                                break;
                        case 'b':
                        case 'B':