Skip to content

Commit dadeb7e

Browse files
committed
Use an arena for parser metadata
1 parent db57f23 commit dadeb7e

9 files changed

Lines changed: 77 additions & 174 deletions

File tree

include/prism/parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,9 @@ struct pm_parser {
639639
/** The arena used for all AST-lifetime allocations. Caller-owned. */
640640
pm_arena_t *arena;
641641

642+
/** The arena used for parser metadata (comments, diagnostics, etc.). */
643+
pm_arena_t metadata_arena;
644+
642645
/**
643646
* The next node identifier that will be assigned. This is a unique
644647
* identifier used to track nodes such that the syntax tree can be dropped

include/prism/util/pm_char.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length);
3636
* @return The number of characters at the start of the string that are
3737
* whitespace.
3838
*/
39-
size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset);
39+
size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_t *arena, pm_line_offset_list_t *line_offsets, uint32_t start_offset);
4040

4141
/**
4242
* Returns the number of characters at the start of the string that are inline

include/prism/util/pm_line_offset_list.h

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define PRISM_LINE_OFFSET_LIST_H
1616

1717
#include "prism/defines.h"
18+
#include "prism/util/pm_arena.h"
1819

1920
#include <assert.h>
2021
#include <stdbool.h>
@@ -48,14 +49,13 @@ typedef struct {
4849
} pm_line_column_t;
4950

5051
/**
51-
* Initialize a new line offset list with the given capacity. Returns true if
52-
* the allocation of the offsets succeeds, otherwise returns false.
52+
* Initialize a new line offset list with the given capacity.
5353
*
54+
* @param arena The arena to allocate from.
5455
* @param list The list to initialize.
5556
* @param capacity The initial capacity of the list.
56-
* @return True if the allocation of the offsets succeeds, otherwise false.
5757
*/
58-
bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity);
58+
void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity);
5959

6060
/**
6161
* Clear out the offsets that have been appended to the list.
@@ -65,15 +65,13 @@ bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity);
6565
void pm_line_offset_list_clear(pm_line_offset_list_t *list);
6666

6767
/**
68-
* Append a new offset to the list. Returns true if the reallocation of the
69-
* offsets succeeds (if one was necessary), otherwise returns false.
68+
* Append a new offset to the list.
7069
*
70+
* @param arena The arena to allocate from.
7171
* @param list The list to append to.
7272
* @param cursor The offset to append.
73-
* @return True if the reallocation of the offsets succeeds (if one was
74-
* necessary), otherwise false.
7573
*/
76-
bool pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor);
74+
void pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor);
7775

7876
/**
7977
* Returns the line of the given offset. If the offset is not in the list, the
@@ -98,11 +96,4 @@ int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cur
9896
*/
9997
PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line);
10098

101-
/**
102-
* Free the internal memory allocated for the list.
103-
*
104-
* @param list The list to free.
105-
*/
106-
void pm_line_offset_list_free(pm_line_offset_list_t *list);
107-
10899
#endif

src/prism.c

Lines changed: 35 additions & 70 deletions
Large diffs are not rendered by default.

src/util/pm_char.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length) {
8383
* searching past the given maximum number of characters.
8484
*/
8585
size_t
86-
pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset) {
86+
pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_t *arena, pm_line_offset_list_t *line_offsets, uint32_t start_offset) {
8787
if (length <= 0) return 0;
8888

8989
uint32_t size = 0;
9090
uint32_t maximum = (uint32_t) length;
9191

9292
while (size < maximum && (pm_byte_table[string[size]] & PRISM_CHAR_BIT_WHITESPACE)) {
9393
if (string[size] == '\n') {
94-
pm_line_offset_list_append(line_offsets, start_offset + size + 1);
94+
pm_line_offset_list_append(arena, line_offsets, start_offset + size + 1);
9595
}
9696

9797
size++;

src/util/pm_line_offset_list.c

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
#include "prism/util/pm_line_offset_list.h"
22

33
/**
4-
* Initialize a new newline list with the given capacity. Returns true if the
5-
* allocation of the offsets succeeds, otherwise returns false.
4+
* Initialize a new line offset list with the given capacity.
65
*/
7-
bool
8-
pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity) {
9-
list->offsets = (uint32_t *) xcalloc(capacity, sizeof(uint32_t));
10-
if (list->offsets == NULL) return false;
6+
void
7+
pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity) {
8+
list->offsets = (uint32_t *) pm_arena_zalloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
119

1210
// This is 1 instead of 0 because we want to include the first line of the
13-
// file as having offset 0, which is set because of calloc.
11+
// file as having offset 0, which is set because of the zero-initialization.
1412
list->size = 1;
1513
list->capacity = capacity;
16-
17-
return true;
1814
}
1915

2016
/**
@@ -26,26 +22,22 @@ pm_line_offset_list_clear(pm_line_offset_list_t *list) {
2622
}
2723

2824
/**
29-
* Append a new offset to the newline list. Returns true if the reallocation of
30-
* the offsets succeeds (if one was necessary), otherwise returns false.
25+
* Append a new offset to the newline list.
3126
*/
32-
bool
33-
pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor) {
27+
void
28+
pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) {
3429
if (list->size == list->capacity) {
35-
uint32_t *original_offsets = list->offsets;
30+
size_t new_capacity = (list->capacity * 3) / 2;
31+
uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
3632

37-
list->capacity = (list->capacity * 3) / 2;
38-
list->offsets = (uint32_t *) xcalloc(list->capacity, sizeof(uint32_t));
39-
if (list->offsets == NULL) return false;
33+
memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t));
4034

