Skip to content

Commit 530fbad

Browse files
committed
1 parent 9c20b52 commit 530fbad

File tree

15 files changed

+785
-272
lines changed

15 files changed

+785
-272
lines changed

src/main/c/yarp/include/prism.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "prism/defines.h"
1010
#include "prism/util/pm_buffer.h"
1111
#include "prism/util/pm_char.h"
12+
#include "prism/util/pm_integer.h"
1213
#include "prism/util/pm_memchr.h"
1314
#include "prism/util/pm_strncasecmp.h"
1415
#include "prism/util/pm_strpbrk.h"
@@ -24,6 +25,7 @@
2425

2526
#include <assert.h>
2627
#include <errno.h>
28+
#include <math.h>
2729
#include <stdarg.h>
2830
#include <stdbool.h>
2931
#include <stdint.h>

src/main/c/yarp/include/prism/ast.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "prism/defines.h"
1717
#include "prism/util/pm_constant_pool.h"
18+
#include "prism/util/pm_integer.h"
1819
#include "prism/util/pm_string.h"
1920

2021
#include <assert.h>
@@ -2841,6 +2842,13 @@ typedef struct pm_flip_flop_node {
28412842
typedef struct pm_float_node {
28422843
/** The embedded base node. */
28432844
pm_node_t base;
2845+
2846+
/**
2847+
* FloatNode#value
2848+
*
2849+
* The value of the floating point number as a Float.
2850+
*/
2851+
double value;
28442852
} pm_float_node_t;
28452853

28462854
/**
@@ -3712,6 +3720,13 @@ typedef struct pm_instance_variable_write_node {
37123720
typedef struct pm_integer_node {
37133721
/** The embedded base node. */
37143722
pm_node_t base;
3723+
3724+
/**
3725+
* IntegerNode#value
3726+
*
3727+
* The value of the integer literal as a number.
3728+
*/
3729+
pm_integer_t value;
37153730
} pm_integer_node_t;
37163731

37173732
/**

src/main/c/yarp/include/prism/defines.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define PRISM_DEFINES_H
1111

1212
#include <ctype.h>
13+
#include <math.h>
1314
#include <stdarg.h>
1415
#include <stddef.h>
1516
#include <stdint.h>
@@ -113,4 +114,15 @@
113114
# endif
114115
#endif
115116

117+
/**
118+
* isinf on Windows is defined as accepting a float, but on POSIX systems it
119+
* accepts a float, a double, or a long double. We want to mirror this behavior
120+
* on windows.
121+
*/
122+
#ifdef _WIN32
123+
# include <float.h>
124+
# undef isinf
125+
# define isinf(x) (sizeof(x) == sizeof(float) ? !_finitef(x) : !_finite(x))
126+
#endif
127+
116128
#endif

src/main/c/yarp/include/prism/diagnostic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ typedef enum {
176176
PM_ERR_EXPECT_STRING_CONTENT,
177177
PM_ERR_EXPECT_WHEN_DELIMITER,
178178
PM_ERR_EXPRESSION_BARE_HASH,
179+
PM_ERR_FLOAT_PARSE,
179180
PM_ERR_FOR_COLLECTION,
180181
PM_ERR_FOR_IN,
181182
PM_ERR_FOR_INDEX,
@@ -305,6 +306,7 @@ typedef enum {
305306
PM_WARN_AMBIGUOUS_SLASH,
306307
PM_WARN_EQUAL_IN_CONDITIONAL,
307308
PM_WARN_END_IN_METHOD,
309+
PM_WARN_FLOAT_OUT_OF_RANGE,
308310

309311
// This is the number of diagnostic codes.
310312
PM_DIAGNOSTIC_ID_LEN,

src/main/c/yarp/include/prism/util/pm_buffer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value);
129129
*/
130130
void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value);
131131

