summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/prism/node_ext.rb7
-rw-r--r--prism/config.yml4
-rw-r--r--prism/diagnostic.c2
-rw-r--r--prism/diagnostic.h2
-rw-r--r--prism/prism.c92
-rw-r--r--prism/prism.h1
-rw-r--r--prism/templates/ext/prism/api_node.c.erb3
-rw-r--r--prism/templates/include/prism/ast.h.erb1
-rw-r--r--prism/templates/lib/prism/dot_visitor.rb.erb2
-rw-r--r--prism/templates/lib/prism/node.rb.erb2
-rw-r--r--prism/templates/lib/prism/serialize.rb.erb6
-rw-r--r--prism/templates/src/node.c.erb8
-rw-r--r--prism/templates/src/prettyprint.c.erb2
-rw-r--r--prism/templates/src/serialize.c.erb2
-rwxr-xr-xprism/templates/template.rb17
-rw-r--r--prism/util/pm_buffer.c9
-rw-r--r--prism/util/pm_buffer.h8
-rw-r--r--test/prism/snapshots/numbers.txt5
-rw-r--r--test/prism/snapshots/patterns.txt6
-rw-r--r--test/prism/snapshots/seattlerb/float_with_if_modifier.txt1
-rw-r--r--test/prism/snapshots/seattlerb/uminus_float.txt1
-rw-r--r--test/prism/snapshots/symbols.txt1
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/literal.txt12
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/literal.txt6
-rw-r--r--test/prism/snapshots/whitequark/complex.txt2
-rw-r--r--test/prism/snapshots/whitequark/float.txt2
-rw-r--r--test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt2
-rw-r--r--test/prism/snapshots/whitequark/rational.txt1
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873_a.txt12
-rw-r--r--test/prism/snapshots/whitequark/unary_num_pow_precedence.txt2
30 files changed, 199 insertions, 22 deletions
diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb
index a9a0115a09..c0f485f675 100644
--- a/lib/prism/node_ext.rb
+++ b/lib/prism/node_ext.rb
@@ -57,13 +57,6 @@ module Prism
private_constant :HeredocQuery
- class FloatNode < Node
- # Returns the value of the node as a Ruby Float.
- def value
- Float(slice)
- end
- end
-
class ImaginaryNode < Node
# Returns the value of the node as a Ruby Complex.
def value
diff --git a/prism/config.yml b/prism/config.yml
index 33abcc623c..af4bc42fb6 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -1396,6 +1396,10 @@ nodes:
baz if foo .. bar
^^^^^^^^^^
- name: FloatNode
+ fields:
+ - name: value
+ type: double
+ comment: The value of the floating point number as a Float.
comment: |
Represents a floating point number literal.
diff --git a/prism/diagnostic.c b/prism/diagnostic.c
index 601f967116..2040387d80 100644
--- a/prism/diagnostic.c
+++ b/prism/diagnostic.c
@@ -179,6 +179,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
[PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_FATAL },
[PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_FATAL },
[PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_FATAL },
+ [PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_FATAL },
[PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_FATAL },
[PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_FATAL },
[PM_ERR_FOR_IN] = { "expected an `in` after the index in a `for` statement", PM_ERROR_LEVEL_FATAL },
@@ -307,6 +308,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
[PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_LEVEL_VERBOSE },
[PM_WARN_EQUAL_IN_CONDITIONAL] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT },
[PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT },
+ [PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE }
};
static inline const char *
diff --git a/prism/diagnostic.h b/prism/diagnostic.h
index eb60eea8fc..7419c0e791 100644
--- a/prism/diagnostic.h
+++ b/prism/diagnostic.h
@@ -176,6 +176,7 @@ typedef enum {
PM_ERR_EXPECT_STRING_CONTENT,
PM_ERR_EXPECT_WHEN_DELIMITER,
PM_ERR_EXPRESSION_BARE_HASH,
+ PM_ERR_FLOAT_PARSE,
PM_ERR_FOR_COLLECTION,
PM_ERR_FOR_IN,
PM_ERR_FOR_INDEX,
@@ -305,6 +306,7 @@ typedef enum {
PM_WARN_AMBIGUOUS_SLASH,
PM_WARN_EQUAL_IN_CONDITIONAL,
PM_WARN_END_IN_METHOD,
+ PM_WARN_FLOAT_OUT_OF_RANGE,
// This is the number of diagnostic codes.
PM_DIAGNOSTIC_ID_LEN,
diff --git a/prism/prism.c b/prism/prism.c
index e14911167a..4f268fc952 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -3139,6 +3139,70 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) {
}
/**
+ * Parse the value of a double, add appropriate errors if there is an issue, and
+ * return the value that should be saved on the PM_FLOAT_NODE node.
+ */
+static double
+pm_double_parse(pm_parser_t *parser, const pm_token_t *token) {
+ ptrdiff_t diff = token->end - token->start;
+ if (diff <= 0) return 0.0;
+
+ // First, get a buffer of the content.
+ size_t length = (size_t) diff;
+ char *buffer = malloc(sizeof(char) * (length + 1));
+ memcpy((void *) buffer, token->start, length);
+
+ // Next, handle underscores by removing them from the buffer.
+ for (size_t index = 0; index < length; index++) {
+ if (buffer[index] == '_') {
+ memmove((void *) (buffer + index), (void *) (buffer + index + 1), length - index);
+ length--;
+ }
+ }
+
+ // Null-terminate the buffer so that strtod cannot read off the end.
+ buffer[length] = '\0';
+
+ // Now, call strtod to parse the value. Note that CRuby has their own
+ // version of strtod which avoids locales. We're okay using the locale-aware
+ // version because we've already validated through the parser that the token
+ // is in a valid format.
+ errno = 0;
+ char *eptr;
+ double value = strtod(buffer, &eptr);
+
+ // This should never happen, because we've already checked that the token
+ // is in a valid format. However it's good to be safe.
+ if ((eptr != buffer + length) || (errno != 0 && errno != ERANGE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, (*token), PM_ERR_FLOAT_PARSE);
+ free((void *) buffer);
+ return 0.0;
+ }
+
+ // If errno is set, then it should only be ERANGE. At this point we need to
+ // check if it's infinity (it should be).
+ if (errno == ERANGE) {
+ int warn_width;
+ const char *ellipsis;
+
+ if (length > 20) {
+ warn_width = 20;
+ ellipsis = "...";
+ } else {
+ warn_width = (int) length;
+ ellipsis = "";
+ }
+
+ pm_diagnostic_list_append_format(&parser->warning_list, token->start, token->end, PM_WARN_FLOAT_OUT_OF_RANGE, warn_width, (const char *) token->start, ellipsis);
+ value = (value < 0x0) ? -HUGE_VAL : HUGE_VAL;
+ }
+
+ // Finally we can free the buffer and return the value.
+ free((void *) buffer);
+ return value;
+}
+
+/**
* Allocate and initialize a new FloatNode node.
*/
static pm_float_node_t *
@@ -3146,11 +3210,14 @@ pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_FLOAT);
pm_float_node_t *node = PM_ALLOC_NODE(parser, pm_float_node_t);
- *node = (pm_float_node_t) {{
- .type = PM_FLOAT_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_float_node_t) {
+ {
+ .type = PM_FLOAT_NODE,
+ .flags = PM_NODE_FLAG_STATIC_LITERAL,
+ .location = PM_LOCATION_TOKEN_VALUE(token)
+ },
+ .value = pm_double_parse(parser, token)
+ };
return node;
}
@@ -14293,13 +14360,18 @@ parse_pattern(pm_parser_t *parser, bool top_pattern, pm_diagnostic_id_t diag_id)
static inline void
parse_negative_numeric(pm_node_t *node) {
switch (PM_NODE_TYPE(node)) {
- case PM_INTEGER_NODE:
- node->location.start--;
- ((pm_integer_node_t *) node)->value.negative = true;
+ case PM_INTEGER_NODE: {
+ pm_integer_node_t *cast = (pm_integer_node_t *) node;
+ cast->base.location.start--;
+ cast->value.negative = true;
break;
- case PM_FLOAT_NODE:
- node->location.start--;
+ }
+ case PM_FLOAT_NODE: {
+ pm_float_node_t *cast = (pm_float_node_t *) node;
+ cast->base.location.start--;
+ cast->value = -cast->value;
break;
+ }
case PM_RATIONAL_NODE:
node->location.start--;
parse_negative_numeric(((pm_rational_node_t *) node)->numeric);
diff --git a/prism/prism.h b/prism/prism.h
index f26ca0c784..e24dbf5cad 100644
--- a/prism/prism.h
+++ b/prism/prism.h
@@ -25,6 +25,7 @@
#include <assert.h>
#include <errno.h>
+#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb
index c669a4aac9..1e7663ac85 100644
--- a/prism/templates/ext/prism/api_node.c.erb
+++ b/prism/templates/ext/prism/api_node.c.erb
@@ -213,6 +213,9 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
<%- when Prism::IntegerField -%>
#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>);
+ <%- when Prism::DoubleField -%>
+#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+ argv[<%= index %>] = DBL2NUM(cast-><%= field.name %>);
<%- else -%>
<%- raise -%>
<%- end -%>
diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb
index d1c94fe541..ac528a086b 100644
--- a/prism/templates/include/prism/ast.h.erb
+++ b/prism/templates/include/prism/ast.h.erb
@@ -185,6 +185,7 @@ typedef struct pm_<%= node.human %> {
when Prism::UInt8Field then "uint8_t #{field.name}"
when Prism::UInt32Field then "uint32_t #{field.name}"
when Prism::IntegerField then "pm_integer_t #{field.name}"
+ when Prism::DoubleField then "double #{field.name}"
else raise field.class.name
end
%>;
diff --git a/prism/templates/lib/prism/dot_visitor.rb.erb b/prism/templates/lib/prism/dot_visitor.rb.erb
index 7689bc913f..1dc48d265d 100644
--- a/prism/templates/lib/prism/dot_visitor.rb.erb
+++ b/prism/templates/lib/prism/dot_visitor.rb.erb
@@ -133,7 +133,7 @@ module Prism
else
table.field("<%= field.name %>", "[]")
end
- <%- when Prism::StringField, Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::ConstantListField, Prism::IntegerField -%>
+ <%- when Prism::StringField, Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::ConstantListField, Prism::IntegerField, Prism::DoubleField -%>
table.field("<%= field.name %>", node.<%= field.name %>.inspect)
<%- when Prism::LocationField -%>
table.field("<%= field.name %>", location_inspect(node.<%= field.name %>))
diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb
index df8f16a1e8..19fcda936f 100644
--- a/prism/templates/lib/prism/node.rb.erb
+++ b/prism/templates/lib/prism/node.rb.erb
@@ -281,7 +281,7 @@ module Prism
inspector << "<%= pointer %><%= field.name %>:\n"
inspector << <%= field.name %>.inspect(inspector.child_inspector("<%= preadd %>")).delete_prefix(inspector.prefix)
end
- <%- when Prism::ConstantField, Prism::StringField, Prism::UInt8Field, Prism::UInt32Field, Prism::IntegerField -%>
+ <%- when Prism::ConstantField, Prism::StringField, Prism::UInt8Field, Prism::UInt32Field, Prism::IntegerField, Prism::DoubleField -%>
inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
<%- when Prism::OptionalConstantField -%>
if (<%= field.name %> = self.<%= field.name %>).nil?
diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb
index 0214913c19..1356496a5e 100644
--- a/prism/templates/lib/prism/serialize.rb.erb
+++ b/prism/templates/lib/prism/serialize.rb.erb
@@ -183,6 +183,10 @@ module Prism
value
end
+ def load_double
+ io.read(8).unpack1("D")
+ end
+
def load_serialized_length
io.read(4).unpack1("L")
end
@@ -300,6 +304,7 @@ module Prism
when Prism::UInt8Field then "io.getbyte"
when Prism::UInt32Field, Prism::FlagsField then "load_varuint"
when Prism::IntegerField then "load_integer"
+ when Prism::DoubleField then "load_double"
else raise
end
} + ["location"]).join(", ") -%>)
@@ -336,6 +341,7 @@ module Prism
when Prism::UInt8Field then "io.getbyte"
when Prism::UInt32Field, Prism::FlagsField then "load_varuint"
when Prism::IntegerField then "load_integer"
+ when Prism::DoubleField then "load_double"
else raise
end
} + ["location"]).join(", ") -%>)
diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb
index 082d1a3698..89c73451e8 100644
--- a/prism/templates/src/node.c.erb
+++ b/prism/templates/src/node.c.erb
@@ -56,12 +56,12 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) {
<%- nodes.each do |node| -%>
#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
case <%= node.type %>: {
- <%- if node.fields.any? { |field| ![Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField].include?(field.class) } -%>
+ <%- if node.fields.any? { |field| ![Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField, Prism::DoubleField].include?(field.class) } -%>
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
<%- end -%>
<%- node.fields.each do |field| -%>
<%- case field -%>
- <%- when Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField -%>
+ <%- when Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField, Prism::DoubleField -%>
<%- when Prism::NodeField -%>
pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>);
<%- when Prism::OptionalNodeField -%>
@@ -107,7 +107,7 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) {
memsize->memsize += sizeof(*cast);
<%- node.fields.each do |field| -%>
<%- case field -%>
- <%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::LocationField, Prism::OptionalLocationField -%>
+ <%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::LocationField, Prism::OptionalLocationField, Prism::DoubleField -%>
<%- when Prism::NodeField -%>
pm_node_memsize_node((pm_node_t *)cast-><%= field.name %>, memsize);
<%- when Prism::OptionalNodeField -%>
@@ -276,6 +276,8 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no
pm_buffer_append_string(buffer, "]}", 2);
}
}
+ <%- when Prism::DoubleField -%>
+ pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>);
<%- else -%>
<%- raise %>
<%- end -%>
diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb
index dafe3671f1..67a2f444e6 100644
--- a/prism/templates/src/prettyprint.c.erb
+++ b/prism/templates/src/prettyprint.c.erb
@@ -156,6 +156,8 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm
}
pm_buffer_append_string(output_buffer, "]\n", 2);
}
+ <%- when Prism::DoubleField -%>
+ pm_buffer_append_format(output_buffer, " %f\n", cast-><%= field.name %>);
<%- else -%>
<%- raise -%>
<%- end -%>
diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb
index 9e0fe1e4e8..49fd5882ee 100644
--- a/prism/templates/src/serialize.c.erb
+++ b/prism/templates/src/serialize.c.erb
@@ -127,6 +127,8 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
pm_buffer_append_varuint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK));
<%- when Prism::IntegerField -%>
pm_serialize_integer(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer);
+ <%- when Prism::DoubleField -%>
+ pm_buffer_append_double(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>);
<%- else -%>
<%- raise -%>
<%- end -%>
diff --git a/prism/templates/template.rb b/prism/templates/template.rb
index 8e20042bb8..12749add22 100755
--- a/prism/templates/template.rb
+++ b/prism/templates/template.rb
@@ -270,6 +270,22 @@ module Prism
end
end
+ # This represents a double-precision floating point number. When it gets to
+ # Ruby it will be a Float.
+ class DoubleField < Field
+ def rbs_class
+ "Float"
+ end
+
+ def rbi_class
+ "Float"
+ end
+
+ def java_type
+ "double"
+ end
+ end
+
# This class represents a node in the tree, configured by the config.yml file
# in YAML format. It contains information about the name of the node and the
# various child nodes it contains.
@@ -332,6 +348,7 @@ module Prism
when "uint32" then UInt32Field
when "flags" then FlagsField
when "integer" then IntegerField
+ when "double" then DoubleField
else raise("Unknown field type: #{name.inspect}")
end
end
diff --git a/prism/util/pm_buffer.c b/prism/util/pm_buffer.c
index 80a65f02b5..048bc97363 100644
--- a/prism/util/pm_buffer.c
+++ b/prism/util/pm_buffer.c
@@ -164,6 +164,15 @@ pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value) {
}
/**
+ * Append a double to the buffer.
+ */
+void
+pm_buffer_append_double(pm_buffer_t *buffer, double value) {
+ const void *source = &value;
+ pm_buffer_append(buffer, source, sizeof(double));
+}
+
+/**
* Append a slice of source code to the buffer.
*/
void
diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h
index a798dd1d17..d8ec8180e7 100644
--- a/prism/util/pm_buffer.h
+++ b/prism/util/pm_buffer.h
@@ -130,6 +130,14 @@ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value);
void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value);
/**
+ * Append a double to the buffer.
+ *
+ * @param buffer The buffer to append to.
+ * @param value The double to append.
+ */
+void pm_buffer_append_double(pm_buffer_t *buffer, double value);
+
+/**
* The different types of escaping that can be performed by the buffer when
* appending a slice of Ruby source code.
*/
diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt
index abcbf44c5e..740f3f5a2a 100644
--- a/test/prism/snapshots/numbers.txt
+++ b/test/prism/snapshots/numbers.txt
@@ -10,6 +10,7 @@
│ ├── flags: decimal
│ └── value: 1
├── @ FloatNode (location: (5,0)-(5,3))
+ │ └── value: 1.0
├── @ IntegerNode (location: (7,0)-(7,1))
│ ├── flags: decimal
│ └── value: 2
@@ -81,11 +82,13 @@
├── @ RationalNode (location: (47,0)-(47,4))
│ └── numeric:
│ @ FloatNode (location: (47,0)-(47,3))
+ │ └── value: 1.2
├── @ ImaginaryNode (location: (49,0)-(49,5))
│ └── numeric:
│ @ RationalNode (location: (49,0)-(49,4))
│ └── numeric:
│ @ FloatNode (location: (49,0)-(49,3))
+ │ └── value: 1.2
├── @ ImaginaryNode (location: (51,0)-(51,4))
│ └── numeric:
│ @ RationalNode (location: (51,0)-(51,3))
@@ -96,11 +99,13 @@
├── @ RationalNode (location: (53,0)-(53,5))
│ └── numeric:
│ @ FloatNode (location: (53,0)-(53,4))
+ │ └── value: -1.2
├── @ ImaginaryNode (location: (55,0)-(55,6))
│ └── numeric:
│ @ RationalNode (location: (55,0)-(55,5))
│ └── numeric:
│ @ FloatNode (location: (55,0)-(55,4))
+ │ └── value: -1.2
├── @ RationalNode (location: (57,0)-(57,4))
│ └── numeric:
│ @ IntegerNode (location: (57,0)-(57,3))
diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt
index 7080749a9e..96205349d3 100644
--- a/test/prism/snapshots/patterns.txt
+++ b/test/prism/snapshots/patterns.txt
@@ -51,6 +51,7 @@
│ │ └── block: ∅
│ ├── pattern:
│ │ @ FloatNode (location: (3,7)-(3,10))
+ │ │ └── value: 1.0
│ └── operator_loc: (3,4)-(3,6) = "=>"
├── @ MatchRequiredNode (location: (4,0)-(4,9))
│ ├── value:
@@ -544,8 +545,10 @@
│ │ ├── flags: ∅
│ │ ├── left:
│ │ │ @ FloatNode (location: (29,7)-(29,10))
+ │ │ │ └── value: 1.0
│ │ ├── right:
│ │ │ @ FloatNode (location: (29,14)-(29,17))
+ │ │ │ └── value: 1.0
│ │ └── operator_loc: (29,11)-(29,13) = ".."
│ └── operator_loc: (29,4)-(29,6) = "=>"
├── @ MatchRequiredNode (location: (30,0)-(30,15))
@@ -2426,6 +2429,7 @@
│ │ └── block: ∅
│ ├── pattern:
│ │ @ FloatNode (location: (106,7)-(106,10))
+ │ │ └── value: 1.0
│ └── operator_loc: (106,4)-(106,6) = "in"
├── @ MatchPredicateNode (location: (107,0)-(107,9))
│ ├── value:
@@ -2966,6 +2970,7 @@
│ │ └── @ InNode (location: (137,10)-(137,21))
│ │ ├── pattern:
│ │ │ @ FloatNode (location: (137,13)-(137,16))
+ │ │ │ └── value: 1.0
│ │ ├── statements: ∅
│ │ ├── in_loc: (137,10)-(137,12) = "in"
│ │ └── then_loc: (137,17)-(137,21) = "then"
@@ -3681,6 +3686,7 @@
│ │ │ │ @ StatementsNode (location: (164,13)-(164,16))
│ │ │ │ └── body: (length: 1)
│ │ │ │ └── @ FloatNode (location: (164,13)-(164,16))
+ │ │ │ │ └── value: 1.0
│ │ │ ├── consequent: ∅
│ │ │ └── end_keyword_loc: ∅
│ │ ├── statements: ∅
diff --git a/test/prism/snapshots/seattlerb/float_with_if_modifier.txt b/test/prism/snapshots/seattlerb/float_with_if_modifier.txt
index 5cf12848c4..9c1da70f24 100644
--- a/test/prism/snapshots/seattlerb/float_with_if_modifier.txt
+++ b/test/prism/snapshots/seattlerb/float_with_if_modifier.txt
@@ -12,5 +12,6 @@
│ @ StatementsNode (location: (1,0)-(1,3))
│ └── body: (length: 1)
│ └── @ FloatNode (location: (1,0)-(1,3))
+ │ └── value: 1.0
├── consequent: ∅
└── end_keyword_loc: ∅
diff --git a/test/prism/snapshots/seattlerb/uminus_float.txt b/test/prism/snapshots/seattlerb/uminus_float.txt
index b509e2f7f3..0578dbbd68 100644
--- a/test/prism/snapshots/seattlerb/uminus_float.txt
+++ b/test/prism/snapshots/seattlerb/uminus_float.txt
@@ -4,3 +4,4 @@
@ StatementsNode (location: (1,0)-(1,4))
└── body: (length: 1)
└── @ FloatNode (location: (1,0)-(1,4))
+ └── value: -0.0
diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt
index 4fbb277c6e..c34be74b37 100644
--- a/test/prism/snapshots/symbols.txt
+++ b/test/prism/snapshots/symbols.txt
@@ -144,6 +144,7 @@
│ │ │ ├── flags: decimal
│ │ │ └── value: 1
│ │ ├── @ FloatNode (location: (29,4)-(29,7))
+ │ │ │ └── value: 1.0
│ │ ├── @ RationalNode (location: (29,9)-(29,11))
│ │ │ └── numeric:
│ │ │ @ IntegerNode (location: (29,9)-(29,10))
diff --git a/test/prism/snapshots/unparser/corpus/literal/literal.txt b/test/prism/snapshots/unparser/corpus/literal/literal.txt
index 6a3d817a6e..8ed1bf5fe9 100644
--- a/test/prism/snapshots/unparser/corpus/literal/literal.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/literal.txt
@@ -319,9 +319,11 @@
├── @ RationalNode (location: (20,0)-(20,4))
│ └── numeric:
│ @ FloatNode (location: (20,0)-(20,3))
+ │ └── value: 1.5
├── @ RationalNode (location: (21,0)-(21,4))
│ └── numeric:
│ @ FloatNode (location: (21,0)-(21,3))
+ │ └── value: 1.3
├── @ ImaginaryNode (location: (22,0)-(22,2))
│ └── numeric:
│ @ IntegerNode (location: (22,0)-(22,1))
@@ -335,9 +337,11 @@
├── @ ImaginaryNode (location: (24,0)-(24,4))
│ └── numeric:
│ @ FloatNode (location: (24,0)-(24,3))
+ │ └── value: 0.6
├── @ ImaginaryNode (location: (25,0)-(25,5))
│ └── numeric:
│ @ FloatNode (location: (25,0)-(25,4))
+ │ └── value: -0.6
├── @ ImaginaryNode (location: (26,0)-(26,32))
│ └── numeric:
│ @ IntegerNode (location: (26,0)-(26,31))
@@ -711,6 +715,7 @@
│ │ │ ├── flags: ∅
│ │ │ ├── receiver:
│ │ │ │ @ FloatNode (location: (60,1)-(60,4))
+ │ │ │ │ └── value: 0.0
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── name: :/
│ │ │ ├── message_loc: (60,5)-(60,6) = "/"
@@ -720,6 +725,7 @@
│ │ │ │ ├── flags: ∅
│ │ │ │ └── arguments: (length: 1)
│ │ │ │ └── @ FloatNode (location: (60,7)-(60,10))
+ │ │ │ │ └── value: 0.0
│ │ │ ├── closing_loc: ∅
│ │ │ └── block: ∅
│ │ ├── opening_loc: (60,0)-(60,1) = "("
@@ -744,6 +750,7 @@
│ │ │ ├── flags: ∅
│ │ │ ├── receiver:
│ │ │ │ @ FloatNode (location: (61,4)-(61,7))
+ │ │ │ │ └── value: 0.0
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── name: :/
│ │ │ ├── message_loc: (61,8)-(61,9) = "/"
@@ -753,6 +760,7 @@
│ │ │ │ ├── flags: ∅
│ │ │ │ └── arguments: (length: 1)
│ │ │ │ └── @ FloatNode (location: (61,10)-(61,13))
+ │ │ │ │ └── value: 0.0
│ │ │ ├── closing_loc: ∅
│ │ │ └── block: ∅
│ │ ├── opening_loc: (61,3)-(61,4) = "("
@@ -769,6 +777,7 @@
│ │ │ ├── flags: ∅
│ │ │ ├── receiver:
│ │ │ │ @ FloatNode (location: (62,1)-(62,4))
+ │ │ │ │ └── value: 0.0
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── name: :/
│ │ │ ├── message_loc: (62,5)-(62,6) = "/"
@@ -778,6 +787,7 @@
│ │ │ │ ├── flags: ∅
│ │ │ │ └── arguments: (length: 1)
│ │ │ │ └── @ FloatNode (location: (62,7)-(62,10))
+ │ │ │ │ └── value: 0.0
│ │ │ ├── closing_loc: ∅
│ │ │ └── block: ∅
│ │ ├── opening_loc: (62,0)-(62,1) = "("
@@ -788,7 +798,9 @@
│ │ └── value: 100
│ └── operator_loc: (62,11)-(62,13) = ".."
├── @ FloatNode (location: (63,0)-(63,4))
+ │ └── value: -0.1
├── @ FloatNode (location: (64,0)-(64,3))
+ │ └── value: 0.1
├── @ ArrayNode (location: (65,0)-(65,6))
│ ├── flags: ∅
│ ├── elements: (length: 2)
diff --git a/test/prism/snapshots/unparser/corpus/semantic/literal.txt b/test/prism/snapshots/unparser/corpus/semantic/literal.txt
index 915254d372..7f76e2f561 100644
--- a/test/prism/snapshots/unparser/corpus/semantic/literal.txt
+++ b/test/prism/snapshots/unparser/corpus/semantic/literal.txt
@@ -6,6 +6,7 @@
├── @ RationalNode (location: (1,0)-(1,4))
│ └── numeric:
│ @ FloatNode (location: (1,0)-(1,3))
+ │ └── value: 1.0
├── @ RationalNode (location: (2,0)-(2,3))
│ └── numeric:
│ @ IntegerNode (location: (2,0)-(2,2))
@@ -18,8 +19,11 @@
│ ├── flags: decimal
│ └── value: 1000
├── @ FloatNode (location: (5,0)-(5,4))
+ │ └── value: 10000000000.0
├── @ FloatNode (location: (6,0)-(6,14))
+ │ └── value: Infinity
├── @ FloatNode (location: (7,0)-(7,15))
+ │ └── value: -Infinity
├── @ StringNode (location: (8,0)-(8,2))
│ ├── flags: ∅
│ ├── opening_loc: (8,0)-(8,1) = "?"
@@ -58,7 +62,9 @@
│ │ └── unescaped: "baz"
│ └── closing_loc: (11,13)-(11,14) = ")"
├── @ FloatNode (location: (12,0)-(12,16))
+ │ └── value: Infinity
├── @ FloatNode (location: (13,0)-(13,17))
+ │ └── value: -Infinity
└── @ CallNode (location: (14,0)-(14,10))
├── flags: ignore_visibility
├── receiver: ∅
diff --git a/test/prism/snapshots/whitequark/complex.txt b/test/prism/snapshots/whitequark/complex.txt
index 80e7c00fb9..e688585a5f 100644
--- a/test/prism/snapshots/whitequark/complex.txt
+++ b/test/prism/snapshots/whitequark/complex.txt
@@ -6,11 +6,13 @@
├── @ ImaginaryNode (location: (1,0)-(1,5))
│ └── numeric:
│ @ FloatNode (location: (1,0)-(1,4))
+ │ └── value: 42.1
├── @ ImaginaryNode (location: (3,0)-(3,6))
│ └── numeric:
│ @ RationalNode (location: (3,0)-(3,5))
│ └── numeric:
│ @ FloatNode (location: (3,0)-(3,4))
+ │ └── value: 42.1
├── @ ImaginaryNode (location: (5,0)-(5,3))
│ └── numeric:
│ @ IntegerNode (location: (5,0)-(5,2))
diff --git a/test/prism/snapshots/whitequark/float.txt b/test/prism/snapshots/whitequark/float.txt
index 14457fcff2..5e6a597db7 100644
--- a/test/prism/snapshots/whitequark/float.txt
+++ b/test/prism/snapshots/whitequark/float.txt
@@ -4,4 +4,6 @@
@ StatementsNode (location: (1,0)-(3,4))
└── body: (length: 2)
├── @ FloatNode (location: (1,0)-(1,5))
+ │ └── value: -1.33
└── @ FloatNode (location: (3,0)-(3,4))
+ └── value: 1.33
diff --git a/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt b/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt
index e5b953b9fd..afddc9cd3c 100644
--- a/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt
+++ b/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt
@@ -22,6 +22,7 @@
│ │ │ │ @ StatementsNode (location: (1,5)-(1,9))
│ │ │ │ └── body: (length: 1)
│ │ │ │ └── @ FloatNode (location: (1,5)-(1,9))
+ │ │ │ │ └── value: -1.3
│ │ │ ├── opening_loc: (1,4)-(1,5) = "("
│ │ │ └── closing_loc: (1,9)-(1,10) = ")"
│ │ ├── call_operator_loc: (1,10)-(1,11) = "."
@@ -52,6 +53,7 @@
│ │ │ @ StatementsNode (location: (3,6)-(3,10))
│ │ │ └── body: (length: 1)
│ │ │ └── @ FloatNode (location: (3,6)-(3,10))
+ │ │ │ └── value: -1.3
│ │ ├── opening_loc: (3,5)-(3,6) = "("
│ │ └── closing_loc: (3,10)-(3,11) = ")"
│ ├── call_operator_loc: (3,11)-(3,12) = "."
diff --git a/test/prism/snapshots/whitequark/rational.txt b/test/prism/snapshots/whitequark/rational.txt
index 8b2cc17efd..90bbd17929 100644
--- a/test/prism/snapshots/whitequark/rational.txt
+++ b/test/prism/snapshots/whitequark/rational.txt
@@ -6,6 +6,7 @@
├── @ RationalNode (location: (1,0)-(1,5))
│ └── numeric:
│ @ FloatNode (location: (1,0)-(1,4))
+ │ └── value: 42.1
└── @ RationalNode (location: (3,0)-(3,3))
└── numeric:
@ IntegerNode (location: (3,0)-(3,2))
diff --git a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt
index 320958c9d4..93418e6448 100644
--- a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt
+++ b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt
@@ -109,6 +109,7 @@
│ │ │ ├── closing_loc: (3,7)-(3,8) = ")"
│ │ │ └── block: ∅
│ │ └── @ FloatNode (location: (3,10)-(3,13))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (3,14)-(3,20))
@@ -167,6 +168,7 @@
│ │ └── @ ImaginaryNode (location: (5,10)-(5,14))
│ │ └── numeric:
│ │ @ FloatNode (location: (5,10)-(5,13))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (5,15)-(5,21))
@@ -225,6 +227,7 @@
│ │ └── @ RationalNode (location: (7,10)-(7,14))
│ │ └── numeric:
│ │ @ FloatNode (location: (7,10)-(7,13))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (7,15)-(7,21))
@@ -400,6 +403,7 @@
│ │ │ ├── closing_loc: (13,8)-(13,9) = ")"
│ │ │ └── block: ∅
│ │ └── @ FloatNode (location: (13,11)-(13,14))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (13,15)-(13,21))
@@ -458,6 +462,7 @@
│ │ └── @ ImaginaryNode (location: (15,11)-(15,15))
│ │ └── numeric:
│ │ @ FloatNode (location: (15,11)-(15,14))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (15,16)-(15,22))
@@ -516,6 +521,7 @@
│ │ └── @ RationalNode (location: (17,11)-(17,15))
│ │ └── numeric:
│ │ @ FloatNode (location: (17,11)-(17,14))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (17,16)-(17,22))
@@ -701,6 +707,7 @@
│ │ │ ├── opening_loc: (23,3)-(23,4) = "{"
│ │ │ └── closing_loc: (23,7)-(23,8) = "}"
│ │ └── @ FloatNode (location: (23,10)-(23,13))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (23,14)-(23,20))
@@ -764,6 +771,7 @@
│ │ └── @ ImaginaryNode (location: (25,10)-(25,14))
│ │ └── numeric:
│ │ @ FloatNode (location: (25,10)-(25,13))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (25,15)-(25,21))
@@ -827,6 +835,7 @@
│ │ └── @ RationalNode (location: (27,10)-(27,14))
│ │ └── numeric:
│ │ @ FloatNode (location: (27,10)-(27,13))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (27,15)-(27,21))
@@ -1017,6 +1026,7 @@
│ │ │ ├── opening_loc: (33,3)-(33,4) = "{"
│ │ │ └── closing_loc: (33,8)-(33,9) = "}"
│ │ └── @ FloatNode (location: (33,11)-(33,14))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (33,15)-(33,21))
@@ -1080,6 +1090,7 @@
│ │ └── @ ImaginaryNode (location: (35,11)-(35,15))
│ │ └── numeric:
│ │ @ FloatNode (location: (35,11)-(35,14))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (35,16)-(35,22))
@@ -1143,6 +1154,7 @@
│ │ └── @ RationalNode (location: (37,11)-(37,15))
│ │ └── numeric:
│ │ @ FloatNode (location: (37,11)-(37,14))
+ │ │ └── value: 1.0
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (37,16)-(37,22))
diff --git a/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt b/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt
index 75be379e2e..e14b0567e7 100644
--- a/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt
+++ b/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt
@@ -7,6 +7,7 @@
│ ├── flags: ∅
│ ├── receiver:
│ │ @ FloatNode (location: (1,0)-(1,4))
+ │ │ └── value: 2.0
│ ├── call_operator_loc: ∅
│ ├── name: :**
│ ├── message_loc: (1,5)-(1,7) = "**"
@@ -56,6 +57,7 @@
│ ├── flags: ∅
│ ├── receiver:
│ │ @ FloatNode (location: (5,1)-(5,4))
+ │ │ └── value: 2.0
│ ├── call_operator_loc: ∅
│ ├── name: :**
│ ├── message_loc: (5,5)-(5,7) = "**"