41-
memcpy(list->offsets, original_offsets, list->size * sizeof(uint32_t));
42-
xfree_sized(original_offsets, list->size * sizeof(uint32_t));
35+
list->offsets = new_offsets;
36+
list->capacity = new_capacity;
4337
}
4438

4539
assert(list->size == 0 || cursor > list->offsets[list->size - 1]);
4640
list->offsets[list->size++] = cursor;
47-
48-
return true;
4941
}
5042

5143
/**
@@ -103,11 +95,3 @@ pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t curs
10395
.column = cursor - list->offsets[left - 1]
10496
});
10597
}
106-
107-
/**
108-
* Free the internal memory allocated for the newline list.
109-
*/
110-
void
111-
pm_line_offset_list_free(pm_line_offset_list_t *list) {
112-
xfree_sized(list->offsets, list->capacity * sizeof(uint32_t));
113-
}

src/util/pm_strpbrk.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
static inline void
77
pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, uint32_t start, uint32_t length) {
8-
pm_diagnostic_list_append_format(&parser->error_list, start, length, PM_ERR_INVALID_MULTIBYTE_CHARACTER, parser->start[start]);
8+
pm_diagnostic_list_append_format(&parser->metadata_arena, &parser->error_list, start, length, PM_ERR_INVALID_MULTIBYTE_CHARACTER, parser->start[start]);
99
}
1010

1111
/**
@@ -19,7 +19,7 @@ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t l
1919
} else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) {
2020
// Not okay, we already found a Unicode escape sequence and this
2121
// conflicts.
22-
pm_diagnostic_list_append_format(&parser->error_list, start, length, PM_ERR_MIXED_ENCODING, parser->encoding->name);
22+
pm_diagnostic_list_append_format(&parser->metadata_arena, &parser->error_list, start, length, PM_ERR_MIXED_ENCODING, parser->encoding->name);
2323
} else {
2424
// Should not be anything else.
2525
assert(false && "unreachable");

templates/include/prism/diagnostic.h.erb

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "prism/ast.h"
1010
#include "prism/defines.h"
11+
#include "prism/util/pm_arena.h"
1112
#include "prism/util/pm_list.h"
1213

1314
#include <stdbool.h>
@@ -48,13 +49,6 @@ typedef struct {
4849
/** The message associated with the diagnostic. */
4950
const char *message;
5051

51-
/**
52-
* Whether or not the memory related to the message of this diagnostic is
53-
* owned by this diagnostic. If it is, it needs to be freed when the
54-
* diagnostic is freed.
55-
*/
56-
bool owned;
57-
5852
/**
5953
* The level of the diagnostic, see `pm_error_level_t` and
6054
* `pm_warning_level_t` for possible values.
@@ -99,32 +93,25 @@ const char * pm_diagnostic_id_human(pm_diagnostic_id_t diag_id);
9993
* Append a diagnostic to the given list of diagnostics that is using shared
10094
* memory for its message.
10195
*
96+
* @param arena The arena to allocate from.
10297
* @param list The list to append to.
10398
* @param start The source offset of the start of the diagnostic.
10499
* @param length The length of the diagnostic.
105100
* @param diag_id The diagnostic ID.
106-
* @return Whether the diagnostic was successfully appended.
107101
*/
108-
bool pm_diagnostic_list_append(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id);
102+
void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id);
109103

