[ruby/prism] Match existing Ruby prettyprint
https://github.com/ruby/prism/commit/6d8358c083
This commit is contained in:
parent
e9aa2398b9
commit
d1bb858d47
@ -16,16 +16,32 @@ module Prism
|
||||
source.byteslice(offset, length)
|
||||
end
|
||||
|
||||
# Binary search through the offsets to find the line number for the given
|
||||
# offset.
|
||||
def line(value)
|
||||
offsets.bsearch_index { |offset| offset > value } || offsets.length
|
||||
left = 0
|
||||
right = offsets.length - 1
|
||||
|
||||
while left <= right
|
||||
mid = left + (right - left) / 2
|
||||
return mid if offsets[mid] == value
|
||||
|
||||
if offsets[mid] < value
|
||||
left = mid + 1
|
||||
else
|
||||
right = mid - 1
|
||||
end
|
||||
end
|
||||
|
||||
left - 1
|
||||
end
|
||||
|
||||
def line_offset(value)
|
||||
offsets[line(value) - 1]
|
||||
offsets[line(value)]
|
||||
end
|
||||
|
||||
def column(value)
|
||||
value - offsets[line(value) - 1]
|
||||
value - offsets[line(value)]
|
||||
end
|
||||
|
||||
private
|
||||
@ -86,7 +102,7 @@ module Prism
|
||||
|
||||
# The line number where this location starts.
|
||||
def start_line
|
||||
source.line(start_offset)
|
||||
source.line(start_offset) + 1
|
||||
end
|
||||
|
||||
# The content of the line where this location starts before this location.
|
||||
@ -97,7 +113,7 @@ module Prism
|
||||
|
||||
# The line number where this location ends.
|
||||
def end_line
|
||||
source.line(end_offset - 1)
|
||||
source.line(end_offset) + 1
|
||||
end
|
||||
|
||||
# The column number in bytes where this location starts from the start of
|
||||
|
@ -554,8 +554,10 @@ parse_serialize_file_metadata(VALUE self, VALUE filepath, VALUE metadata) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Inspect the AST that represents the given source using the prism pretty print
|
||||
// as opposed to the Ruby implementation.
|
||||
static VALUE
|
||||
rb_prism_debug_inspect_node(VALUE self, VALUE source) {
|
||||
inspect_node(VALUE self, VALUE source) {
|
||||
pm_string_t input;
|
||||
input_load_string(&input, source);
|
||||
|
||||
@ -565,8 +567,10 @@ rb_prism_debug_inspect_node(VALUE self, VALUE source) {
|
||||
pm_node_t *node = pm_parse(&parser);
|
||||
pm_buffer_t buffer = { 0 };
|
||||
|
||||
pm_prettyprint(&parser, node, &buffer);
|
||||
VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer));
|
||||
pm_prettyprint(&buffer, &parser, node);
|
||||
|
||||
rb_encoding *encoding = rb_enc_find(parser.encoding.name);
|
||||
VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
|
||||
|
||||
pm_buffer_free(&buffer);
|
||||
pm_node_destroy(&parser, node);
|
||||
@ -627,8 +631,7 @@ Init_prism(void) {
|
||||
rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1);
|
||||
rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
|
||||
rb_define_singleton_method(rb_cPrismDebug, "parse_serialize_file_metadata", parse_serialize_file_metadata, 2);
|
||||
|
||||
rb_define_singleton_method(rb_cPrismDebug, "inspect_node", rb_prism_debug_inspect_node, 1);
|
||||
rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1);
|
||||
|
||||
// Next, initialize the other APIs.
|
||||
Init_prism_api_node();
|
||||
|
15
prism/prettyprint.h
Normal file
15
prism/prettyprint.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef PRISM_PRETTYPRINT_H
|
||||
#define PRISM_PRETTYPRINT_H
|
||||
|
||||
#include "prism/defines.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "prism/ast.h"
|
||||
#include "prism/parser.h"
|
||||
#include "prism/util/pm_buffer.h"
|
||||
|
||||
// Pretty-prints the AST represented by the given node to the given buffer.
|
||||
PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node);
|
||||
|
||||
#endif
|
@ -2,16 +2,17 @@
|
||||
#define PRISM_H
|
||||
|
||||
#include "prism/defines.h"
|
||||
#include "prism/util/pm_buffer.h"
|
||||
#include "prism/util/pm_char.h"
|
||||
#include "prism/util/pm_memchr.h"
|
||||
#include "prism/util/pm_strpbrk.h"
|
||||
#include "prism/ast.h"
|
||||
#include "prism/diagnostic.h"
|
||||
#include "prism/node.h"
|
||||
#include "prism/pack.h"
|
||||
#include "prism/parser.h"
|
||||
#include "prism/prettyprint.h"
|
||||
#include "prism/regexp.h"
|
||||
#include "prism/util/pm_buffer.h"
|
||||
#include "prism/util/pm_char.h"
|
||||
#include "prism/util/pm_memchr.h"
|
||||
#include "prism/util/pm_strpbrk.h"
|
||||
#include "prism/version.h"
|
||||
|
||||
#include <assert.h>
|
||||
@ -29,8 +30,6 @@
|
||||
|
||||
void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
|
||||
|
||||
void pm_print_node(pm_parser_t *parser, pm_node_t *node);
|
||||
|
||||
void pm_parser_metadata(pm_parser_t *parser, const char *metadata);
|
||||
|
||||
// The prism version and the serialization format.
|
||||
@ -56,9 +55,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
|
||||
// Parse the Ruby source associated with the given parser and return the tree.
|
||||
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser);
|
||||
|
||||
// Pretty-prints the AST represented by the given node to the given buffer.
|
||||
PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
|
||||
|
||||
// Serialize the AST represented by the given node to the given buffer.
|
||||
PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
|
||||
|
||||
|
@ -179,8 +179,14 @@ module Prism
|
||||
inspector << "<%= pointer %><%= field.name %>:\n"
|
||||
inspector << <%= field.name %>.inspect(inspector.child_inspector("<%= preadd %>")).delete_prefix(inspector.prefix)
|
||||
end
|
||||
<%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::StringField, Prism::UInt32Field -%>
|
||||
<%- when Prism::ConstantField, Prism::StringField, Prism::UInt32Field -%>
|
||||
inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
|
||||
<%- when Prism::OptionalConstantField -%>
|
||||
if (<%= field.name %> = self.<%= field.name %>).nil?
|
||||
inspector << "<%= pointer %><%= field.name %>: ∅\n"
|
||||
else
|
||||
inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
|
||||
end
|
||||
<%- when Prism::FlagsField -%>
|
||||
<%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise unless flag } -%>
|
||||
flags = [<%= flag.values.map { |value| "(\"#{value.name.downcase}\" if #{value.name.downcase}?)" }.join(", ") %>].compact
|
||||
|
@ -7,27 +7,67 @@
|
||||
#include "prism/util/pm_buffer.h"
|
||||
|
||||
static void
|
||||
prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *node, pm_buffer_t *prefix_buffer);
|
||||
prettyprint_source(pm_buffer_t *output_buffer, const uint8_t *source, size_t length) {
|
||||
for (size_t index = 0; index < length; index++) {
|
||||
const uint8_t byte = source[index];
|
||||
|
||||
static void
|
||||
prettyprint_location(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_location_t *location) {
|
||||
char printed[] = "[0000-0000]";
|
||||
snprintf(printed, sizeof(printed), "[%04ld-%04ld]", (long int) (location->start - parser->start), (long int) (location->end - parser->start));
|
||||
pm_buffer_append_string(output_buffer, printed, strlen(printed));
|
||||
if ((byte <= 0x06) || (byte >= 0x0E && byte <= 0x1F) || (byte >= 0x7F)) {
|
||||
pm_buffer_append_format(output_buffer, "\\x%02X", byte);
|
||||
} else {
|
||||
switch (byte) {
|
||||
case '\a': pm_buffer_append_string(output_buffer, "\\a", 2); break;
|
||||
case '\b': pm_buffer_append_string(output_buffer, "\\b", 2); break;
|
||||
case '\t': pm_buffer_append_string(output_buffer, "\\t", 2); break;
|
||||
case '\n': pm_buffer_append_string(output_buffer, "\\n", 2); break;
|
||||
case '\v': pm_buffer_append_string(output_buffer, "\\v", 2); break;
|
||||
case '\f': pm_buffer_append_string(output_buffer, "\\f", 2); break;
|
||||
case '\r': pm_buffer_append_string(output_buffer, "\\r", 2); break;
|
||||
case '"': pm_buffer_append_string(output_buffer, "\\\"", 2); break;
|
||||
case '#': {
|
||||
if (index + 1 < length) {
|
||||
const uint8_t next_byte = source[index + 1];
|
||||
if (next_byte == '{' || next_byte == '@' || next_byte == '$') {
|
||||
pm_buffer_append_byte(output_buffer, '\\');
|
||||
}
|
||||
}
|
||||
|
||||
pm_buffer_append_byte(output_buffer, '#');
|
||||
break;
|
||||
}
|
||||
case '\\': pm_buffer_append_string(output_buffer, "\\\\", 2); break;
|
||||
default: pm_buffer_append_byte(output_buffer, byte); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) {
|
||||
pm_line_column_t start = pm_newline_list_line_column(&parser->newline_list, location->start);
|
||||
pm_line_column_t end = pm_newline_list_line_column(&parser->newline_list, location->end);
|
||||
pm_buffer_append_format(output_buffer, "(%d,%d)-(%d,%d)", start.line + 1, start.column, end.line + 1, end.column);
|
||||
}
|
||||
|
||||
static inline void
|
||||
prettyprint_constant(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_constant_id_t constant_id) {
|
||||
pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
|
||||
pm_buffer_append_format(output_buffer, ":%.*s", (int) constant->length, constant->start);
|
||||
}
|
||||
|
||||
static void
|
||||
prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *node, pm_buffer_t *prefix_buffer) {
|
||||
prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, const pm_node_t *node, pm_buffer_t *prefix_buffer) {
|
||||
switch (PM_NODE_TYPE(node)) {
|
||||
case PM_SCOPE_NODE:
|
||||
// We do not need to print a ScopeNode as it's not part of the AST.
|
||||
return;
|
||||
<%- nodes.each do |node| -%>
|
||||
case <%= node.type %>: {
|
||||
<%- if node.fields.any? { |field| !field.is_a?(Prism::FlagsField) } -%>
|
||||
<%- if node.fields.any? -%>
|
||||
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
|
||||
<%- end -%>
|
||||
pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ()-())\n", <%= node.name.length + 21 %>);
|
||||
pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ", <%= node.name.length + 14 %>);
|
||||
prettyprint_location(output_buffer, parser, &node->location);
|
||||
pm_buffer_append_string(output_buffer, ")\n", 2);
|
||||
<%- node.fields.each_with_index do |field, index| -%>
|
||||
<%- pointer, preadd = index == node.fields.length - 1 ? ["└── ", " "] : ["├── ", "│ "] -%>
|
||||
|
||||
@ -58,17 +98,18 @@ prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *nod
|
||||
}
|
||||
<%- when Prism::StringField -%>
|
||||
pm_buffer_append_string(output_buffer, " \"", 2);
|
||||
pm_buffer_append_bytes(output_buffer, pm_string_source(&cast-><%= field.name %>), pm_string_length(&cast-><%= field.name %>));
|
||||
prettyprint_source(output_buffer, pm_string_source(&cast-><%= field.name %>), pm_string_length(&cast-><%= field.name %>));
|
||||
pm_buffer_append_string(output_buffer, "\"\n", 2);
|
||||
<%- when Prism::NodeListField -%>
|
||||
pm_buffer_append_string(output_buffer, " (length: )\n", 13);
|
||||
size_t last_index = cast-><%= field.name %>.size - 1;
|
||||
for (uint32_t index = 0; index <= last_index; index++) {
|
||||
pm_buffer_append_format(output_buffer, " (length: %d)\n", cast-><%= field.name %>.size);
|
||||
|
||||
size_t last_index = cast-><%= field.name %>.size;
|
||||
for (uint32_t index = 0; index < last_index; index++) {
|
||||
size_t prefix_length = prefix_buffer->length;
|
||||
pm_buffer_append_string(prefix_buffer, " ", 4);
|
||||
pm_buffer_append_string(prefix_buffer, "<%= preadd %>", <%= preadd.bytesize %>);
|
||||
pm_buffer_concat(output_buffer, prefix_buffer);
|
||||
|
||||
if (index == last_index) {
|
||||
if (index == last_index - 1) {
|
||||
pm_buffer_append_string(output_buffer, "└── ", 10);
|
||||
pm_buffer_append_string(prefix_buffer, " ", 4);
|
||||
} else {
|
||||
@ -79,55 +120,56 @@ prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *nod
|
||||
prettyprint_node(output_buffer, parser, (pm_node_t *) cast-><%= field.name %>.nodes[index], prefix_buffer);
|
||||
prefix_buffer->length = prefix_length;
|
||||
}
|
||||
pm_buffer_append_string(output_buffer, "\n", 1);
|
||||
<%- when Prism::ConstantField -%>
|
||||
char <%= field.name %>_buffer[12];
|
||||
snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "%u", cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, ' ');
|
||||
pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
|
||||
prettyprint_constant(output_buffer, parser, cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, '\n');
|
||||
<%- when Prism::OptionalConstantField -%>
|
||||
if (cast-><%= field.name %> == 0) {
|
||||
pm_buffer_append_string(output_buffer, " ∅\n", 5);
|
||||
} else {
|
||||
char <%= field.name %>_buffer[12];
|
||||
snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "%u", cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, ' ');
|
||||
pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
|
||||
prettyprint_constant(output_buffer, parser, cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, '\n');
|
||||
}
|
||||
<%- when Prism::ConstantListField -%>
|
||||
pm_buffer_append_string(output_buffer, " [", 2);
|
||||
for (uint32_t index = 0; index < cast-><%= field.name %>.size; index++) {
|
||||
if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2);
|
||||
char <%= field.name %>_buffer[12];
|
||||
snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "%u", cast-><%= field.name %>.ids[index]);
|
||||
pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
|
||||
prettyprint_constant(output_buffer, parser, cast-><%= field.name %>.ids[index]);
|
||||
}
|
||||
pm_buffer_append_string(output_buffer, "]\n", 2);
|
||||
<%- when Prism::LocationField -%>
|
||||
pm_location_t *location = &cast-><%= field.name %>;
|
||||
pm_buffer_append_byte(output_buffer, ' ');
|
||||
prettyprint_location(output_buffer, parser, &cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, '\n');
|
||||
prettyprint_location(output_buffer, parser, location);
|
||||
pm_buffer_append_string(output_buffer, " = \"", 4);
|
||||
prettyprint_source(output_buffer, location->start, (size_t) (location->end - location->start));
|
||||
pm_buffer_append_string(output_buffer, "\"\n", 2);
|
||||
<%- when Prism::OptionalLocationField -%>
|
||||
if (cast-><%= field.name %>.start == NULL) {
|
||||
pm_location_t *location = &cast-><%= field.name %>;
|
||||
if (location->start == NULL) {
|
||||
pm_buffer_append_string(output_buffer, " ∅\n", 5);
|
||||
} else {
|
||||
pm_buffer_append_byte(output_buffer, ' ');
|
||||
prettyprint_location(output_buffer, parser, &cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, '\n');
|
||||
prettyprint_location(output_buffer, parser, location);
|
||||
pm_buffer_append_string(output_buffer, " = \"", 4);
|
||||
prettyprint_source(output_buffer, location->start, (size_t) (location->end - location->start));
|
||||
pm_buffer_append_string(output_buffer, "\"\n", 2);
|
||||
}
|
||||
<%- when Prism::UInt32Field -%>
|
||||
char <%= field.name %>_buffer[12];
|
||||
snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "+%d", cast-><%= field.name %>);
|
||||
pm_buffer_append_byte(output_buffer, ' ');
|
||||
pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
|
||||
pm_buffer_append_byte(output_buffer, '\n');
|
||||
pm_buffer_append_format(output_buffer, " %d\n", cast-><%= field.name %>);
|
||||
<%- when Prism::FlagsField -%>
|
||||
char <%= field.name %>_buffer[12];
|
||||
snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK));
|
||||
pm_buffer_append_byte(output_buffer, ' ');
|
||||
pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
|
||||
bool found = false;
|
||||
<%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%>
|
||||
<%- found.values.each do |value| -%>
|
||||
if (cast->base.<%= field.name %> & PM_<%= found.human.upcase %>_<%= value.name %>) {
|
||||
if (found) pm_buffer_append_byte(output_buffer, ',');
|
||||
pm_buffer_append_string(output_buffer, " <%= value.name.downcase %>", <%= value.name.bytesize + 1 %>);
|
||||
found = true;
|
||||
}
|
||||
<%- end -%>
|
||||
if (!found) pm_buffer_append_string(output_buffer, " ∅", 4);
|
||||
pm_buffer_append_byte(output_buffer, '\n');
|
||||
<%- else -%>
|
||||
<%- raise -%>
|
||||
@ -141,21 +183,9 @@ prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *nod
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pm_print_node(pm_parser_t *parser, pm_node_t *node) {
|
||||
pm_buffer_t output_buffer = { 0 };
|
||||
pm_buffer_t prefix_buffer = { 0 };
|
||||
|
||||
prettyprint_node(&output_buffer, parser, node, &prefix_buffer);
|
||||
printf("%.*s\n", (int) output_buffer.length, output_buffer.value);
|
||||
|
||||
pm_buffer_free(&output_buffer);
|
||||
pm_buffer_free(&prefix_buffer);
|
||||
}
|
||||
|
||||
// Pretty-prints the AST represented by the given node to the given buffer.
|
||||
PRISM_EXPORTED_FUNCTION void
|
||||
pm_prettyprint(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *output_buffer) {
|
||||
pm_prettyprint(pm_buffer_t *output_buffer, pm_parser_t *parser, const pm_node_t *node) {
|
||||
pm_buffer_t prefix_buffer = { 0 };
|
||||
prettyprint_node(output_buffer, parser, node, &prefix_buffer);
|
||||
pm_buffer_free(&prefix_buffer);
|
||||
|
@ -70,6 +70,27 @@ pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length) {
|
||||
memset(buffer->value + cursor, 0, length);
|
||||
}
|
||||
|
||||
// Append a formatted string to the buffer.
|
||||
void
|
||||
pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...) {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
int result = vsnprintf(NULL, 0, format, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
if (result < 0) return;
|
||||
size_t length = (size_t) (result + 1);
|
||||
|
||||
size_t cursor = buffer->length;
|
||||
pm_buffer_append_length(buffer, length);
|
||||
|
||||
va_start(arguments, format);
|
||||
vsnprintf(buffer->value + cursor, length, format, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
buffer->length--;
|
||||
}
|
||||
|
||||
// Append a string to the buffer.
|
||||
void
|
||||
pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length) {
|
||||
|
@ -36,6 +36,9 @@ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(pm_buffer_t *buffer);
|
||||
// Append the given amount of space as zeroes to the buffer.
|
||||
void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length);
|
||||
|
||||
// Append a formatted string to the buffer.
|
||||
void pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...);
|
||||
|
||||
// Append a string to the buffer.
|
||||
void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length);
|
||||
|
||||
|
@ -156,7 +156,7 @@ pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity) {
|
||||
|
||||
// Return a pointer to the constant indicated by the given constant id.
|
||||
pm_constant_t *
|
||||
pm_constant_pool_id_to_constant(pm_constant_pool_t *pool, pm_constant_id_t constant_id) {
|
||||
pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id) {
|
||||
assert(constant_id > 0 && constant_id <= pool->size);
|
||||
return &pool->constants[constant_id - 1];
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ typedef struct {
|
||||
bool pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity);
|
||||
|
||||
// Return a pointer to the constant indicated by the given constant id.
|
||||
pm_constant_t * pm_constant_pool_id_to_constant(pm_constant_pool_t *pool, pm_constant_id_t constant_id);
|
||||
pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id);
|
||||
|
||||
// Insert a constant into a constant pool that is a slice of a source string.
|
||||
// Returns the id of the constant, or 0 if any potential calls to resize fail.
|
||||
|
@ -53,10 +53,14 @@ pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor) {
|
||||
return pm_newline_list_append(list, cursor);
|
||||
}
|
||||
|
||||
// Returns the line and column of the given offset, assuming we don't have any
|
||||
// information about the previous index that we found.
|
||||
static pm_line_column_t
|
||||
pm_newline_list_line_column_search(pm_newline_list_t *list, size_t offset) {
|
||||
// Returns the line and column of the given offset. If the offset is not in the
|
||||
// list, the line and column of the closest offset less than the given offset
|
||||
// are returned.
|
||||
pm_line_column_t
|
||||
pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor) {
|
||||
assert(cursor >= list->start);
|
||||
size_t offset = (size_t) (cursor - list->start);
|
||||
|
||||
size_t left = 0;
|
||||
size_t right = list->size - 1;
|
||||
|
||||
@ -77,56 +81,6 @@ pm_newline_list_line_column_search(pm_newline_list_t *list, size_t offset) {
|
||||
return ((pm_line_column_t) { left - 1, offset - list->offsets[left - 1] });
|
||||
}
|
||||
|
||||
// Returns the line and column of the given offset, assuming we know the last
|
||||
// index that we found.
|
||||
static pm_line_column_t
|
||||
pm_newline_list_line_column_scan(pm_newline_list_t *list, size_t offset) {
|
||||
if (offset > list->last_offset) {
|
||||
size_t index = list->last_index;
|
||||
while (index < list->size && list->offsets[index] < offset) {
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index == list->size) {
|
||||
return ((pm_line_column_t) { index - 1, offset - list->offsets[index - 1] });
|
||||
}
|
||||
|
||||
return ((pm_line_column_t) { index, 0 });
|
||||
} else {
|
||||
size_t index = list->last_index;
|
||||
while (index > 0 && list->offsets[index] > offset) {
|
||||
index--;
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
return ((pm_line_column_t) { 0, offset });
|
||||
}
|
||||
|
||||
return ((pm_line_column_t) { index, offset - list->offsets[index - 1] });
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the line and column of the given offset. If the offset is not in the
|
||||
// list, the line and column of the closest offset less than the given offset
|
||||
// are returned.
|
||||
pm_line_column_t
|
||||
pm_newline_list_line_column(pm_newline_list_t *list, const uint8_t *cursor) {
|
||||
assert(cursor >= list->start);
|
||||
size_t offset = (size_t) (cursor - list->start);
|
||||
pm_line_column_t result;
|
||||
|
||||
if (list->last_offset == 0) {
|
||||
result = pm_newline_list_line_column_search(list, offset);
|
||||
} else {
|
||||
result = pm_newline_list_line_column_scan(list, offset);
|
||||
}
|
||||
|
||||
list->last_index = result.line;
|
||||
list->last_offset = offset;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Free the internal memory allocated for the newline list.
|
||||
void
|
||||
pm_newline_list_free(pm_newline_list_t *list) {
|
||||
|
@ -53,7 +53,7 @@ bool pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor
|
||||
// Returns the line and column of the given offset. If the offset is not in the
|
||||
// list, the line and column of the closest offset less than the given offset
|
||||
// are returned.
|
||||
pm_line_column_t pm_newline_list_line_column(pm_newline_list_t *list, const uint8_t *cursor);
|
||||
pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor);
|
||||
|
||||
// Free the internal memory allocated for the newline list.
|
||||
void pm_newline_list_free(pm_newline_list_t *list);
|
||||
|
Loading…
x
Reference in New Issue
Block a user