From 54ca3c304d252eda7fe7ee50014ca28a3b68dd19 Mon Sep 17 00:00:00 2001 From: wszqkzqk Date: Fri, 9 Dec 2022 20:07:59 +0800 Subject: vala: Add support for Hexadecimal floating point literals https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html#Hex-Floats --- tests/Makefile.am | 5 ++ tests/basic-types/floats-hexadecimal.c-expected | 73 ++++++++++++++++++++++ tests/basic-types/floats-hexadecimal.vala | 28 +++++++++ tests/scanner/floats-hexadecimal-invalid1.test | 5 ++ tests/scanner/floats-hexadecimal-invalid2.test | 5 ++ .../realliteral-exponent-has-no-digits4.test | 5 ++ .../realliteral-exponent-has-no-digits5.test | 5 ++ vala/valarealliteral.vala | 27 ++++++-- vala/valascanner.vala | 24 ++++++- 9 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 tests/basic-types/floats-hexadecimal.c-expected create mode 100644 tests/basic-types/floats-hexadecimal.vala create mode 100644 tests/scanner/floats-hexadecimal-invalid1.test create mode 100644 tests/scanner/floats-hexadecimal-invalid2.test create mode 100644 tests/semantic/realliteral-exponent-has-no-digits4.test create mode 100644 tests/semantic/realliteral-exponent-has-no-digits5.test diff --git a/tests/Makefile.am b/tests/Makefile.am index 844f4c2a7..f8ddab919 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..5e6f5d96b --- /dev/null +++ b/tests/basic-types/floats-hexadecimal.c-expected @@ -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 +#include +#include + +#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 index 000000000..f7f43611c --- /dev/null +++ b/tests/basic-types/floats-hexadecimal.vala @@ -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 index 000000000..2cb72b126 --- /dev/null +++ b/tests/scanner/floats-hexadecimal-invalid1.test @@ -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 index 000000000..96302020f --- /dev/null +++ b/tests/scanner/floats-hexadecimal-invalid2.test @@ -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 index 000000000..47590e231 --- /dev/null +++ b/tests/semantic/realliteral-exponent-has-no-digits4.test @@ -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 index 000000000..66cc22a8f --- /dev/null +++ b/tests/semantic/realliteral-exponent-has-no-digits5.test @@ -0,0 +1,5 @@ +Invalid Code + +void main () { + float foo = 0xf.fpf; +} diff --git a/vala/valarealliteral.vala b/vala/valarealliteral.vala index 86e7cf5c1..07d28dbe8 100644 --- a/vala/valarealliteral.vala +++ b/vala/valarealliteral.vala @@ -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); diff --git a/vala/valascanner.vala b/vala/valascanner.vala index f6f4cd7bf..a198ed72a 100644 --- a/vala/valascanner.vala +++ b/vala/valascanner.vala @@ -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': -- cgit v1.2.1