110104
/**
111105
* Append a diagnostic to the given list of diagnostics that is using a format
112106
* string for its message.
113107
*
108+
* @param arena The arena to allocate from.
114109
* @param list The list to append to.
115110
* @param start The source offset of the start of the diagnostic.
116111
* @param length The length of the diagnostic.
117112
* @param diag_id The diagnostic ID.
118113
* @param ... The arguments to the format string for the message.
119-
* @return Whether the diagnostic was successfully appended.
120-
*/
121-
bool pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...);
122-
123-
/**
124-
* Deallocate the internal state of the given diagnostic list.
125-
*
126-
* @param list The list to deallocate.
127114
*/
128-
void pm_diagnostic_list_free(pm_list_t *list);
115+
void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...);
129116

130117
#endif

templates/src/diagnostic.c.erb

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "prism/diagnostic.h"
2+
#include "prism/util/pm_arena.h"
23

34
#define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %>
45

@@ -451,29 +452,26 @@ pm_diagnostic_level(pm_diagnostic_id_t diag_id) {
451452
/**
452453
* Append an error to the given list of diagnostic.
453454
*/
454-
bool
455-
pm_diagnostic_list_append(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) {
456-
pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) xcalloc(1, sizeof(pm_diagnostic_t));
457-
if (diagnostic == NULL) return false;
455+
void
456+
pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) {
457+
pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) pm_arena_zalloc(arena, sizeof(pm_diagnostic_t), PRISM_ALIGNOF(pm_diagnostic_t));
458458

459459
*diagnostic = (pm_diagnostic_t) {
460460
.location = { .start = start, .length = length },
461461
.diag_id = diag_id,
462462
.message = pm_diagnostic_message(diag_id),
463-
.owned = false,
464463
.level = pm_diagnostic_level(diag_id)
465464
};
466465

467466
pm_list_append(list, (pm_list_node_t *) diagnostic);
468-
return true;
469467
}
470468

471469
/**
472470
* Append a diagnostic to the given list of diagnostics that is using a format
473471
* string for its message.
474472
*/
475-
bool
476-
pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...) {
473+
void
474+
pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...) {
477475
va_list arguments;
478476
va_start(arguments, diag_id);
479477

@@ -482,20 +480,13 @@ pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t lengt
482480
va_end(arguments);
483481

484482
if (result < 0) {
485-
return false;
483+
return;
486484
}
487485

488-
pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) xcalloc(1, sizeof(pm_diagnostic_t));
489-
if (diagnostic == NULL) {
490-
return false;
491-
}
486+
pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) pm_arena_zalloc(arena, sizeof(pm_diagnostic_t), PRISM_ALIGNOF(pm_diagnostic_t));
492487

493488
size_t message_length = (size_t) (result + 1);
494-
char *message = (char *) xmalloc(message_length);
495-
if (message == NULL) {
496-
xfree_sized(diagnostic, sizeof(pm_diagnostic_t));
497-
return false;
498-
}
489+
char *message = (char *) pm_arena_alloc(arena, message_length, 1);
499490

500491
va_start(arguments, diag_id);
501492
vsnprintf(message, message_length, format, arguments);
@@ -505,27 +496,9 @@ pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t lengt
505496
.location = { .start = start, .length = length },
506497
.diag_id = diag_id,
507498
.message = message,
508-
.owned = true,
509499
.level = pm_diagnostic_level(diag_id)
510500
};
511501

512502
pm_list_append(list, (pm_list_node_t *) diagnostic);
513-
return true;
514503
}
515504

516-
/**
517-
* Deallocate the internal state of the given diagnostic list.
518-
*/
519-
void
520-
pm_diagnostic_list_free(pm_list_t *list) {
521-
pm_diagnostic_t *node = (pm_diagnostic_t *) list->head;
522-
523-
while (node != NULL) {
524-
pm_diagnostic_t *next = (pm_diagnostic_t *) node->node.next;
525-
526-
if (node->owned) xfree((void *) node->message);
527-
xfree_sized(node, sizeof(pm_diagnostic_t));
528-
529-
node = next;
530-
}
531-
}

0 commit comments

Comments
 (0)