132+
/**
133+
* Append a double to the buffer.
134+
*
135+
* @param buffer The buffer to append to.
136+
* @param value The double to append.
137+
*/
138+
void pm_buffer_append_double(pm_buffer_t *buffer, double value);
139+
132140
/**
133141
* The different types of escaping that can be performed by the buffer when
134142
* appending a slice of Ruby source code.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* @file pm_integer.h
3+
*
4+
* This module provides functions for working with arbitrary-sized integers.
5+
*/
6+
#ifndef PRISM_NUMBER_H
7+
#define PRISM_NUMBER_H
8+
9+
#include "prism/defines.h"
10+
11+
#include <assert.h>
12+
#include <stdbool.h>
13+
#include <stdint.h>
14+
#include <stdlib.h>
15+
16+
/**
17+
* A node in the linked list of a pm_integer_t.
18+
*/
19+
typedef struct pm_integer_word {
20+
/** A pointer to the next node in the list. */
21+
struct pm_integer_word *next;
22+
23+
/** The value of the node. */
24+
uint32_t value;
25+
} pm_integer_word_t;
26+
27+
/**
28+
* This structure represents an arbitrary-sized integer. It is implemented as a
29+
* linked list of 32-bit integers, with the least significant digit at the head
30+
* of the list.
31+
*/
32+
typedef struct {
33+
/** The number of nodes in the linked list that have been allocated. */
34+
size_t length;
35+
36+
/**
37+
* The head of the linked list, embedded directly so that allocations do not
38+
* need to be performed for small integers.
39+
*/
40+
pm_integer_word_t head;
41+
42+
/**
43+
* Whether or not the integer is negative. It is stored this way so that a
44+
* zeroed pm_integer_t is always positive zero.
45+
*/
46+
bool negative;
47+
} pm_integer_t;
48+
49+
/**
50+
* An enum controlling the base of an integer. It is expected that the base is
51+
* already known before parsing the integer, even though it could be derived
52+
* from the string itself.
53+
*/
54+
typedef enum {
55+
/** The binary base, indicated by a 0b or 0B prefix. */
56+
PM_INTEGER_BASE_BINARY,
57+
58+
/** The octal base, indicated by a 0, 0o, or 0O prefix. */
59+
PM_INTEGER_BASE_OCTAL,
60+
61+
/** The decimal base, indicated by a 0d, 0D, or empty prefix. */
62+
PM_INTEGER_BASE_DECIMAL,
63+
64+
/** The hexidecimal base, indicated by a 0x or 0X prefix. */
65+
PM_INTEGER_BASE_HEXADECIMAL,
66+
67+
/**
68+
* An unknown base, in which case pm_integer_parse will derive it based on
69+
* the content of the string. This is less efficient and does more
70+
* comparisons, so if callers know the base ahead of time, they should use
71+
* that instead.
72+
*/
73+
PM_INTEGER_BASE_UNKNOWN
74+
} pm_integer_base_t;
75+
76+
/**
77+
* Parse an integer from a string. This assumes that the format of the integer
78+
* has already been validated, as internal validation checks are not performed
79+
* here.
80+
*
81+
* @param integer The integer to parse into.
82+
* @param base The base of the integer.
83+
* @param start The start of the string.
84+
* @param end The end of the string.
85+
*/
86+
PRISM_EXPORTED_FUNCTION void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end);
87+
88+
/**
89+
* Return the memory size of the integer.
90+
*
91+
* @param integer The integer to get the memory size of.
92+
* @return The size of the memory associated with the integer.
93+
*/
94+
size_t pm_integer_memsize(const pm_integer_t *integer);
95+
96+
/**
97+
* Free the internal memory of an integer. This memory will only be allocated if
98+
* the integer exceeds the size of a single node in the linked list.
99+
*
100+
* @param integer The integer to free.
101+
*/
102+
PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer);
103+
104+
#endif

src/main/c/yarp/src/diagnostic.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
179179
[PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_FATAL },
180180
[PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_FATAL },
181181
[PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_FATAL },
182+
[PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_FATAL },
182183
[PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_FATAL },
183184
[PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_FATAL },
184185
[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] = {
307308
[PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_LEVEL_VERBOSE },
308309
[PM_WARN_EQUAL_IN_CONDITIONAL] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT },
309310
[PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT },
311+
[PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE }
310312
};
311313

312314
static inline const char *

0 commit comments

Comments
 (0)